blob: 06c1c931578cfaf05f33c9c759506866ecceffc3 [file] [log] [blame]
Douglas Gregor81b747b2009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
John McCall2d887082010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.h"
Douglas Gregore737f502010-08-12 20:07:10 +000014#include "clang/Sema/Lookup.h"
John McCall120d63c2010-08-24 20:38:10 +000015#include "clang/Sema/Overload.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000016#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregor719770d2010-04-06 17:30:22 +000017#include "clang/Sema/ExternalSemaSource.h"
John McCall5f1e0942010-08-24 08:50:51 +000018#include "clang/Sema/Scope.h"
John McCall781472f2010-08-25 08:40:02 +000019#include "clang/Sema/ScopeInfo.h"
John McCall7cd088e2010-08-24 07:21:54 +000020#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000021#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000022#include "clang/AST/ExprObjC.h"
Douglas Gregorc5b2e582012-01-29 18:15:03 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000024#include "clang/Lex/MacroInfo.h"
25#include "clang/Lex/Preprocessor.h"
Douglas Gregord36adf52010-09-16 16:06:31 +000026#include "llvm/ADT/DenseSet.h"
Benjamin Kramer013b3662012-01-30 16:17:39 +000027#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000028#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer8fe83e12012-02-04 13:45:25 +000029#include "llvm/ADT/SmallString.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000030#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000031#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000032#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000033#include <list>
34#include <map>
35#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000036
37using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000038using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000039
Douglas Gregor86d9a522009-09-21 16:56:56 +000040namespace {
41 /// \brief A container of code-completion results.
42 class ResultBuilder {
43 public:
44 /// \brief The type of a name-lookup filter, which can be provided to the
45 /// name-lookup routines to specify which declarations should be included in
46 /// the result set (when it returns true) and which declarations should be
47 /// filtered out (returns false).
48 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
49
John McCall0a2c5e22010-08-25 06:19:51 +000050 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000051
52 private:
53 /// \brief The actual results we have found.
54 std::vector<Result> Results;
55
56 /// \brief A record of all of the declarations we have found and placed
57 /// into the result set, used to ensure that no declaration ever gets into
58 /// the result set twice.
59 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
60
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000061 typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
62
63 /// \brief An entry in the shadow map, which is optimized to store
64 /// a single (declaration, index) mapping (the common case) but
65 /// can also store a list of (declaration, index) mappings.
66 class ShadowMapEntry {
Chris Lattner5f9e2722011-07-23 10:55:15 +000067 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000068
69 /// \brief Contains either the solitary NamedDecl * or a vector
70 /// of (declaration, index) pairs.
71 llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
72
73 /// \brief When the entry contains a single declaration, this is
74 /// the index associated with that entry.
75 unsigned SingleDeclIndex;
76
77 public:
78 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
79
80 void Add(NamedDecl *ND, unsigned Index) {
81 if (DeclOrVector.isNull()) {
82 // 0 - > 1 elements: just set the single element information.
83 DeclOrVector = ND;
84 SingleDeclIndex = Index;
85 return;
86 }
87
88 if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
89 // 1 -> 2 elements: create the vector of results and push in the
90 // existing declaration.
91 DeclIndexPairVector *Vec = new DeclIndexPairVector;
92 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
93 DeclOrVector = Vec;
94 }
95
96 // Add the new element to the end of the vector.
97 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
98 DeclIndexPair(ND, Index));
99 }
100
101 void Destroy() {
102 if (DeclIndexPairVector *Vec
103 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
104 delete Vec;
105 DeclOrVector = ((NamedDecl *)0);
106 }
107 }
108
109 // Iteration.
110 class iterator;
111 iterator begin() const;
112 iterator end() const;
113 };
114
Douglas Gregor86d9a522009-09-21 16:56:56 +0000115 /// \brief A mapping from declaration names to the declarations that have
116 /// this name within a particular scope and their index within the list of
117 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000118 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000119
120 /// \brief The semantic analysis object for which results are being
121 /// produced.
122 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000123
124 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000125 CodeCompletionAllocator &Allocator;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000126
127 /// \brief If non-NULL, a filter function used to remove any code-completion
128 /// results that are not desirable.
129 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000130
131 /// \brief Whether we should allow declarations as
132 /// nested-name-specifiers that would otherwise be filtered out.
133 bool AllowNestedNameSpecifiers;
134
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000135 /// \brief If set, the type that we would prefer our resulting value
136 /// declarations to have.
137 ///
138 /// Closely matching the preferred type gives a boost to a result's
139 /// priority.
140 CanQualType PreferredType;
141
Douglas Gregor86d9a522009-09-21 16:56:56 +0000142 /// \brief A list of shadow maps, which is used to model name hiding at
143 /// different levels of, e.g., the inheritance hierarchy.
144 std::list<ShadowMap> ShadowMaps;
145
Douglas Gregor3cdee122010-08-26 16:36:48 +0000146 /// \brief If we're potentially referring to a C++ member function, the set
147 /// of qualifiers applied to the object type.
148 Qualifiers ObjectTypeQualifiers;
149
150 /// \brief Whether the \p ObjectTypeQualifiers field is active.
151 bool HasObjectTypeQualifiers;
152
Douglas Gregor265f7492010-08-27 15:29:55 +0000153 /// \brief The selector that we prefer.
154 Selector PreferredSelector;
155
Douglas Gregorca45da02010-11-02 20:36:02 +0000156 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000157 CodeCompletionContext CompletionContext;
158
Douglas Gregorca45da02010-11-02 20:36:02 +0000159 /// \brief If we are in an instance method definition, the @implementation
160 /// object.
161 ObjCImplementationDecl *ObjCImplementation;
162
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000163 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000164
Douglas Gregor6f942b22010-09-21 16:06:22 +0000165 void MaybeAddConstructorResults(Result R);
166
Douglas Gregor86d9a522009-09-21 16:56:56 +0000167 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000168 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000169 const CodeCompletionContext &CompletionContext,
170 LookupFilter Filter = 0)
Douglas Gregor218937c2011-02-01 19:23:04 +0000171 : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
172 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000173 CompletionContext(CompletionContext),
174 ObjCImplementation(0)
175 {
176 // If this is an Objective-C instance method definition, dig out the
177 // corresponding implementation.
178 switch (CompletionContext.getKind()) {
179 case CodeCompletionContext::CCC_Expression:
180 case CodeCompletionContext::CCC_ObjCMessageReceiver:
181 case CodeCompletionContext::CCC_ParenthesizedExpression:
182 case CodeCompletionContext::CCC_Statement:
183 case CodeCompletionContext::CCC_Recovery:
184 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
185 if (Method->isInstanceMethod())
186 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
187 ObjCImplementation = Interface->getImplementation();
188 break;
189
190 default:
191 break;
192 }
193 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000194
Douglas Gregord8e8a582010-05-25 21:41:55 +0000195 /// \brief Whether we should include code patterns in the completion
196 /// results.
197 bool includeCodePatterns() const {
198 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000199 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000200 }
201
Douglas Gregor86d9a522009-09-21 16:56:56 +0000202 /// \brief Set the filter used for code-completion results.
203 void setFilter(LookupFilter Filter) {
204 this->Filter = Filter;
205 }
206
Douglas Gregor86d9a522009-09-21 16:56:56 +0000207 Result *data() { return Results.empty()? 0 : &Results.front(); }
208 unsigned size() const { return Results.size(); }
209 bool empty() const { return Results.empty(); }
210
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000211 /// \brief Specify the preferred type.
212 void setPreferredType(QualType T) {
213 PreferredType = SemaRef.Context.getCanonicalType(T);
214 }
215
Douglas Gregor3cdee122010-08-26 16:36:48 +0000216 /// \brief Set the cv-qualifiers on the object type, for us in filtering
217 /// calls to member functions.
218 ///
219 /// When there are qualifiers in this set, they will be used to filter
220 /// out member functions that aren't available (because there will be a
221 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
222 /// match.
223 void setObjectTypeQualifiers(Qualifiers Quals) {
224 ObjectTypeQualifiers = Quals;
225 HasObjectTypeQualifiers = true;
226 }
227
Douglas Gregor265f7492010-08-27 15:29:55 +0000228 /// \brief Set the preferred selector.
229 ///
230 /// When an Objective-C method declaration result is added, and that
231 /// method's selector matches this preferred selector, we give that method
232 /// a slight priority boost.
233 void setPreferredSelector(Selector Sel) {
234 PreferredSelector = Sel;
235 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000236
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000237 /// \brief Retrieve the code-completion context for which results are
238 /// being collected.
239 const CodeCompletionContext &getCompletionContext() const {
240 return CompletionContext;
241 }
242
Douglas Gregor45bcd432010-01-14 03:21:49 +0000243 /// \brief Specify whether nested-name-specifiers are allowed.
244 void allowNestedNameSpecifiers(bool Allow = true) {
245 AllowNestedNameSpecifiers = Allow;
246 }
247
Douglas Gregorb9d77572010-09-21 00:03:25 +0000248 /// \brief Return the semantic analysis object for which we are collecting
249 /// code completion results.
250 Sema &getSema() const { return SemaRef; }
251
Douglas Gregor218937c2011-02-01 19:23:04 +0000252 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000253 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000254
Douglas Gregore495b7f2010-01-14 00:20:49 +0000255 /// \brief Determine whether the given declaration is at all interesting
256 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000257 ///
258 /// \param ND the declaration that we are inspecting.
259 ///
260 /// \param AsNestedNameSpecifier will be set true if this declaration is
261 /// only interesting when it is a nested-name-specifier.
262 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000263
264 /// \brief Check whether the result is hidden by the Hiding declaration.
265 ///
266 /// \returns true if the result is hidden and cannot be found, false if
267 /// the hidden result could still be found. When false, \p R may be
268 /// modified to describe how the result can be found (e.g., via extra
269 /// qualification).
270 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
271 NamedDecl *Hiding);
272
Douglas Gregor86d9a522009-09-21 16:56:56 +0000273 /// \brief Add a new result to this result set (if it isn't already in one
274 /// of the shadow maps), or replace an existing result (for, e.g., a
275 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000276 ///
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000277 /// \param CurContext the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000278 ///
279 /// \param R the context in which this result will be named.
280 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000281
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000282 /// \brief Add a new result to this result set, where we already know
283 /// the hiding declation (if any).
284 ///
285 /// \param R the result to add (if it is unique).
286 ///
287 /// \param CurContext the context in which this result will be named.
288 ///
289 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000290 ///
291 /// \param InBaseClass whether the result was found in a base
292 /// class of the searched context.
293 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
294 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000295
Douglas Gregora4477812010-01-14 16:01:26 +0000296 /// \brief Add a new non-declaration result to this result set.
297 void AddResult(Result R);
298
Douglas Gregor86d9a522009-09-21 16:56:56 +0000299 /// \brief Enter into a new scope.
300 void EnterNewScope();
301
302 /// \brief Exit from the current scope.
303 void ExitScope();
304
Douglas Gregor55385fe2009-11-18 04:19:12 +0000305 /// \brief Ignore this declaration, if it is seen again.
306 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
307
Douglas Gregor86d9a522009-09-21 16:56:56 +0000308 /// \name Name lookup predicates
309 ///
310 /// These predicates can be passed to the name lookup functions to filter the
311 /// results of name lookup. All of the predicates have the same type, so that
312 ///
313 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000314 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000315 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000316 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000317 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000318 bool IsNestedNameSpecifier(NamedDecl *ND) const;
319 bool IsEnum(NamedDecl *ND) const;
320 bool IsClassOrStruct(NamedDecl *ND) const;
321 bool IsUnion(NamedDecl *ND) const;
322 bool IsNamespace(NamedDecl *ND) const;
323 bool IsNamespaceOrAlias(NamedDecl *ND) const;
324 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000325 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000326 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000327 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000328 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000329 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000330 //@}
331 };
332}
333
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000334class ResultBuilder::ShadowMapEntry::iterator {
335 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
336 unsigned SingleDeclIndex;
337
338public:
339 typedef DeclIndexPair value_type;
340 typedef value_type reference;
341 typedef std::ptrdiff_t difference_type;
342 typedef std::input_iterator_tag iterator_category;
343
344 class pointer {
345 DeclIndexPair Value;
346
347 public:
348 pointer(const DeclIndexPair &Value) : Value(Value) { }
349
350 const DeclIndexPair *operator->() const {
351 return &Value;
352 }
353 };
354
355 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
356
357 iterator(NamedDecl *SingleDecl, unsigned Index)
358 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
359
360 iterator(const DeclIndexPair *Iterator)
361 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
362
363 iterator &operator++() {
364 if (DeclOrIterator.is<NamedDecl *>()) {
365 DeclOrIterator = (NamedDecl *)0;
366 SingleDeclIndex = 0;
367 return *this;
368 }
369
370 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
371 ++I;
372 DeclOrIterator = I;
373 return *this;
374 }
375
Chris Lattner66392d42010-09-04 18:12:20 +0000376 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000377 iterator tmp(*this);
378 ++(*this);
379 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000380 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000381
382 reference operator*() const {
383 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
384 return reference(ND, SingleDeclIndex);
385
Douglas Gregord490f952009-12-06 21:27:58 +0000386 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000387 }
388
389 pointer operator->() const {
390 return pointer(**this);
391 }
392
393 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000394 return X.DeclOrIterator.getOpaqueValue()
395 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000396 X.SingleDeclIndex == Y.SingleDeclIndex;
397 }
398
399 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000400 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000401 }
402};
403
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000404ResultBuilder::ShadowMapEntry::iterator
405ResultBuilder::ShadowMapEntry::begin() const {
406 if (DeclOrVector.isNull())
407 return iterator();
408
409 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
410 return iterator(ND, SingleDeclIndex);
411
412 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
413}
414
415ResultBuilder::ShadowMapEntry::iterator
416ResultBuilder::ShadowMapEntry::end() const {
417 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
418 return iterator();
419
420 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
421}
422
Douglas Gregor456c4a12009-09-21 20:12:40 +0000423/// \brief Compute the qualification required to get from the current context
424/// (\p CurContext) to the target context (\p TargetContext).
425///
426/// \param Context the AST context in which the qualification will be used.
427///
428/// \param CurContext the context where an entity is being named, which is
429/// typically based on the current scope.
430///
431/// \param TargetContext the context in which the named entity actually
432/// resides.
433///
434/// \returns a nested name specifier that refers into the target context, or
435/// NULL if no qualification is needed.
436static NestedNameSpecifier *
437getRequiredQualification(ASTContext &Context,
438 DeclContext *CurContext,
439 DeclContext *TargetContext) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000440 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000441
442 for (DeclContext *CommonAncestor = TargetContext;
443 CommonAncestor && !CommonAncestor->Encloses(CurContext);
444 CommonAncestor = CommonAncestor->getLookupParent()) {
445 if (CommonAncestor->isTransparentContext() ||
446 CommonAncestor->isFunctionOrMethod())
447 continue;
448
449 TargetParents.push_back(CommonAncestor);
450 }
451
452 NestedNameSpecifier *Result = 0;
453 while (!TargetParents.empty()) {
454 DeclContext *Parent = TargetParents.back();
455 TargetParents.pop_back();
456
Douglas Gregorfb629412010-08-23 21:17:50 +0000457 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
458 if (!Namespace->getIdentifier())
459 continue;
460
Douglas Gregor456c4a12009-09-21 20:12:40 +0000461 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000462 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000463 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
464 Result = NestedNameSpecifier::Create(Context, Result,
465 false,
466 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000467 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000468 return Result;
469}
470
Douglas Gregor45bcd432010-01-14 03:21:49 +0000471bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
472 bool &AsNestedNameSpecifier) const {
473 AsNestedNameSpecifier = false;
474
Douglas Gregore495b7f2010-01-14 00:20:49 +0000475 ND = ND->getUnderlyingDecl();
476 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000477
478 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000479 if (!ND->getDeclName())
480 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000481
482 // Friend declarations and declarations introduced due to friends are never
483 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000484 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000485 return false;
486
Douglas Gregor76282942009-12-11 17:31:05 +0000487 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000488 if (isa<ClassTemplateSpecializationDecl>(ND) ||
489 isa<ClassTemplatePartialSpecializationDecl>(ND))
490 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000491
Douglas Gregor76282942009-12-11 17:31:05 +0000492 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000493 if (isa<UsingDecl>(ND))
494 return false;
495
496 // Some declarations have reserved names that we don't want to ever show.
497 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000498 // __va_list_tag is a freak of nature. Find it and skip it.
499 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000500 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000501
Douglas Gregorf52cede2009-10-09 22:16:47 +0000502 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000503 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000504 //
505 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000506 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000507 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000508 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000509 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
510 (ND->getLocation().isInvalid() ||
511 SemaRef.SourceMgr.isInSystemHeader(
512 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000513 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000514 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000515 }
Douglas Gregor6f942b22010-09-21 16:06:22 +0000516
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000517 // Skip out-of-line declarations and definitions.
518 // NOTE: Unless it's an Objective-C property, method, or ivar, where
519 // the contexts can be messy.
520 if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) &&
521 !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) ||
522 isa<ObjCMethodDecl>(ND)))
523 return false;
524
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000525 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
526 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
527 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000528 Filter != &ResultBuilder::IsNamespaceOrAlias &&
529 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000530 AsNestedNameSpecifier = true;
531
Douglas Gregor86d9a522009-09-21 16:56:56 +0000532 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000533 if (Filter && !(this->*Filter)(ND)) {
534 // Check whether it is interesting as a nested-name-specifier.
535 if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus &&
536 IsNestedNameSpecifier(ND) &&
537 (Filter != &ResultBuilder::IsMember ||
538 (isa<CXXRecordDecl>(ND) &&
539 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
540 AsNestedNameSpecifier = true;
541 return true;
542 }
543
Douglas Gregore495b7f2010-01-14 00:20:49 +0000544 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000545 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000546 // ... then it must be interesting!
547 return true;
548}
549
Douglas Gregor6660d842010-01-14 00:41:07 +0000550bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
551 NamedDecl *Hiding) {
552 // In C, there is no way to refer to a hidden name.
553 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
554 // name if we introduce the tag type.
555 if (!SemaRef.getLangOptions().CPlusPlus)
556 return true;
557
Sebastian Redl7a126a42010-08-31 00:36:30 +0000558 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000559
560 // There is no way to qualify a name declared in a function or method.
561 if (HiddenCtx->isFunctionOrMethod())
562 return true;
563
Sebastian Redl7a126a42010-08-31 00:36:30 +0000564 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000565 return true;
566
567 // We can refer to the result with the appropriate qualification. Do it.
568 R.Hidden = true;
569 R.QualifierIsInformative = false;
570
571 if (!R.Qualifier)
572 R.Qualifier = getRequiredQualification(SemaRef.Context,
573 CurContext,
574 R.Declaration->getDeclContext());
575 return false;
576}
577
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000578/// \brief A simplified classification of types used to determine whether two
579/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000580SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000581 switch (T->getTypeClass()) {
582 case Type::Builtin:
583 switch (cast<BuiltinType>(T)->getKind()) {
584 case BuiltinType::Void:
585 return STC_Void;
586
587 case BuiltinType::NullPtr:
588 return STC_Pointer;
589
590 case BuiltinType::Overload:
591 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000592 return STC_Other;
593
594 case BuiltinType::ObjCId:
595 case BuiltinType::ObjCClass:
596 case BuiltinType::ObjCSel:
597 return STC_ObjectiveC;
598
599 default:
600 return STC_Arithmetic;
601 }
David Blaikie7530c032012-01-17 06:56:22 +0000602
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000603 case Type::Complex:
604 return STC_Arithmetic;
605
606 case Type::Pointer:
607 return STC_Pointer;
608
609 case Type::BlockPointer:
610 return STC_Block;
611
612 case Type::LValueReference:
613 case Type::RValueReference:
614 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
615
616 case Type::ConstantArray:
617 case Type::IncompleteArray:
618 case Type::VariableArray:
619 case Type::DependentSizedArray:
620 return STC_Array;
621
622 case Type::DependentSizedExtVector:
623 case Type::Vector:
624 case Type::ExtVector:
625 return STC_Arithmetic;
626
627 case Type::FunctionProto:
628 case Type::FunctionNoProto:
629 return STC_Function;
630
631 case Type::Record:
632 return STC_Record;
633
634 case Type::Enum:
635 return STC_Arithmetic;
636
637 case Type::ObjCObject:
638 case Type::ObjCInterface:
639 case Type::ObjCObjectPointer:
640 return STC_ObjectiveC;
641
642 default:
643 return STC_Other;
644 }
645}
646
647/// \brief Get the type that a given expression will have if this declaration
648/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000649QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000650 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
651
652 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
653 return C.getTypeDeclType(Type);
654 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
655 return C.getObjCInterfaceType(Iface);
656
657 QualType T;
658 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000659 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000660 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000661 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000662 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000663 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000664 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
665 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
666 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
667 T = Property->getType();
668 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
669 T = Value->getType();
670 else
671 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000672
673 // Dig through references, function pointers, and block pointers to
674 // get down to the likely type of an expression when the entity is
675 // used.
676 do {
677 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
678 T = Ref->getPointeeType();
679 continue;
680 }
681
682 if (const PointerType *Pointer = T->getAs<PointerType>()) {
683 if (Pointer->getPointeeType()->isFunctionType()) {
684 T = Pointer->getPointeeType();
685 continue;
686 }
687
688 break;
689 }
690
691 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
692 T = Block->getPointeeType();
693 continue;
694 }
695
696 if (const FunctionType *Function = T->getAs<FunctionType>()) {
697 T = Function->getResultType();
698 continue;
699 }
700
701 break;
702 } while (true);
703
704 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000705}
706
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000707void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
708 // If this is an Objective-C method declaration whose selector matches our
709 // preferred selector, give it a priority boost.
710 if (!PreferredSelector.isNull())
711 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
712 if (PreferredSelector == Method->getSelector())
713 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000714
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000715 // If we have a preferred type, adjust the priority for results with exactly-
716 // matching or nearly-matching types.
717 if (!PreferredType.isNull()) {
718 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
719 if (!T.isNull()) {
720 CanQualType TC = SemaRef.Context.getCanonicalType(T);
721 // Check for exactly-matching types (modulo qualifiers).
722 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
723 R.Priority /= CCF_ExactTypeMatch;
724 // Check for nearly-matching types, based on classification of each.
725 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000726 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000727 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
728 R.Priority /= CCF_SimilarTypeMatch;
729 }
730 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000731}
732
Douglas Gregor6f942b22010-09-21 16:06:22 +0000733void ResultBuilder::MaybeAddConstructorResults(Result R) {
734 if (!SemaRef.getLangOptions().CPlusPlus || !R.Declaration ||
735 !CompletionContext.wantConstructorResults())
736 return;
737
738 ASTContext &Context = SemaRef.Context;
739 NamedDecl *D = R.Declaration;
740 CXXRecordDecl *Record = 0;
741 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
742 Record = ClassTemplate->getTemplatedDecl();
743 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
744 // Skip specializations and partial specializations.
745 if (isa<ClassTemplateSpecializationDecl>(Record))
746 return;
747 } else {
748 // There are no constructors here.
749 return;
750 }
751
752 Record = Record->getDefinition();
753 if (!Record)
754 return;
755
756
757 QualType RecordTy = Context.getTypeDeclType(Record);
758 DeclarationName ConstructorName
759 = Context.DeclarationNames.getCXXConstructorName(
760 Context.getCanonicalType(RecordTy));
761 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
762 Ctors.first != Ctors.second; ++Ctors.first) {
763 R.Declaration = *Ctors.first;
764 R.CursorKind = getCursorKindForDecl(R.Declaration);
765 Results.push_back(R);
766 }
767}
768
Douglas Gregore495b7f2010-01-14 00:20:49 +0000769void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
770 assert(!ShadowMaps.empty() && "Must enter into a results scope");
771
772 if (R.Kind != Result::RK_Declaration) {
773 // For non-declaration results, just add the result.
774 Results.push_back(R);
775 return;
776 }
777
778 // Look through using declarations.
779 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
780 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
781 return;
782 }
783
784 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
785 unsigned IDNS = CanonDecl->getIdentifierNamespace();
786
Douglas Gregor45bcd432010-01-14 03:21:49 +0000787 bool AsNestedNameSpecifier = false;
788 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000789 return;
790
Douglas Gregor6f942b22010-09-21 16:06:22 +0000791 // C++ constructors are never found by name lookup.
792 if (isa<CXXConstructorDecl>(R.Declaration))
793 return;
794
Douglas Gregor86d9a522009-09-21 16:56:56 +0000795 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000796 ShadowMapEntry::iterator I, IEnd;
797 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
798 if (NamePos != SMap.end()) {
799 I = NamePos->second.begin();
800 IEnd = NamePos->second.end();
801 }
802
803 for (; I != IEnd; ++I) {
804 NamedDecl *ND = I->first;
805 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000806 if (ND->getCanonicalDecl() == CanonDecl) {
807 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000808 Results[Index].Declaration = R.Declaration;
809
Douglas Gregor86d9a522009-09-21 16:56:56 +0000810 // We're done.
811 return;
812 }
813 }
814
815 // This is a new declaration in this scope. However, check whether this
816 // declaration name is hidden by a similarly-named declaration in an outer
817 // scope.
818 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
819 --SMEnd;
820 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000821 ShadowMapEntry::iterator I, IEnd;
822 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
823 if (NamePos != SM->end()) {
824 I = NamePos->second.begin();
825 IEnd = NamePos->second.end();
826 }
827 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000828 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000829 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000830 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
831 Decl::IDNS_ObjCProtocol)))
832 continue;
833
834 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000835 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000836 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000837 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000838 continue;
839
840 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000841 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000842 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000843
844 break;
845 }
846 }
847
848 // Make sure that any given declaration only shows up in the result set once.
849 if (!AllDeclsFound.insert(CanonDecl))
850 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000851
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000852 // If the filter is for nested-name-specifiers, then this result starts a
853 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000854 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000855 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000856 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000857 } else
858 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000859
Douglas Gregor0563c262009-09-22 23:15:58 +0000860 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000861 if (R.QualifierIsInformative && !R.Qualifier &&
862 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000863 DeclContext *Ctx = R.Declaration->getDeclContext();
864 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
865 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
866 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
867 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
868 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
869 else
870 R.QualifierIsInformative = false;
871 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000872
Douglas Gregor86d9a522009-09-21 16:56:56 +0000873 // Insert this result into the set of results and into the current shadow
874 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000875 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000876 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000877
878 if (!AsNestedNameSpecifier)
879 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000880}
881
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000882void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000883 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000884 if (R.Kind != Result::RK_Declaration) {
885 // For non-declaration results, just add the result.
886 Results.push_back(R);
887 return;
888 }
889
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000890 // Look through using declarations.
891 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
892 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
893 return;
894 }
895
Douglas Gregor45bcd432010-01-14 03:21:49 +0000896 bool AsNestedNameSpecifier = false;
897 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000898 return;
899
Douglas Gregor6f942b22010-09-21 16:06:22 +0000900 // C++ constructors are never found by name lookup.
901 if (isa<CXXConstructorDecl>(R.Declaration))
902 return;
903
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000904 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
905 return;
906
907 // Make sure that any given declaration only shows up in the result set once.
908 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
909 return;
910
911 // If the filter is for nested-name-specifiers, then this result starts a
912 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000913 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000914 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000915 R.Priority = CCP_NestedNameSpecifier;
916 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000917 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
918 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000919 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000920 R.QualifierIsInformative = true;
921
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000922 // If this result is supposed to have an informative qualifier, add one.
923 if (R.QualifierIsInformative && !R.Qualifier &&
924 !R.StartsNestedNameSpecifier) {
925 DeclContext *Ctx = R.Declaration->getDeclContext();
926 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
927 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
928 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
929 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000930 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000931 else
932 R.QualifierIsInformative = false;
933 }
934
Douglas Gregor12e13132010-05-26 22:00:08 +0000935 // Adjust the priority if this result comes from a base class.
936 if (InBaseClass)
937 R.Priority += CCD_InBaseClass;
938
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000939 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000940
Douglas Gregor3cdee122010-08-26 16:36:48 +0000941 if (HasObjectTypeQualifiers)
942 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
943 if (Method->isInstance()) {
944 Qualifiers MethodQuals
945 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
946 if (ObjectTypeQualifiers == MethodQuals)
947 R.Priority += CCD_ObjectQualifierMatch;
948 else if (ObjectTypeQualifiers - MethodQuals) {
949 // The method cannot be invoked, because doing so would drop
950 // qualifiers.
951 return;
952 }
953 }
954
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000955 // Insert this result into the set of results.
956 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000957
958 if (!AsNestedNameSpecifier)
959 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000960}
961
Douglas Gregora4477812010-01-14 16:01:26 +0000962void ResultBuilder::AddResult(Result R) {
963 assert(R.Kind != Result::RK_Declaration &&
964 "Declaration results need more context");
965 Results.push_back(R);
966}
967
Douglas Gregor86d9a522009-09-21 16:56:56 +0000968/// \brief Enter into a new scope.
969void ResultBuilder::EnterNewScope() {
970 ShadowMaps.push_back(ShadowMap());
971}
972
973/// \brief Exit from the current scope.
974void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000975 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
976 EEnd = ShadowMaps.back().end();
977 E != EEnd;
978 ++E)
979 E->second.Destroy();
980
Douglas Gregor86d9a522009-09-21 16:56:56 +0000981 ShadowMaps.pop_back();
982}
983
Douglas Gregor791215b2009-09-21 20:51:25 +0000984/// \brief Determines whether this given declaration will be found by
985/// ordinary name lookup.
986bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000987 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
988
Douglas Gregor791215b2009-09-21 20:51:25 +0000989 unsigned IDNS = Decl::IDNS_Ordinary;
990 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000991 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +0000992 else if (SemaRef.getLangOptions().ObjC1) {
993 if (isa<ObjCIvarDecl>(ND))
994 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +0000995 }
996
Douglas Gregor791215b2009-09-21 20:51:25 +0000997 return ND->getIdentifierNamespace() & IDNS;
998}
999
Douglas Gregor01dfea02010-01-10 23:08:15 +00001000/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001001/// ordinary name lookup but is not a type name.
1002bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
1003 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1004 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1005 return false;
1006
1007 unsigned IDNS = Decl::IDNS_Ordinary;
1008 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001009 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +00001010 else if (SemaRef.getLangOptions().ObjC1) {
1011 if (isa<ObjCIvarDecl>(ND))
1012 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001013 }
1014
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001015 return ND->getIdentifierNamespace() & IDNS;
1016}
1017
Douglas Gregorf9578432010-07-28 21:50:18 +00001018bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1019 if (!IsOrdinaryNonTypeName(ND))
1020 return 0;
1021
1022 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1023 if (VD->getType()->isIntegralOrEnumerationType())
1024 return true;
1025
1026 return false;
1027}
1028
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001029/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001030/// ordinary name lookup.
1031bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001032 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1033
Douglas Gregor01dfea02010-01-10 23:08:15 +00001034 unsigned IDNS = Decl::IDNS_Ordinary;
1035 if (SemaRef.getLangOptions().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001036 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001037
1038 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001039 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1040 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001041}
1042
Douglas Gregor86d9a522009-09-21 16:56:56 +00001043/// \brief Determines whether the given declaration is suitable as the
1044/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1045bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1046 // Allow us to find class templates, too.
1047 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1048 ND = ClassTemplate->getTemplatedDecl();
1049
1050 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1051}
1052
1053/// \brief Determines whether the given declaration is an enumeration.
1054bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1055 return isa<EnumDecl>(ND);
1056}
1057
1058/// \brief Determines whether the given declaration is a class or struct.
1059bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1060 // Allow us to find class templates, too.
1061 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1062 ND = ClassTemplate->getTemplatedDecl();
1063
1064 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001065 return RD->getTagKind() == TTK_Class ||
1066 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001067
1068 return false;
1069}
1070
1071/// \brief Determines whether the given declaration is a union.
1072bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1073 // Allow us to find class templates, too.
1074 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1075 ND = ClassTemplate->getTemplatedDecl();
1076
1077 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001078 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001079
1080 return false;
1081}
1082
1083/// \brief Determines whether the given declaration is a namespace.
1084bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1085 return isa<NamespaceDecl>(ND);
1086}
1087
1088/// \brief Determines whether the given declaration is a namespace or
1089/// namespace alias.
1090bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1091 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1092}
1093
Douglas Gregor76282942009-12-11 17:31:05 +00001094/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001095bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001096 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1097 ND = Using->getTargetDecl();
1098
1099 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001100}
1101
Douglas Gregor76282942009-12-11 17:31:05 +00001102/// \brief Determines which members of a class should be visible via
1103/// "." or "->". Only value declarations, nested name specifiers, and
1104/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001105bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001106 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1107 ND = Using->getTargetDecl();
1108
Douglas Gregorce821962009-12-11 18:14:22 +00001109 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1110 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001111}
1112
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001113static bool isObjCReceiverType(ASTContext &C, QualType T) {
1114 T = C.getCanonicalType(T);
1115 switch (T->getTypeClass()) {
1116 case Type::ObjCObject:
1117 case Type::ObjCInterface:
1118 case Type::ObjCObjectPointer:
1119 return true;
1120
1121 case Type::Builtin:
1122 switch (cast<BuiltinType>(T)->getKind()) {
1123 case BuiltinType::ObjCId:
1124 case BuiltinType::ObjCClass:
1125 case BuiltinType::ObjCSel:
1126 return true;
1127
1128 default:
1129 break;
1130 }
1131 return false;
1132
1133 default:
1134 break;
1135 }
1136
1137 if (!C.getLangOptions().CPlusPlus)
1138 return false;
1139
1140 // FIXME: We could perform more analysis here to determine whether a
1141 // particular class type has any conversions to Objective-C types. For now,
1142 // just accept all class types.
1143 return T->isDependentType() || T->isRecordType();
1144}
1145
1146bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1147 QualType T = getDeclUsageType(SemaRef.Context, ND);
1148 if (T.isNull())
1149 return false;
1150
1151 T = SemaRef.Context.getBaseElementType(T);
1152 return isObjCReceiverType(SemaRef.Context, T);
1153}
1154
Douglas Gregorfb629412010-08-23 21:17:50 +00001155bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
1156 if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
1157 (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
1158 return false;
1159
1160 QualType T = getDeclUsageType(SemaRef.Context, ND);
1161 if (T.isNull())
1162 return false;
1163
1164 T = SemaRef.Context.getBaseElementType(T);
1165 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1166 T->isObjCIdType() ||
1167 (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
1168}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001169
Douglas Gregor52779fb2010-09-23 23:01:17 +00001170bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1171 return false;
1172}
1173
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001174/// \rief Determines whether the given declaration is an Objective-C
1175/// instance variable.
1176bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1177 return isa<ObjCIvarDecl>(ND);
1178}
1179
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001180namespace {
1181 /// \brief Visible declaration consumer that adds a code-completion result
1182 /// for each visible declaration.
1183 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1184 ResultBuilder &Results;
1185 DeclContext *CurContext;
1186
1187 public:
1188 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1189 : Results(Results), CurContext(CurContext) { }
1190
Erik Verbruggend1205962011-10-06 07:27:49 +00001191 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1192 bool InBaseClass) {
1193 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001194 if (Ctx)
1195 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1196
Erik Verbruggend1205962011-10-06 07:27:49 +00001197 ResultBuilder::Result Result(ND, 0, false, Accessible);
1198 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001199 }
1200 };
1201}
1202
Douglas Gregor86d9a522009-09-21 16:56:56 +00001203/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001204static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001205 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001206 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001207 Results.AddResult(Result("short", CCP_Type));
1208 Results.AddResult(Result("long", CCP_Type));
1209 Results.AddResult(Result("signed", CCP_Type));
1210 Results.AddResult(Result("unsigned", CCP_Type));
1211 Results.AddResult(Result("void", CCP_Type));
1212 Results.AddResult(Result("char", CCP_Type));
1213 Results.AddResult(Result("int", CCP_Type));
1214 Results.AddResult(Result("float", CCP_Type));
1215 Results.AddResult(Result("double", CCP_Type));
1216 Results.AddResult(Result("enum", CCP_Type));
1217 Results.AddResult(Result("struct", CCP_Type));
1218 Results.AddResult(Result("union", CCP_Type));
1219 Results.AddResult(Result("const", CCP_Type));
1220 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001221
Douglas Gregor86d9a522009-09-21 16:56:56 +00001222 if (LangOpts.C99) {
1223 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001224 Results.AddResult(Result("_Complex", CCP_Type));
1225 Results.AddResult(Result("_Imaginary", CCP_Type));
1226 Results.AddResult(Result("_Bool", CCP_Type));
1227 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001228 }
1229
Douglas Gregor218937c2011-02-01 19:23:04 +00001230 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001231 if (LangOpts.CPlusPlus) {
1232 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001233 Results.AddResult(Result("bool", CCP_Type +
1234 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001235 Results.AddResult(Result("class", CCP_Type));
1236 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001237
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001238 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001239 Builder.AddTypedTextChunk("typename");
1240 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1241 Builder.AddPlaceholderChunk("qualifier");
1242 Builder.AddTextChunk("::");
1243 Builder.AddPlaceholderChunk("name");
1244 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001245
Douglas Gregor86d9a522009-09-21 16:56:56 +00001246 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001247 Results.AddResult(Result("auto", CCP_Type));
1248 Results.AddResult(Result("char16_t", CCP_Type));
1249 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001250
Douglas Gregor218937c2011-02-01 19:23:04 +00001251 Builder.AddTypedTextChunk("decltype");
1252 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1253 Builder.AddPlaceholderChunk("expression");
1254 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1255 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001256 }
1257 }
1258
1259 // GNU extensions
1260 if (LangOpts.GNUMode) {
1261 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001262 // Results.AddResult(Result("_Decimal32"));
1263 // Results.AddResult(Result("_Decimal64"));
1264 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001265
Douglas Gregor218937c2011-02-01 19:23:04 +00001266 Builder.AddTypedTextChunk("typeof");
1267 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1268 Builder.AddPlaceholderChunk("expression");
1269 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001270
Douglas Gregor218937c2011-02-01 19:23:04 +00001271 Builder.AddTypedTextChunk("typeof");
1272 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1273 Builder.AddPlaceholderChunk("type");
1274 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1275 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001276 }
1277}
1278
John McCallf312b1e2010-08-26 23:41:50 +00001279static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001280 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001281 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001282 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001283 // Note: we don't suggest either "auto" or "register", because both
1284 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1285 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001286 Results.AddResult(Result("extern"));
1287 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001288}
1289
John McCallf312b1e2010-08-26 23:41:50 +00001290static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001291 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001292 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001293 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001294 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001295 case Sema::PCC_Class:
1296 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001297 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001298 Results.AddResult(Result("explicit"));
1299 Results.AddResult(Result("friend"));
1300 Results.AddResult(Result("mutable"));
1301 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001302 }
1303 // Fall through
1304
John McCallf312b1e2010-08-26 23:41:50 +00001305 case Sema::PCC_ObjCInterface:
1306 case Sema::PCC_ObjCImplementation:
1307 case Sema::PCC_Namespace:
1308 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001309 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001310 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001311 break;
1312
John McCallf312b1e2010-08-26 23:41:50 +00001313 case Sema::PCC_ObjCInstanceVariableList:
1314 case Sema::PCC_Expression:
1315 case Sema::PCC_Statement:
1316 case Sema::PCC_ForInit:
1317 case Sema::PCC_Condition:
1318 case Sema::PCC_RecoveryInFunction:
1319 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001320 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001321 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001322 break;
1323 }
1324}
1325
Douglas Gregorbca403c2010-01-13 23:51:12 +00001326static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1327static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1328static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001329 ResultBuilder &Results,
1330 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001331static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001332 ResultBuilder &Results,
1333 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001334static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001335 ResultBuilder &Results,
1336 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001337static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001338
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001339static void AddTypedefResult(ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001340 CodeCompletionBuilder Builder(Results.getAllocator());
1341 Builder.AddTypedTextChunk("typedef");
1342 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1343 Builder.AddPlaceholderChunk("type");
1344 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1345 Builder.AddPlaceholderChunk("name");
1346 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001347}
1348
John McCallf312b1e2010-08-26 23:41:50 +00001349static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001350 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001351 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001352 case Sema::PCC_Namespace:
1353 case Sema::PCC_Class:
1354 case Sema::PCC_ObjCInstanceVariableList:
1355 case Sema::PCC_Template:
1356 case Sema::PCC_MemberTemplate:
1357 case Sema::PCC_Statement:
1358 case Sema::PCC_RecoveryInFunction:
1359 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001360 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001361 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001362 return true;
1363
John McCallf312b1e2010-08-26 23:41:50 +00001364 case Sema::PCC_Expression:
1365 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001366 return LangOpts.CPlusPlus;
1367
1368 case Sema::PCC_ObjCInterface:
1369 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001370 return false;
1371
John McCallf312b1e2010-08-26 23:41:50 +00001372 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001373 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001374 }
David Blaikie7530c032012-01-17 06:56:22 +00001375
1376 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001377}
1378
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001379static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1380 const Preprocessor &PP) {
1381 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001382 Policy.AnonymousTagLocations = false;
1383 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001384 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001385 return Policy;
1386}
1387
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001388/// \brief Retrieve a printing policy suitable for code completion.
1389static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1390 return getCompletionPrintingPolicy(S.Context, S.PP);
1391}
1392
Douglas Gregor8ca72082011-10-18 21:20:17 +00001393/// \brief Retrieve the string representation of the given type as a string
1394/// that has the appropriate lifetime for code completion.
1395///
1396/// This routine provides a fast path where we provide constant strings for
1397/// common type names.
1398static const char *GetCompletionTypeString(QualType T,
1399 ASTContext &Context,
1400 const PrintingPolicy &Policy,
1401 CodeCompletionAllocator &Allocator) {
1402 if (!T.getLocalQualifiers()) {
1403 // Built-in type names are constant strings.
1404 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
1405 return BT->getName(Policy);
1406
1407 // Anonymous tag types are constant strings.
1408 if (const TagType *TagT = dyn_cast<TagType>(T))
1409 if (TagDecl *Tag = TagT->getDecl())
1410 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1411 switch (Tag->getTagKind()) {
1412 case TTK_Struct: return "struct <anonymous>";
1413 case TTK_Class: return "class <anonymous>";
1414 case TTK_Union: return "union <anonymous>";
1415 case TTK_Enum: return "enum <anonymous>";
1416 }
1417 }
1418 }
1419
1420 // Slow path: format the type as a string.
1421 std::string Result;
1422 T.getAsStringInternal(Result, Policy);
1423 return Allocator.CopyString(Result);
1424}
1425
Douglas Gregor01dfea02010-01-10 23:08:15 +00001426/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001427static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001428 Scope *S,
1429 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001430 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001431 CodeCompletionAllocator &Allocator = Results.getAllocator();
1432 CodeCompletionBuilder Builder(Allocator);
1433 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001434
John McCall0a2c5e22010-08-25 06:19:51 +00001435 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001436 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001437 case Sema::PCC_Namespace:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001438 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001439 if (Results.includeCodePatterns()) {
1440 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001441 Builder.AddTypedTextChunk("namespace");
1442 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1443 Builder.AddPlaceholderChunk("identifier");
1444 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1445 Builder.AddPlaceholderChunk("declarations");
1446 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1447 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1448 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001449 }
1450
Douglas Gregor01dfea02010-01-10 23:08:15 +00001451 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001452 Builder.AddTypedTextChunk("namespace");
1453 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1454 Builder.AddPlaceholderChunk("name");
1455 Builder.AddChunk(CodeCompletionString::CK_Equal);
1456 Builder.AddPlaceholderChunk("namespace");
1457 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001458
1459 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001460 Builder.AddTypedTextChunk("using");
1461 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1462 Builder.AddTextChunk("namespace");
1463 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1464 Builder.AddPlaceholderChunk("identifier");
1465 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001466
1467 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001468 Builder.AddTypedTextChunk("asm");
1469 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1470 Builder.AddPlaceholderChunk("string-literal");
1471 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1472 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001473
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001474 if (Results.includeCodePatterns()) {
1475 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001476 Builder.AddTypedTextChunk("template");
1477 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1478 Builder.AddPlaceholderChunk("declaration");
1479 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001480 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001481 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001482
1483 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001484 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001485
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001486 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001487 // Fall through
1488
John McCallf312b1e2010-08-26 23:41:50 +00001489 case Sema::PCC_Class:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001490 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001491 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001492 Builder.AddTypedTextChunk("using");
1493 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1494 Builder.AddPlaceholderChunk("qualifier");
1495 Builder.AddTextChunk("::");
1496 Builder.AddPlaceholderChunk("name");
1497 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001498
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001499 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001500 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001501 Builder.AddTypedTextChunk("using");
1502 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1503 Builder.AddTextChunk("typename");
1504 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1505 Builder.AddPlaceholderChunk("qualifier");
1506 Builder.AddTextChunk("::");
1507 Builder.AddPlaceholderChunk("name");
1508 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001509 }
1510
John McCallf312b1e2010-08-26 23:41:50 +00001511 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001512 AddTypedefResult(Results);
1513
Douglas Gregor01dfea02010-01-10 23:08:15 +00001514 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001515 Builder.AddTypedTextChunk("public");
1516 Builder.AddChunk(CodeCompletionString::CK_Colon);
1517 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001518
1519 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001520 Builder.AddTypedTextChunk("protected");
1521 Builder.AddChunk(CodeCompletionString::CK_Colon);
1522 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001523
1524 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001525 Builder.AddTypedTextChunk("private");
1526 Builder.AddChunk(CodeCompletionString::CK_Colon);
1527 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001528 }
1529 }
1530 // Fall through
1531
John McCallf312b1e2010-08-26 23:41:50 +00001532 case Sema::PCC_Template:
1533 case Sema::PCC_MemberTemplate:
Douglas Gregord8e8a582010-05-25 21:41:55 +00001534 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001535 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001536 Builder.AddTypedTextChunk("template");
1537 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1538 Builder.AddPlaceholderChunk("parameters");
1539 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1540 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001541 }
1542
Douglas Gregorbca403c2010-01-13 23:51:12 +00001543 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1544 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001545 break;
1546
John McCallf312b1e2010-08-26 23:41:50 +00001547 case Sema::PCC_ObjCInterface:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001548 AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true);
1549 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1550 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001551 break;
1552
John McCallf312b1e2010-08-26 23:41:50 +00001553 case Sema::PCC_ObjCImplementation:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001554 AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true);
1555 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1556 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001557 break;
1558
John McCallf312b1e2010-08-26 23:41:50 +00001559 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001560 AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001561 break;
1562
John McCallf312b1e2010-08-26 23:41:50 +00001563 case Sema::PCC_RecoveryInFunction:
1564 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001565 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001566
Douglas Gregorec3310a2011-04-12 02:47:21 +00001567 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns() &&
1568 SemaRef.getLangOptions().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001569 Builder.AddTypedTextChunk("try");
1570 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1571 Builder.AddPlaceholderChunk("statements");
1572 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1573 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1574 Builder.AddTextChunk("catch");
1575 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1576 Builder.AddPlaceholderChunk("declaration");
1577 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1578 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1579 Builder.AddPlaceholderChunk("statements");
1580 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1581 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1582 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001583 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001584 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001585 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001586
Douglas Gregord8e8a582010-05-25 21:41:55 +00001587 if (Results.includeCodePatterns()) {
1588 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001589 Builder.AddTypedTextChunk("if");
1590 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001591 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001592 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001593 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001594 Builder.AddPlaceholderChunk("expression");
1595 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1596 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1597 Builder.AddPlaceholderChunk("statements");
1598 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1599 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1600 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001601
Douglas Gregord8e8a582010-05-25 21:41:55 +00001602 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001603 Builder.AddTypedTextChunk("switch");
1604 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001605 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001606 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001607 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001608 Builder.AddPlaceholderChunk("expression");
1609 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1610 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1611 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1612 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1613 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001614 }
1615
Douglas Gregor01dfea02010-01-10 23:08:15 +00001616 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001617 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001618 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001619 Builder.AddTypedTextChunk("case");
1620 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1621 Builder.AddPlaceholderChunk("expression");
1622 Builder.AddChunk(CodeCompletionString::CK_Colon);
1623 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001624
1625 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001626 Builder.AddTypedTextChunk("default");
1627 Builder.AddChunk(CodeCompletionString::CK_Colon);
1628 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001629 }
1630
Douglas Gregord8e8a582010-05-25 21:41:55 +00001631 if (Results.includeCodePatterns()) {
1632 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001633 Builder.AddTypedTextChunk("while");
1634 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001635 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001636 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001637 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001638 Builder.AddPlaceholderChunk("expression");
1639 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1640 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1641 Builder.AddPlaceholderChunk("statements");
1642 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1643 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1644 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001645
1646 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001647 Builder.AddTypedTextChunk("do");
1648 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1649 Builder.AddPlaceholderChunk("statements");
1650 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1651 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1652 Builder.AddTextChunk("while");
1653 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1654 Builder.AddPlaceholderChunk("expression");
1655 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1656 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001657
Douglas Gregord8e8a582010-05-25 21:41:55 +00001658 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001659 Builder.AddTypedTextChunk("for");
1660 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001661 if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001662 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001663 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001664 Builder.AddPlaceholderChunk("init-expression");
1665 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1666 Builder.AddPlaceholderChunk("condition");
1667 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1668 Builder.AddPlaceholderChunk("inc-expression");
1669 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1670 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1671 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1672 Builder.AddPlaceholderChunk("statements");
1673 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1674 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1675 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001676 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001677
1678 if (S->getContinueParent()) {
1679 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001680 Builder.AddTypedTextChunk("continue");
1681 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001682 }
1683
1684 if (S->getBreakParent()) {
1685 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001686 Builder.AddTypedTextChunk("break");
1687 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001688 }
1689
1690 // "return expression ;" or "return ;", depending on whether we
1691 // know the function is void or not.
1692 bool isVoid = false;
1693 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1694 isVoid = Function->getResultType()->isVoidType();
1695 else if (ObjCMethodDecl *Method
1696 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1697 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001698 else if (SemaRef.getCurBlock() &&
1699 !SemaRef.getCurBlock()->ReturnType.isNull())
1700 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001701 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001702 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001703 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1704 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001705 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001706 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001707
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001708 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001709 Builder.AddTypedTextChunk("goto");
1710 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1711 Builder.AddPlaceholderChunk("label");
1712 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001713
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001714 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("using");
1716 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1717 Builder.AddTextChunk("namespace");
1718 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1719 Builder.AddPlaceholderChunk("identifier");
1720 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001721 }
1722
1723 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001724 case Sema::PCC_ForInit:
1725 case Sema::PCC_Condition:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001726 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001727 // Fall through: conditions and statements can have expressions.
1728
Douglas Gregor02688102010-09-14 23:59:36 +00001729 case Sema::PCC_ParenthesizedExpression:
John McCallf85e1932011-06-15 23:02:42 +00001730 if (SemaRef.getLangOptions().ObjCAutoRefCount &&
1731 CCC == Sema::PCC_ParenthesizedExpression) {
1732 // (__bridge <type>)<expression>
1733 Builder.AddTypedTextChunk("__bridge");
1734 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1735 Builder.AddPlaceholderChunk("type");
1736 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1737 Builder.AddPlaceholderChunk("expression");
1738 Results.AddResult(Result(Builder.TakeString()));
1739
1740 // (__bridge_transfer <Objective-C type>)<expression>
1741 Builder.AddTypedTextChunk("__bridge_transfer");
1742 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1743 Builder.AddPlaceholderChunk("Objective-C type");
1744 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1745 Builder.AddPlaceholderChunk("expression");
1746 Results.AddResult(Result(Builder.TakeString()));
1747
1748 // (__bridge_retained <CF type>)<expression>
1749 Builder.AddTypedTextChunk("__bridge_retained");
1750 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1751 Builder.AddPlaceholderChunk("CF type");
1752 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1753 Builder.AddPlaceholderChunk("expression");
1754 Results.AddResult(Result(Builder.TakeString()));
1755 }
1756 // Fall through
1757
John McCallf312b1e2010-08-26 23:41:50 +00001758 case Sema::PCC_Expression: {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001759 if (SemaRef.getLangOptions().CPlusPlus) {
1760 // 'this', if we're in a non-static member function.
Eli Friedman72899c32012-01-07 04:59:52 +00001761 QualType ThisTy = SemaRef.getCurrentThisType();
Douglas Gregor8ca72082011-10-18 21:20:17 +00001762 if (!ThisTy.isNull()) {
1763 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1764 SemaRef.Context,
1765 Policy,
1766 Allocator));
1767 Builder.AddTypedTextChunk("this");
1768 Results.AddResult(Result(Builder.TakeString()));
1769 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001770
Douglas Gregor8ca72082011-10-18 21:20:17 +00001771 // true
1772 Builder.AddResultTypeChunk("bool");
1773 Builder.AddTypedTextChunk("true");
1774 Results.AddResult(Result(Builder.TakeString()));
1775
1776 // false
1777 Builder.AddResultTypeChunk("bool");
1778 Builder.AddTypedTextChunk("false");
1779 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001780
Douglas Gregorec3310a2011-04-12 02:47:21 +00001781 if (SemaRef.getLangOptions().RTTI) {
1782 // dynamic_cast < type-id > ( expression )
1783 Builder.AddTypedTextChunk("dynamic_cast");
1784 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1785 Builder.AddPlaceholderChunk("type");
1786 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1787 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1788 Builder.AddPlaceholderChunk("expression");
1789 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1790 Results.AddResult(Result(Builder.TakeString()));
1791 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001792
1793 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001794 Builder.AddTypedTextChunk("static_cast");
1795 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1796 Builder.AddPlaceholderChunk("type");
1797 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1798 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1799 Builder.AddPlaceholderChunk("expression");
1800 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1801 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001802
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001803 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001804 Builder.AddTypedTextChunk("reinterpret_cast");
1805 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1806 Builder.AddPlaceholderChunk("type");
1807 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1808 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1809 Builder.AddPlaceholderChunk("expression");
1810 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1811 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001812
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001813 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001814 Builder.AddTypedTextChunk("const_cast");
1815 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1816 Builder.AddPlaceholderChunk("type");
1817 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1818 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1819 Builder.AddPlaceholderChunk("expression");
1820 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1821 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001822
Douglas Gregorec3310a2011-04-12 02:47:21 +00001823 if (SemaRef.getLangOptions().RTTI) {
1824 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001825 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001826 Builder.AddTypedTextChunk("typeid");
1827 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1828 Builder.AddPlaceholderChunk("expression-or-type");
1829 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1830 Results.AddResult(Result(Builder.TakeString()));
1831 }
1832
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001833 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001834 Builder.AddTypedTextChunk("new");
1835 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1836 Builder.AddPlaceholderChunk("type");
1837 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1838 Builder.AddPlaceholderChunk("expressions");
1839 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1840 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001841
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001842 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001843 Builder.AddTypedTextChunk("new");
1844 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1845 Builder.AddPlaceholderChunk("type");
1846 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1847 Builder.AddPlaceholderChunk("size");
1848 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1849 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1850 Builder.AddPlaceholderChunk("expressions");
1851 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1852 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001853
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001854 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001855 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001856 Builder.AddTypedTextChunk("delete");
1857 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1858 Builder.AddPlaceholderChunk("expression");
1859 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001860
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001861 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001862 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001863 Builder.AddTypedTextChunk("delete");
1864 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1865 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1866 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1867 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1868 Builder.AddPlaceholderChunk("expression");
1869 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001870
Douglas Gregorec3310a2011-04-12 02:47:21 +00001871 if (SemaRef.getLangOptions().CXXExceptions) {
1872 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001873 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001874 Builder.AddTypedTextChunk("throw");
1875 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1876 Builder.AddPlaceholderChunk("expression");
1877 Results.AddResult(Result(Builder.TakeString()));
1878 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001879
Douglas Gregor12e13132010-05-26 22:00:08 +00001880 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001881
1882 if (SemaRef.getLangOptions().CPlusPlus0x) {
1883 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001884 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001885 Builder.AddTypedTextChunk("nullptr");
1886 Results.AddResult(Result(Builder.TakeString()));
1887
1888 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001889 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001890 Builder.AddTypedTextChunk("alignof");
1891 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1892 Builder.AddPlaceholderChunk("type");
1893 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1894 Results.AddResult(Result(Builder.TakeString()));
1895
1896 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001897 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001898 Builder.AddTypedTextChunk("noexcept");
1899 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1900 Builder.AddPlaceholderChunk("expression");
1901 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1902 Results.AddResult(Result(Builder.TakeString()));
1903
1904 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001905 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001906 Builder.AddTypedTextChunk("sizeof...");
1907 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1908 Builder.AddPlaceholderChunk("parameter-pack");
1909 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1910 Results.AddResult(Result(Builder.TakeString()));
1911 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001912 }
1913
1914 if (SemaRef.getLangOptions().ObjC1) {
1915 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001916 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1917 // The interface can be NULL.
1918 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001919 if (ID->getSuperClass()) {
1920 std::string SuperType;
1921 SuperType = ID->getSuperClass()->getNameAsString();
1922 if (Method->isInstanceMethod())
1923 SuperType += " *";
1924
1925 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1926 Builder.AddTypedTextChunk("super");
1927 Results.AddResult(Result(Builder.TakeString()));
1928 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001929 }
1930
Douglas Gregorbca403c2010-01-13 23:51:12 +00001931 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001932 }
1933
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001934 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001935 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001936 Builder.AddTypedTextChunk("sizeof");
1937 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1938 Builder.AddPlaceholderChunk("expression-or-type");
1939 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1940 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001941 break;
1942 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001943
John McCallf312b1e2010-08-26 23:41:50 +00001944 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001945 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001946 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001947 }
1948
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001949 if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
1950 AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001951
John McCallf312b1e2010-08-26 23:41:50 +00001952 if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001953 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001954}
1955
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001956/// \brief If the given declaration has an associated type, add it as a result
1957/// type chunk.
1958static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00001959 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001960 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001961 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001962 if (!ND)
1963 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001964
1965 // Skip constructors and conversion functions, which have their return types
1966 // built into their names.
1967 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1968 return;
1969
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001970 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001971 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001972 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1973 T = Function->getResultType();
1974 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1975 T = Method->getResultType();
1976 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1977 T = FunTmpl->getTemplatedDecl()->getResultType();
1978 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
1979 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
1980 else if (isa<UnresolvedUsingValueDecl>(ND)) {
1981 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00001982 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001983 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00001984 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001985 T = Property->getType();
1986
1987 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
1988 return;
1989
Douglas Gregor8987b232011-09-27 23:30:47 +00001990 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00001991 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001992}
1993
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001994static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00001995 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001996 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
1997 if (Sentinel->getSentinel() == 0) {
1998 if (Context.getLangOptions().ObjC1 &&
1999 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002000 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002001 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002002 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002003 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002004 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002005 }
2006}
2007
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002008static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2009 std::string Result;
2010 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002011 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002012 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002013 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002014 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002015 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002016 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002017 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002018 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002019 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002020 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002021 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002022 return Result;
2023}
2024
Douglas Gregor83482d12010-08-24 16:15:59 +00002025static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002026 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002027 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002028 bool SuppressName = false,
2029 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002030 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2031 if (Param->getType()->isDependentType() ||
2032 !Param->getType()->isBlockPointerType()) {
2033 // The argument for a dependent or non-block parameter is a placeholder
2034 // containing that parameter's type.
2035 std::string Result;
2036
Douglas Gregoraba48082010-08-29 19:47:46 +00002037 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002038 Result = Param->getIdentifier()->getName();
2039
John McCallf85e1932011-06-15 23:02:42 +00002040 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002041
2042 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002043 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2044 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002045 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002046 Result += Param->getIdentifier()->getName();
2047 }
2048 return Result;
2049 }
2050
2051 // The argument for a block pointer parameter is a block literal with
2052 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002053 FunctionTypeLoc *Block = 0;
2054 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002055 TypeLoc TL;
2056 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2057 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2058 while (true) {
2059 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002060 if (!SuppressBlock) {
2061 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2062 if (TypeSourceInfo *InnerTSInfo
2063 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2064 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2065 continue;
2066 }
2067 }
2068
2069 // Look through qualified types
2070 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2071 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002072 continue;
2073 }
2074 }
2075
Douglas Gregor83482d12010-08-24 16:15:59 +00002076 // Try to get the function prototype behind the block pointer type,
2077 // then we're done.
2078 if (BlockPointerTypeLoc *BlockPtr
2079 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002080 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002081 Block = dyn_cast<FunctionTypeLoc>(&TL);
2082 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002083 }
2084 break;
2085 }
2086 }
2087
2088 if (!Block) {
2089 // We were unable to find a FunctionProtoTypeLoc with parameter names
2090 // for the block; just use the parameter type as a placeholder.
2091 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002092 if (!ObjCMethodParam && Param->getIdentifier())
2093 Result = Param->getIdentifier()->getName();
2094
John McCallf85e1932011-06-15 23:02:42 +00002095 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002096
2097 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002098 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2099 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002100 if (Param->getIdentifier())
2101 Result += Param->getIdentifier()->getName();
2102 }
2103
2104 return Result;
2105 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002106
Douglas Gregor83482d12010-08-24 16:15:59 +00002107 // We have the function prototype behind the block pointer type, as it was
2108 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002109 std::string Result;
2110 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002111 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002112 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002113
2114 // Format the parameter list.
2115 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002116 if (!BlockProto || Block->getNumArgs() == 0) {
2117 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002118 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002119 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002120 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002121 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002122 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002123 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2124 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002125 Params += ", ";
2126 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2127 /*SuppressName=*/false,
2128 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002129
Douglas Gregor830072c2011-02-15 22:37:09 +00002130 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002131 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002132 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002133 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002134 }
Douglas Gregor38276252010-09-08 22:47:51 +00002135
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002136 if (SuppressBlock) {
2137 // Format as a parameter.
2138 Result = Result + " (^";
2139 if (Param->getIdentifier())
2140 Result += Param->getIdentifier()->getName();
2141 Result += ")";
2142 Result += Params;
2143 } else {
2144 // Format as a block literal argument.
2145 Result = '^' + Result;
2146 Result += Params;
2147
2148 if (Param->getIdentifier())
2149 Result += Param->getIdentifier()->getName();
2150 }
2151
Douglas Gregor83482d12010-08-24 16:15:59 +00002152 return Result;
2153}
2154
Douglas Gregor86d9a522009-09-21 16:56:56 +00002155/// \brief Add function parameter chunks to the given code completion string.
2156static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002157 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002158 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002159 CodeCompletionBuilder &Result,
2160 unsigned Start = 0,
2161 bool InOptional = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002162 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002163 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002164
Douglas Gregor218937c2011-02-01 19:23:04 +00002165 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002166 ParmVarDecl *Param = Function->getParamDecl(P);
2167
Douglas Gregor218937c2011-02-01 19:23:04 +00002168 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002169 // When we see an optional default argument, put that argument and
2170 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002171 CodeCompletionBuilder Opt(Result.getAllocator());
2172 if (!FirstParameter)
2173 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor8987b232011-09-27 23:30:47 +00002174 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002175 Result.AddOptionalChunk(Opt.TakeString());
2176 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002177 }
2178
Douglas Gregor218937c2011-02-01 19:23:04 +00002179 if (FirstParameter)
2180 FirstParameter = false;
2181 else
2182 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2183
2184 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002185
2186 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002187 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2188 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002189
Douglas Gregore17794f2010-08-31 05:13:43 +00002190 if (Function->isVariadic() && P == N - 1)
2191 PlaceholderStr += ", ...";
2192
Douglas Gregor86d9a522009-09-21 16:56:56 +00002193 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002194 Result.AddPlaceholderChunk(
2195 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002196 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002197
2198 if (const FunctionProtoType *Proto
2199 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002200 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002201 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002202 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002203
Douglas Gregor218937c2011-02-01 19:23:04 +00002204 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002205 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002206}
2207
2208/// \brief Add template parameter chunks to the given code completion string.
2209static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002210 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002211 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002212 CodeCompletionBuilder &Result,
2213 unsigned MaxParameters = 0,
2214 unsigned Start = 0,
2215 bool InDefaultArg = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002216 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002217 bool FirstParameter = true;
2218
2219 TemplateParameterList *Params = Template->getTemplateParameters();
2220 TemplateParameterList::iterator PEnd = Params->end();
2221 if (MaxParameters)
2222 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002223 for (TemplateParameterList::iterator P = Params->begin() + Start;
2224 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002225 bool HasDefaultArg = false;
2226 std::string PlaceholderStr;
2227 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2228 if (TTP->wasDeclaredWithTypename())
2229 PlaceholderStr = "typename";
2230 else
2231 PlaceholderStr = "class";
2232
2233 if (TTP->getIdentifier()) {
2234 PlaceholderStr += ' ';
2235 PlaceholderStr += TTP->getIdentifier()->getName();
2236 }
2237
2238 HasDefaultArg = TTP->hasDefaultArgument();
2239 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002240 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002241 if (NTTP->getIdentifier())
2242 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002243 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002244 HasDefaultArg = NTTP->hasDefaultArgument();
2245 } else {
2246 assert(isa<TemplateTemplateParmDecl>(*P));
2247 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2248
2249 // Since putting the template argument list into the placeholder would
2250 // be very, very long, we just use an abbreviation.
2251 PlaceholderStr = "template<...> class";
2252 if (TTP->getIdentifier()) {
2253 PlaceholderStr += ' ';
2254 PlaceholderStr += TTP->getIdentifier()->getName();
2255 }
2256
2257 HasDefaultArg = TTP->hasDefaultArgument();
2258 }
2259
Douglas Gregor218937c2011-02-01 19:23:04 +00002260 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002261 // When we see an optional default argument, put that argument and
2262 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002263 CodeCompletionBuilder Opt(Result.getAllocator());
2264 if (!FirstParameter)
2265 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor8987b232011-09-27 23:30:47 +00002266 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002267 P - Params->begin(), true);
2268 Result.AddOptionalChunk(Opt.TakeString());
2269 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002270 }
2271
Douglas Gregor218937c2011-02-01 19:23:04 +00002272 InDefaultArg = false;
2273
Douglas Gregor86d9a522009-09-21 16:56:56 +00002274 if (FirstParameter)
2275 FirstParameter = false;
2276 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002277 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002278
2279 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002280 Result.AddPlaceholderChunk(
2281 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002282 }
2283}
2284
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002285/// \brief Add a qualifier to the given code-completion string, if the
2286/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002287static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002288AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002289 NestedNameSpecifier *Qualifier,
2290 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002291 ASTContext &Context,
2292 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002293 if (!Qualifier)
2294 return;
2295
2296 std::string PrintedNNS;
2297 {
2298 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002299 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002300 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002301 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002302 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002303 else
Douglas Gregordae68752011-02-01 22:57:45 +00002304 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002305}
2306
Douglas Gregor218937c2011-02-01 19:23:04 +00002307static void
2308AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2309 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002310 const FunctionProtoType *Proto
2311 = Function->getType()->getAs<FunctionProtoType>();
2312 if (!Proto || !Proto->getTypeQuals())
2313 return;
2314
Douglas Gregora63f6de2011-02-01 21:15:40 +00002315 // FIXME: Add ref-qualifier!
2316
2317 // Handle single qualifiers without copying
2318 if (Proto->getTypeQuals() == Qualifiers::Const) {
2319 Result.AddInformativeChunk(" const");
2320 return;
2321 }
2322
2323 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2324 Result.AddInformativeChunk(" volatile");
2325 return;
2326 }
2327
2328 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2329 Result.AddInformativeChunk(" restrict");
2330 return;
2331 }
2332
2333 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002334 std::string QualsStr;
2335 if (Proto->getTypeQuals() & Qualifiers::Const)
2336 QualsStr += " const";
2337 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2338 QualsStr += " volatile";
2339 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2340 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002341 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002342}
2343
Douglas Gregor6f942b22010-09-21 16:06:22 +00002344/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002345static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2346 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002347 typedef CodeCompletionString::Chunk Chunk;
2348
2349 DeclarationName Name = ND->getDeclName();
2350 if (!Name)
2351 return;
2352
2353 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002354 case DeclarationName::CXXOperatorName: {
2355 const char *OperatorName = 0;
2356 switch (Name.getCXXOverloadedOperator()) {
2357 case OO_None:
2358 case OO_Conditional:
2359 case NUM_OVERLOADED_OPERATORS:
2360 OperatorName = "operator";
2361 break;
2362
2363#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2364 case OO_##Name: OperatorName = "operator" Spelling; break;
2365#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2366#include "clang/Basic/OperatorKinds.def"
2367
2368 case OO_New: OperatorName = "operator new"; break;
2369 case OO_Delete: OperatorName = "operator delete"; break;
2370 case OO_Array_New: OperatorName = "operator new[]"; break;
2371 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2372 case OO_Call: OperatorName = "operator()"; break;
2373 case OO_Subscript: OperatorName = "operator[]"; break;
2374 }
2375 Result.AddTypedTextChunk(OperatorName);
2376 break;
2377 }
2378
Douglas Gregor6f942b22010-09-21 16:06:22 +00002379 case DeclarationName::Identifier:
2380 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002381 case DeclarationName::CXXDestructorName:
2382 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002383 Result.AddTypedTextChunk(
2384 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002385 break;
2386
2387 case DeclarationName::CXXUsingDirective:
2388 case DeclarationName::ObjCZeroArgSelector:
2389 case DeclarationName::ObjCOneArgSelector:
2390 case DeclarationName::ObjCMultiArgSelector:
2391 break;
2392
2393 case DeclarationName::CXXConstructorName: {
2394 CXXRecordDecl *Record = 0;
2395 QualType Ty = Name.getCXXNameType();
2396 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2397 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2398 else if (const InjectedClassNameType *InjectedTy
2399 = Ty->getAs<InjectedClassNameType>())
2400 Record = InjectedTy->getDecl();
2401 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002402 Result.AddTypedTextChunk(
2403 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002404 break;
2405 }
2406
Douglas Gregordae68752011-02-01 22:57:45 +00002407 Result.AddTypedTextChunk(
2408 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002409 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002410 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor8987b232011-09-27 23:30:47 +00002411 AddTemplateParameterChunks(Context, Policy, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002412 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002413 }
2414 break;
2415 }
2416 }
2417}
2418
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002419CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
2420 CodeCompletionAllocator &Allocator) {
2421 return CreateCodeCompletionString(S.Context, S.PP, Allocator);
2422}
2423
Douglas Gregor86d9a522009-09-21 16:56:56 +00002424/// \brief If possible, create a new code completion string for the given
2425/// result.
2426///
2427/// \returns Either a new, heap-allocated code completion string describing
2428/// how to use this result, or NULL to indicate that the string or name of the
2429/// result is all that is needed.
2430CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002431CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2432 Preprocessor &PP,
Douglas Gregordae68752011-02-01 22:57:45 +00002433 CodeCompletionAllocator &Allocator) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002434 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002435 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002436
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002437 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002438 if (Kind == RK_Pattern) {
2439 Pattern->Priority = Priority;
2440 Pattern->Availability = Availability;
2441 return Pattern;
2442 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002443
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002444 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002445 Result.AddTypedTextChunk(Keyword);
2446 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002447 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002448
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002449 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002450 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002451 assert(MI && "Not a macro?");
2452
Douglas Gregordae68752011-02-01 22:57:45 +00002453 Result.AddTypedTextChunk(
2454 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002455
2456 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002457 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002458
2459 // Format a function-like macro with placeholders for the arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00002460 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregore4244702011-07-30 08:17:44 +00002461 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002462
2463 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2464 if (MI->isC99Varargs()) {
2465 --AEnd;
2466
2467 if (A == AEnd) {
2468 Result.AddPlaceholderChunk("...");
2469 }
Douglas Gregore4244702011-07-30 08:17:44 +00002470 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002471
Douglas Gregore4244702011-07-30 08:17:44 +00002472 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002473 if (A != MI->arg_begin())
Douglas Gregor218937c2011-02-01 19:23:04 +00002474 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002475
2476 if (MI->isVariadic() && (A+1) == AEnd) {
2477 llvm::SmallString<32> Arg = (*A)->getName();
2478 if (MI->isC99Varargs())
2479 Arg += ", ...";
2480 else
2481 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002482 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002483 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002484 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002485
2486 // Non-variadic macros are simple.
2487 Result.AddPlaceholderChunk(
2488 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002489 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002490 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2491 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002492 }
2493
Douglas Gregord8e8a582010-05-25 21:41:55 +00002494 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002495 NamedDecl *ND = Declaration;
2496
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002497 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002498 Result.AddTypedTextChunk(
2499 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002500 Result.AddTextChunk("::");
2501 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002502 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002503
2504 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2505 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2506 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2507 }
2508 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002509
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002510 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002511
Douglas Gregor86d9a522009-09-21 16:56:56 +00002512 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002513 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002514 Ctx, Policy);
2515 AddTypedNameChunk(Ctx, Policy, ND, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002516 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002517 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002518 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002519 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002520 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002521 }
2522
2523 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002524 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002525 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002526 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002527 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002528
Douglas Gregor86d9a522009-09-21 16:56:56 +00002529 // Figure out which template parameters are deduced (or have default
2530 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002531 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002532 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002533 unsigned LastDeducibleArgument;
2534 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2535 --LastDeducibleArgument) {
2536 if (!Deduced[LastDeducibleArgument - 1]) {
2537 // C++0x: Figure out if the template argument has a default. If so,
2538 // the user doesn't need to type this argument.
2539 // FIXME: We need to abstract template parameters better!
2540 bool HasDefaultArg = false;
2541 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002542 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002543 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2544 HasDefaultArg = TTP->hasDefaultArgument();
2545 else if (NonTypeTemplateParmDecl *NTTP
2546 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2547 HasDefaultArg = NTTP->hasDefaultArgument();
2548 else {
2549 assert(isa<TemplateTemplateParmDecl>(Param));
2550 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002551 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002552 }
2553
2554 if (!HasDefaultArg)
2555 break;
2556 }
2557 }
2558
2559 if (LastDeducibleArgument) {
2560 // Some of the function template arguments cannot be deduced from a
2561 // function call, so we introduce an explicit template argument list
2562 // containing all of the arguments up to the first deducible argument.
Douglas Gregor218937c2011-02-01 19:23:04 +00002563 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002564 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002565 LastDeducibleArgument);
Douglas Gregor218937c2011-02-01 19:23:04 +00002566 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002567 }
2568
2569 // Add the function parameters
Douglas Gregor218937c2011-02-01 19:23:04 +00002570 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002571 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002572 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002573 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002574 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002575 }
2576
2577 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002578 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002579 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002580 Result.AddTypedTextChunk(
2581 Result.getAllocator().CopyString(Template->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002582 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002583 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002584 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
2585 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002586 }
2587
Douglas Gregor9630eb62009-11-17 16:44:22 +00002588 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002589 Selector Sel = Method->getSelector();
2590 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002591 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002592 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002593 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002594 }
2595
Douglas Gregor813d8342011-02-18 22:29:55 +00002596 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002597 SelName += ':';
2598 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002599 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002600 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002601 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002602
2603 // If there is only one parameter, and we're past it, add an empty
2604 // typed-text chunk since there is nothing to type.
2605 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002606 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002607 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002608 unsigned Idx = 0;
2609 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2610 PEnd = Method->param_end();
2611 P != PEnd; (void)++P, ++Idx) {
2612 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002613 std::string Keyword;
2614 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002615 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002616 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002617 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002618 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002619 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002620 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002621 else
Douglas Gregordae68752011-02-01 22:57:45 +00002622 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002623 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002624
2625 // If we're before the starting parameter, skip the placeholder.
2626 if (Idx < StartParameter)
2627 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002628
2629 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002630
2631 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002632 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002633 else {
John McCallf85e1932011-06-15 23:02:42 +00002634 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002635 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2636 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002637 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002638 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002639 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002640 }
2641
Douglas Gregore17794f2010-08-31 05:13:43 +00002642 if (Method->isVariadic() && (P + 1) == PEnd)
2643 Arg += ", ...";
2644
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002645 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002646 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002647 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002648 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002649 else
Douglas Gregordae68752011-02-01 22:57:45 +00002650 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002651 }
2652
Douglas Gregor2a17af02009-12-23 00:21:46 +00002653 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002654 if (Method->param_size() == 0) {
2655 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002656 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002657 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002658 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002659 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002660 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002661 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002662
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002663 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002664 }
2665
Douglas Gregor218937c2011-02-01 19:23:04 +00002666 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002667 }
2668
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002669 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002670 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002671 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002672
Douglas Gregordae68752011-02-01 22:57:45 +00002673 Result.AddTypedTextChunk(
2674 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002675 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002676}
2677
Douglas Gregor86d802e2009-09-23 00:34:09 +00002678CodeCompletionString *
2679CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2680 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002681 Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002682 CodeCompletionAllocator &Allocator) const {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002683 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor8987b232011-09-27 23:30:47 +00002684 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002685
Douglas Gregor218937c2011-02-01 19:23:04 +00002686 // FIXME: Set priority, availability appropriately.
2687 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002688 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002689 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002690 const FunctionProtoType *Proto
2691 = dyn_cast<FunctionProtoType>(getFunctionType());
2692 if (!FDecl && !Proto) {
2693 // Function without a prototype. Just give the return type and a
2694 // highlighted ellipsis.
2695 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002696 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002697 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002698 Result.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002699 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
2700 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
2701 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2702 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002703 }
2704
2705 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002706 Result.AddTextChunk(
2707 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002708 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002709 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002710 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002711 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002712
Douglas Gregor218937c2011-02-01 19:23:04 +00002713 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002714 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2715 for (unsigned I = 0; I != NumParams; ++I) {
2716 if (I)
Douglas Gregor218937c2011-02-01 19:23:04 +00002717 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002718
2719 std::string ArgString;
2720 QualType ArgType;
2721
2722 if (FDecl) {
2723 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2724 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2725 } else {
2726 ArgType = Proto->getArgType(I);
2727 }
2728
John McCallf85e1932011-06-15 23:02:42 +00002729 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002730
2731 if (I == CurrentArg)
Douglas Gregor218937c2011-02-01 19:23:04 +00002732 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
Douglas Gregordae68752011-02-01 22:57:45 +00002733 Result.getAllocator().CopyString(ArgString)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002734 else
Douglas Gregordae68752011-02-01 22:57:45 +00002735 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002736 }
2737
2738 if (Proto && Proto->isVariadic()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002739 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002740 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002741 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002742 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002743 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002744 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002745 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002746
Douglas Gregor218937c2011-02-01 19:23:04 +00002747 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002748}
2749
Chris Lattner5f9e2722011-07-23 10:55:15 +00002750unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002751 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002752 bool PreferredTypeIsPointer) {
2753 unsigned Priority = CCP_Macro;
2754
Douglas Gregorb05496d2010-09-20 21:11:48 +00002755 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2756 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2757 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002758 Priority = CCP_Constant;
2759 if (PreferredTypeIsPointer)
2760 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002761 }
2762 // Treat "YES", "NO", "true", and "false" as constants.
2763 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2764 MacroName.equals("true") || MacroName.equals("false"))
2765 Priority = CCP_Constant;
2766 // Treat "bool" as a type.
2767 else if (MacroName.equals("bool"))
2768 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2769
Douglas Gregor1827e102010-08-16 16:18:59 +00002770
2771 return Priority;
2772}
2773
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002774CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2775 if (!D)
2776 return CXCursor_UnexposedDecl;
2777
2778 switch (D->getKind()) {
2779 case Decl::Enum: return CXCursor_EnumDecl;
2780 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2781 case Decl::Field: return CXCursor_FieldDecl;
2782 case Decl::Function:
2783 return CXCursor_FunctionDecl;
2784 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2785 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002786 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002787
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002788 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002789 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2790 case Decl::ObjCMethod:
2791 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2792 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2793 case Decl::CXXMethod: return CXCursor_CXXMethod;
2794 case Decl::CXXConstructor: return CXCursor_Constructor;
2795 case Decl::CXXDestructor: return CXCursor_Destructor;
2796 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2797 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002798 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002799 case Decl::ParmVar: return CXCursor_ParmDecl;
2800 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002801 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002802 case Decl::Var: return CXCursor_VarDecl;
2803 case Decl::Namespace: return CXCursor_Namespace;
2804 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2805 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2806 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2807 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2808 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2809 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002810 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002811 case Decl::ClassTemplatePartialSpecialization:
2812 return CXCursor_ClassTemplatePartialSpecialization;
2813 case Decl::UsingDirective: return CXCursor_UsingDirective;
2814
2815 case Decl::Using:
2816 case Decl::UnresolvedUsingValue:
2817 case Decl::UnresolvedUsingTypename:
2818 return CXCursor_UsingDeclaration;
2819
Douglas Gregor352697a2011-06-03 23:08:58 +00002820 case Decl::ObjCPropertyImpl:
2821 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2822 case ObjCPropertyImplDecl::Dynamic:
2823 return CXCursor_ObjCDynamicDecl;
2824
2825 case ObjCPropertyImplDecl::Synthesize:
2826 return CXCursor_ObjCSynthesizeDecl;
2827 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002828
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002829 default:
2830 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2831 switch (TD->getTagKind()) {
2832 case TTK_Struct: return CXCursor_StructDecl;
2833 case TTK_Class: return CXCursor_ClassDecl;
2834 case TTK_Union: return CXCursor_UnionDecl;
2835 case TTK_Enum: return CXCursor_EnumDecl;
2836 }
2837 }
2838 }
2839
2840 return CXCursor_UnexposedDecl;
2841}
2842
Douglas Gregor590c7d52010-07-08 20:55:51 +00002843static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2844 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002845 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002846
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002847 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002848
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002849 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2850 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002851 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002852 Results.AddResult(Result(M->first,
2853 getMacroUsagePriority(M->first->getName(),
Douglas Gregorb05496d2010-09-20 21:11:48 +00002854 PP.getLangOptions(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002855 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002856 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002857
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002858 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002859
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002860}
2861
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002862static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2863 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002864 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002865
2866 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002867
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002868 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2869 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2870 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2871 Results.AddResult(Result("__func__", CCP_Constant));
2872 Results.ExitScope();
2873}
2874
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002875static void HandleCodeCompleteResults(Sema *S,
2876 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002877 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002878 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002879 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002880 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002881 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002882}
2883
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002884static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2885 Sema::ParserCompletionContext PCC) {
2886 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002887 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002888 return CodeCompletionContext::CCC_TopLevel;
2889
John McCallf312b1e2010-08-26 23:41:50 +00002890 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002891 return CodeCompletionContext::CCC_ClassStructUnion;
2892
John McCallf312b1e2010-08-26 23:41:50 +00002893 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002894 return CodeCompletionContext::CCC_ObjCInterface;
2895
John McCallf312b1e2010-08-26 23:41:50 +00002896 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002897 return CodeCompletionContext::CCC_ObjCImplementation;
2898
John McCallf312b1e2010-08-26 23:41:50 +00002899 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002900 return CodeCompletionContext::CCC_ObjCIvarList;
2901
John McCallf312b1e2010-08-26 23:41:50 +00002902 case Sema::PCC_Template:
2903 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002904 if (S.CurContext->isFileContext())
2905 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002906 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002907 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002908 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002909
John McCallf312b1e2010-08-26 23:41:50 +00002910 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002911 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002912
John McCallf312b1e2010-08-26 23:41:50 +00002913 case Sema::PCC_ForInit:
Douglas Gregora5450a02010-10-18 22:01:46 +00002914 if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 ||
2915 S.getLangOptions().ObjC1)
2916 return CodeCompletionContext::CCC_ParenthesizedExpression;
2917 else
2918 return CodeCompletionContext::CCC_Expression;
2919
2920 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002921 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002922 return CodeCompletionContext::CCC_Expression;
2923
John McCallf312b1e2010-08-26 23:41:50 +00002924 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002925 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002926
John McCallf312b1e2010-08-26 23:41:50 +00002927 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002928 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002929
2930 case Sema::PCC_ParenthesizedExpression:
2931 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002932
2933 case Sema::PCC_LocalDeclarationSpecifiers:
2934 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002935 }
David Blaikie7530c032012-01-17 06:56:22 +00002936
2937 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002938}
2939
Douglas Gregorf6961522010-08-27 21:18:54 +00002940/// \brief If we're in a C++ virtual member function, add completion results
2941/// that invoke the functions we override, since it's common to invoke the
2942/// overridden function as well as adding new functionality.
2943///
2944/// \param S The semantic analysis object for which we are generating results.
2945///
2946/// \param InContext This context in which the nested-name-specifier preceding
2947/// the code-completion point
2948static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2949 ResultBuilder &Results) {
2950 // Look through blocks.
2951 DeclContext *CurContext = S.CurContext;
2952 while (isa<BlockDecl>(CurContext))
2953 CurContext = CurContext->getParent();
2954
2955
2956 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2957 if (!Method || !Method->isVirtual())
2958 return;
2959
2960 // We need to have names for all of the parameters, if we're going to
2961 // generate a forwarding call.
2962 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2963 PEnd = Method->param_end();
2964 P != PEnd;
2965 ++P) {
2966 if (!(*P)->getDeclName())
2967 return;
2968 }
2969
Douglas Gregor8987b232011-09-27 23:30:47 +00002970 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00002971 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2972 MEnd = Method->end_overridden_methods();
2973 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002974 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002975 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2976 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2977 continue;
2978
2979 // If we need a nested-name-specifier, add one now.
2980 if (!InContext) {
2981 NestedNameSpecifier *NNS
2982 = getRequiredQualification(S.Context, CurContext,
2983 Overridden->getDeclContext());
2984 if (NNS) {
2985 std::string Str;
2986 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00002987 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002988 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002989 }
2990 } else if (!InContext->Equals(Overridden->getDeclContext()))
2991 continue;
2992
Douglas Gregordae68752011-02-01 22:57:45 +00002993 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002994 Overridden->getNameAsString()));
2995 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00002996 bool FirstParam = true;
2997 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2998 PEnd = Method->param_end();
2999 P != PEnd; ++P) {
3000 if (FirstParam)
3001 FirstParam = false;
3002 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003003 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003004
Douglas Gregordae68752011-02-01 22:57:45 +00003005 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003006 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003007 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003008 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3009 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003010 CCP_SuperCompletion,
3011 CXCursor_CXXMethod));
3012 Results.Ignore(Overridden);
3013 }
3014}
3015
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003016void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3017 ModuleIdPath Path) {
3018 typedef CodeCompletionResult Result;
3019 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3020 CodeCompletionContext::CCC_Other);
3021 Results.EnterNewScope();
3022
3023 CodeCompletionAllocator &Allocator = Results.getAllocator();
3024 CodeCompletionBuilder Builder(Allocator);
3025 typedef CodeCompletionResult Result;
3026 if (Path.empty()) {
3027 // Enumerate all top-level modules.
3028 llvm::SmallVector<Module *, 8> Modules;
3029 PP.getHeaderSearchInfo().collectAllModules(Modules);
3030 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3031 Builder.AddTypedTextChunk(
3032 Builder.getAllocator().CopyString(Modules[I]->Name));
3033 Results.AddResult(Result(Builder.TakeString(),
3034 CCP_Declaration,
3035 CXCursor_NotImplemented,
3036 Modules[I]->isAvailable()
3037 ? CXAvailability_Available
3038 : CXAvailability_NotAvailable));
3039 }
3040 } else {
3041 // Load the named module.
3042 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3043 Module::AllVisible,
3044 /*IsInclusionDirective=*/false);
3045 // Enumerate submodules.
3046 if (Mod) {
3047 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3048 SubEnd = Mod->submodule_end();
3049 Sub != SubEnd; ++Sub) {
3050
3051 Builder.AddTypedTextChunk(
3052 Builder.getAllocator().CopyString((*Sub)->Name));
3053 Results.AddResult(Result(Builder.TakeString(),
3054 CCP_Declaration,
3055 CXCursor_NotImplemented,
3056 (*Sub)->isAvailable()
3057 ? CXAvailability_Available
3058 : CXAvailability_NotAvailable));
3059 }
3060 }
3061 }
3062 Results.ExitScope();
3063 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3064 Results.data(),Results.size());
3065}
3066
Douglas Gregor01dfea02010-01-10 23:08:15 +00003067void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003068 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003069 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003070 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003071 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003072 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003073
Douglas Gregor01dfea02010-01-10 23:08:15 +00003074 // Determine how to filter results, e.g., so that the names of
3075 // values (functions, enumerators, function templates, etc.) are
3076 // only allowed where we can have an expression.
3077 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003078 case PCC_Namespace:
3079 case PCC_Class:
3080 case PCC_ObjCInterface:
3081 case PCC_ObjCImplementation:
3082 case PCC_ObjCInstanceVariableList:
3083 case PCC_Template:
3084 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003085 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003086 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003087 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3088 break;
3089
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003090 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003091 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003092 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003093 case PCC_ForInit:
3094 case PCC_Condition:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003095 if (WantTypesInContext(CompletionContext, getLangOptions()))
3096 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3097 else
3098 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003099
3100 if (getLangOptions().CPlusPlus)
3101 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003102 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003103
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003104 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003105 // Unfiltered
3106 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003107 }
3108
Douglas Gregor3cdee122010-08-26 16:36:48 +00003109 // If we are in a C++ non-static member function, check the qualifiers on
3110 // the member function to filter/prioritize the results list.
3111 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3112 if (CurMethod->isInstance())
3113 Results.setObjectTypeQualifiers(
3114 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3115
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003116 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003117 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3118 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003119
Douglas Gregorbca403c2010-01-13 23:51:12 +00003120 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003121 Results.ExitScope();
3122
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003123 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003124 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003125 case PCC_Expression:
3126 case PCC_Statement:
3127 case PCC_RecoveryInFunction:
3128 if (S->getFnParent())
3129 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3130 break;
3131
3132 case PCC_Namespace:
3133 case PCC_Class:
3134 case PCC_ObjCInterface:
3135 case PCC_ObjCImplementation:
3136 case PCC_ObjCInstanceVariableList:
3137 case PCC_Template:
3138 case PCC_MemberTemplate:
3139 case PCC_ForInit:
3140 case PCC_Condition:
3141 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003142 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003143 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003144 }
3145
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003146 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003147 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003148
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003149 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003150 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003151}
3152
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003153static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3154 ParsedType Receiver,
3155 IdentifierInfo **SelIdents,
3156 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003157 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003158 bool IsSuper,
3159 ResultBuilder &Results);
3160
3161void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3162 bool AllowNonIdentifiers,
3163 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003164 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003165 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003166 AllowNestedNameSpecifiers
3167 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3168 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003169 Results.EnterNewScope();
3170
3171 // Type qualifiers can come after names.
3172 Results.AddResult(Result("const"));
3173 Results.AddResult(Result("volatile"));
3174 if (getLangOptions().C99)
3175 Results.AddResult(Result("restrict"));
3176
3177 if (getLangOptions().CPlusPlus) {
3178 if (AllowNonIdentifiers) {
3179 Results.AddResult(Result("operator"));
3180 }
3181
3182 // Add nested-name-specifiers.
3183 if (AllowNestedNameSpecifiers) {
3184 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003185 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003186 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3187 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3188 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003189 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003190 }
3191 }
3192 Results.ExitScope();
3193
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003194 // If we're in a context where we might have an expression (rather than a
3195 // declaration), and what we've seen so far is an Objective-C type that could
3196 // be a receiver of a class message, this may be a class message send with
3197 // the initial opening bracket '[' missing. Add appropriate completions.
3198 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3199 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3200 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3201 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3202 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3203 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3204 DS.getTypeQualifiers() == 0 &&
3205 S &&
3206 (S->getFlags() & Scope::DeclScope) != 0 &&
3207 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3208 Scope::FunctionPrototypeScope |
3209 Scope::AtCatchScope)) == 0) {
3210 ParsedType T = DS.getRepAsType();
3211 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003212 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003213 }
3214
Douglas Gregor4497dd42010-08-24 04:59:56 +00003215 // Note that we intentionally suppress macro results here, since we do not
3216 // encourage using macros to produce the names of entities.
3217
Douglas Gregor52779fb2010-09-23 23:01:17 +00003218 HandleCodeCompleteResults(this, CodeCompleter,
3219 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003220 Results.data(), Results.size());
3221}
3222
Douglas Gregorfb629412010-08-23 21:17:50 +00003223struct Sema::CodeCompleteExpressionData {
3224 CodeCompleteExpressionData(QualType PreferredType = QualType())
3225 : PreferredType(PreferredType), IntegralConstantExpression(false),
3226 ObjCCollection(false) { }
3227
3228 QualType PreferredType;
3229 bool IntegralConstantExpression;
3230 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003231 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003232};
3233
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003234/// \brief Perform code-completion in an expression context when we know what
3235/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00003236///
3237/// \param IntegralConstantExpression Only permit integral constant
3238/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00003239void Sema::CodeCompleteExpression(Scope *S,
3240 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003241 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003242 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3243 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003244 if (Data.ObjCCollection)
3245 Results.setFilter(&ResultBuilder::IsObjCCollection);
3246 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003247 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003248 else if (WantTypesInContext(PCC_Expression, getLangOptions()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003249 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3250 else
3251 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003252
3253 if (!Data.PreferredType.isNull())
3254 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3255
3256 // Ignore any declarations that we were told that we don't care about.
3257 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3258 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003259
3260 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003261 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3262 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003263
3264 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003265 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003266 Results.ExitScope();
3267
Douglas Gregor590c7d52010-07-08 20:55:51 +00003268 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003269 if (!Data.PreferredType.isNull())
3270 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3271 || Data.PreferredType->isMemberPointerType()
3272 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003273
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003274 if (S->getFnParent() &&
3275 !Data.ObjCCollection &&
3276 !Data.IntegralConstantExpression)
3277 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3278
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003279 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003280 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003281 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003282 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3283 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003284 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003285}
3286
Douglas Gregorac5fd842010-09-18 01:28:11 +00003287void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3288 if (E.isInvalid())
3289 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
3290 else if (getLangOptions().ObjC1)
3291 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003292}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003293
Douglas Gregor73449212010-12-09 23:01:55 +00003294/// \brief The set of properties that have already been added, referenced by
3295/// property name.
3296typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3297
Douglas Gregor95ac6552009-11-18 01:29:26 +00003298static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003299 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003300 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003301 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003302 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003303 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003304 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003305
3306 // Add properties in this container.
3307 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3308 PEnd = Container->prop_end();
3309 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003310 ++P) {
3311 if (AddedProperties.insert(P->getIdentifier()))
3312 Results.MaybeAddResult(Result(*P, 0), CurContext);
3313 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003314
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003315 // Add nullary methods
3316 if (AllowNullaryMethods) {
3317 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003318 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003319 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3320 MEnd = Container->meth_end();
3321 M != MEnd; ++M) {
3322 if (M->getSelector().isUnarySelector())
3323 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3324 if (AddedProperties.insert(Name)) {
3325 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor8987b232011-09-27 23:30:47 +00003326 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003327 Builder.AddTypedTextChunk(
3328 Results.getAllocator().CopyString(Name->getName()));
3329
3330 CXAvailabilityKind Availability = CXAvailability_Available;
3331 switch (M->getAvailability()) {
3332 case AR_Available:
3333 case AR_NotYetIntroduced:
3334 Availability = CXAvailability_Available;
3335 break;
3336
3337 case AR_Deprecated:
3338 Availability = CXAvailability_Deprecated;
3339 break;
3340
3341 case AR_Unavailable:
3342 Availability = CXAvailability_NotAvailable;
3343 break;
3344 }
3345
3346 Results.MaybeAddResult(Result(Builder.TakeString(),
3347 CCP_MemberDeclaration + CCD_MethodAsProperty,
3348 M->isInstanceMethod()
3349 ? CXCursor_ObjCInstanceMethodDecl
3350 : CXCursor_ObjCClassMethodDecl,
3351 Availability),
3352 CurContext);
3353 }
3354 }
3355 }
3356
3357
Douglas Gregor95ac6552009-11-18 01:29:26 +00003358 // Add properties in referenced protocols.
3359 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3360 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3361 PEnd = Protocol->protocol_end();
3362 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003363 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3364 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003365 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003366 if (AllowCategories) {
3367 // Look through categories.
3368 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3369 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003370 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3371 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003372 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003373
3374 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003375 for (ObjCInterfaceDecl::all_protocol_iterator
3376 I = IFace->all_referenced_protocol_begin(),
3377 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003378 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3379 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003380
3381 // Look in the superclass.
3382 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003383 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3384 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003385 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003386 } else if (const ObjCCategoryDecl *Category
3387 = dyn_cast<ObjCCategoryDecl>(Container)) {
3388 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003389 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3390 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003391 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003392 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3393 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003394 }
3395}
3396
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003397void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003398 SourceLocation OpLoc,
3399 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003400 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003401 return;
3402
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003403 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3404 if (ConvertedBase.isInvalid())
3405 return;
3406 Base = ConvertedBase.get();
3407
John McCall0a2c5e22010-08-25 06:19:51 +00003408 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003409
Douglas Gregor81b747b2009-09-17 21:32:03 +00003410 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003411
3412 if (IsArrow) {
3413 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3414 BaseType = Ptr->getPointeeType();
3415 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003416 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003417 else
3418 return;
3419 }
3420
Douglas Gregor3da626b2011-07-07 16:03:39 +00003421 enum CodeCompletionContext::Kind contextKind;
3422
3423 if (IsArrow) {
3424 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3425 }
3426 else {
3427 if (BaseType->isObjCObjectPointerType() ||
3428 BaseType->isObjCObjectOrInterfaceType()) {
3429 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3430 }
3431 else {
3432 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3433 }
3434 }
3435
Douglas Gregor218937c2011-02-01 19:23:04 +00003436 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003437 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003438 BaseType),
3439 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003440 Results.EnterNewScope();
3441 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003442 // Indicate that we are performing a member access, and the cv-qualifiers
3443 // for the base object type.
3444 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3445
Douglas Gregor95ac6552009-11-18 01:29:26 +00003446 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003447 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003448 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003449 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3450 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003451
Douglas Gregor95ac6552009-11-18 01:29:26 +00003452 if (getLangOptions().CPlusPlus) {
3453 if (!Results.empty()) {
3454 // The "template" keyword can follow "->" or "." in the grammar.
3455 // However, we only want to suggest the template keyword if something
3456 // is dependent.
3457 bool IsDependent = BaseType->isDependentType();
3458 if (!IsDependent) {
3459 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3460 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3461 IsDependent = Ctx->isDependentContext();
3462 break;
3463 }
3464 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003465
Douglas Gregor95ac6552009-11-18 01:29:26 +00003466 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003467 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003468 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003469 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003470 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3471 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003472 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003473
3474 // Add property results based on our interface.
3475 const ObjCObjectPointerType *ObjCPtr
3476 = BaseType->getAsObjCInterfacePointerType();
3477 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003478 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3479 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003480 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003481
3482 // Add properties from the protocols in a qualified interface.
3483 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3484 E = ObjCPtr->qual_end();
3485 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003486 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3487 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003488 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003489 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003490 // Objective-C instance variable access.
3491 ObjCInterfaceDecl *Class = 0;
3492 if (const ObjCObjectPointerType *ObjCPtr
3493 = BaseType->getAs<ObjCObjectPointerType>())
3494 Class = ObjCPtr->getInterfaceDecl();
3495 else
John McCallc12c5bb2010-05-15 11:32:37 +00003496 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003497
3498 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003499 if (Class) {
3500 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3501 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003502 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3503 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003504 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003505 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003506
3507 // FIXME: How do we cope with isa?
3508
3509 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003510
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003511 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003512 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003513 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003514 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003515}
3516
Douglas Gregor374929f2009-09-18 15:37:17 +00003517void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3518 if (!CodeCompleter)
3519 return;
3520
John McCall0a2c5e22010-08-25 06:19:51 +00003521 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003522 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003523 enum CodeCompletionContext::Kind ContextKind
3524 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003525 switch ((DeclSpec::TST)TagSpec) {
3526 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003527 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003528 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003529 break;
3530
3531 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003532 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003533 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003534 break;
3535
3536 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003537 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003538 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003539 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003540 break;
3541
3542 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003543 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003544 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003545
Douglas Gregor218937c2011-02-01 19:23:04 +00003546 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003547 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003548
3549 // First pass: look for tags.
3550 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003551 LookupVisibleDecls(S, LookupTagName, Consumer,
3552 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003553
Douglas Gregor8071e422010-08-15 06:18:01 +00003554 if (CodeCompleter->includeGlobals()) {
3555 // Second pass: look for nested name specifiers.
3556 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3557 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3558 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003559
Douglas Gregor52779fb2010-09-23 23:01:17 +00003560 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003561 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003562}
3563
Douglas Gregor1a480c42010-08-27 17:35:51 +00003564void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003565 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3566 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003567 Results.EnterNewScope();
3568 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3569 Results.AddResult("const");
3570 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3571 Results.AddResult("volatile");
3572 if (getLangOptions().C99 &&
3573 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3574 Results.AddResult("restrict");
3575 Results.ExitScope();
3576 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003577 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003578 Results.data(), Results.size());
3579}
3580
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003581void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003582 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003583 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003584
John McCall781472f2010-08-25 08:40:02 +00003585 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003586 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3587 if (!type->isEnumeralType()) {
3588 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003589 Data.IntegralConstantExpression = true;
3590 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003591 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003592 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003593
3594 // Code-complete the cases of a switch statement over an enumeration type
3595 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003596 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003597
3598 // Determine which enumerators we have already seen in the switch statement.
3599 // FIXME: Ideally, we would also be able to look *past* the code-completion
3600 // token, in case we are code-completing in the middle of the switch and not
3601 // at the end. However, we aren't able to do so at the moment.
3602 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003603 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003604 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3605 SC = SC->getNextSwitchCase()) {
3606 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3607 if (!Case)
3608 continue;
3609
3610 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3611 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3612 if (EnumConstantDecl *Enumerator
3613 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3614 // We look into the AST of the case statement to determine which
3615 // enumerator was named. Alternatively, we could compute the value of
3616 // the integral constant expression, then compare it against the
3617 // values of each enumerator. However, value-based approach would not
3618 // work as well with C++ templates where enumerators declared within a
3619 // template are type- and value-dependent.
3620 EnumeratorsSeen.insert(Enumerator);
3621
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003622 // If this is a qualified-id, keep track of the nested-name-specifier
3623 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003624 //
3625 // switch (TagD.getKind()) {
3626 // case TagDecl::TK_enum:
3627 // break;
3628 // case XXX
3629 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003630 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003631 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3632 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003633 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003634 }
3635 }
3636
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003637 if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
3638 // If there are no prior enumerators in C++, check whether we have to
3639 // qualify the names of the enumerators that we suggest, because they
3640 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003641 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003642 }
3643
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003644 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003645 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3646 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003647 Results.EnterNewScope();
3648 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3649 EEnd = Enum->enumerator_end();
3650 E != EEnd; ++E) {
3651 if (EnumeratorsSeen.count(*E))
3652 continue;
3653
Douglas Gregor5c722c702011-02-18 23:30:37 +00003654 CodeCompletionResult R(*E, Qualifier);
3655 R.Priority = CCP_EnumInCase;
3656 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003657 }
3658 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003659
Douglas Gregor3da626b2011-07-07 16:03:39 +00003660 //We need to make sure we're setting the right context,
3661 //so only say we include macros if the code completer says we do
3662 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3663 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003664 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003665 kind = CodeCompletionContext::CCC_OtherWithMacros;
3666 }
3667
3668
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003669 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003670 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003671 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003672}
3673
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003674namespace {
3675 struct IsBetterOverloadCandidate {
3676 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003677 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003678
3679 public:
John McCall5769d612010-02-08 23:07:23 +00003680 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3681 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003682
3683 bool
3684 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003685 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003686 }
3687 };
3688}
3689
Douglas Gregord28dcd72010-05-30 06:10:08 +00003690static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
3691 if (NumArgs && !Args)
3692 return true;
3693
3694 for (unsigned I = 0; I != NumArgs; ++I)
3695 if (!Args[I])
3696 return true;
3697
3698 return false;
3699}
3700
Richard Trieuf81e5a92011-09-09 02:00:50 +00003701void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
3702 Expr **ArgsIn, unsigned NumArgs) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003703 if (!CodeCompleter)
3704 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003705
3706 // When we're code-completing for a call, we fall back to ordinary
3707 // name code-completion whenever we can't produce specific
3708 // results. We may want to revisit this strategy in the future,
3709 // e.g., by merging the two kinds of results.
3710
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003711 Expr *Fn = (Expr *)FnIn;
3712 Expr **Args = (Expr **)ArgsIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003713
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003714 // Ignore type-dependent call expressions entirely.
Douglas Gregord28dcd72010-05-30 06:10:08 +00003715 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Douglas Gregoref96eac2009-12-11 19:06:04 +00003716 Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003717 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003718 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003719 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003720
John McCall3b4294e2009-12-16 12:17:52 +00003721 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003722 SourceLocation Loc = Fn->getExprLoc();
3723 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003724
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003725 // FIXME: What if we're calling something that isn't a function declaration?
3726 // FIXME: What if we're calling a pseudo-destructor?
3727 // FIXME: What if we're calling a member function?
3728
Douglas Gregorc0265402010-01-21 15:46:19 +00003729 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003730 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003731
John McCall3b4294e2009-12-16 12:17:52 +00003732 Expr *NakedFn = Fn->IgnoreParenCasts();
3733 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
3734 AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
3735 /*PartialOverloading=*/ true);
3736 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3737 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003738 if (FDecl) {
Douglas Gregord28dcd72010-05-30 06:10:08 +00003739 if (!getLangOptions().CPlusPlus ||
3740 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003741 Results.push_back(ResultCandidate(FDecl));
3742 else
John McCall86820f52010-01-26 01:37:31 +00003743 // FIXME: access?
John McCall9aa472c2010-03-19 07:35:19 +00003744 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
3745 Args, NumArgs, CandidateSet,
Douglas Gregorc27d6c52010-04-16 17:41:49 +00003746 false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003747 }
John McCall3b4294e2009-12-16 12:17:52 +00003748 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003749
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003750 QualType ParamType;
3751
Douglas Gregorc0265402010-01-21 15:46:19 +00003752 if (!CandidateSet.empty()) {
3753 // Sort the overload candidate set by placing the best overloads first.
3754 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003755 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003756
Douglas Gregorc0265402010-01-21 15:46:19 +00003757 // Add the remaining viable overload candidates as code-completion reslults.
3758 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3759 CandEnd = CandidateSet.end();
3760 Cand != CandEnd; ++Cand) {
3761 if (Cand->Viable)
3762 Results.push_back(ResultCandidate(Cand->Function));
3763 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003764
3765 // From the viable candidates, try to determine the type of this parameter.
3766 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3767 if (const FunctionType *FType = Results[I].getFunctionType())
3768 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
3769 if (NumArgs < Proto->getNumArgs()) {
3770 if (ParamType.isNull())
3771 ParamType = Proto->getArgType(NumArgs);
3772 else if (!Context.hasSameUnqualifiedType(
3773 ParamType.getNonReferenceType(),
3774 Proto->getArgType(NumArgs).getNonReferenceType())) {
3775 ParamType = QualType();
3776 break;
3777 }
3778 }
3779 }
3780 } else {
3781 // Try to determine the parameter type from the type of the expression
3782 // being called.
3783 QualType FunctionType = Fn->getType();
3784 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3785 FunctionType = Ptr->getPointeeType();
3786 else if (const BlockPointerType *BlockPtr
3787 = FunctionType->getAs<BlockPointerType>())
3788 FunctionType = BlockPtr->getPointeeType();
3789 else if (const MemberPointerType *MemPtr
3790 = FunctionType->getAs<MemberPointerType>())
3791 FunctionType = MemPtr->getPointeeType();
3792
3793 if (const FunctionProtoType *Proto
3794 = FunctionType->getAs<FunctionProtoType>()) {
3795 if (NumArgs < Proto->getNumArgs())
3796 ParamType = Proto->getArgType(NumArgs);
3797 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003798 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003799
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003800 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003801 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003802 else
3803 CodeCompleteExpression(S, ParamType);
3804
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003805 if (!Results.empty())
Douglas Gregoref96eac2009-12-11 19:06:04 +00003806 CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
3807 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003808}
3809
John McCalld226f652010-08-21 09:40:31 +00003810void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3811 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003812 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003813 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003814 return;
3815 }
3816
3817 CodeCompleteExpression(S, VD->getType());
3818}
3819
3820void Sema::CodeCompleteReturn(Scope *S) {
3821 QualType ResultType;
3822 if (isa<BlockDecl>(CurContext)) {
3823 if (BlockScopeInfo *BSI = getCurBlock())
3824 ResultType = BSI->ReturnType;
3825 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3826 ResultType = Function->getResultType();
3827 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3828 ResultType = Method->getResultType();
3829
3830 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003831 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003832 else
3833 CodeCompleteExpression(S, ResultType);
3834}
3835
Douglas Gregord2d8be62011-07-30 08:36:53 +00003836void Sema::CodeCompleteAfterIf(Scope *S) {
3837 typedef CodeCompletionResult Result;
3838 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3839 mapCodeCompletionContext(*this, PCC_Statement));
3840 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3841 Results.EnterNewScope();
3842
3843 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3844 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3845 CodeCompleter->includeGlobals());
3846
3847 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3848
3849 // "else" block
3850 CodeCompletionBuilder Builder(Results.getAllocator());
3851 Builder.AddTypedTextChunk("else");
3852 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3853 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3854 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3855 Builder.AddPlaceholderChunk("statements");
3856 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3857 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3858 Results.AddResult(Builder.TakeString());
3859
3860 // "else if" block
3861 Builder.AddTypedTextChunk("else");
3862 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3863 Builder.AddTextChunk("if");
3864 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3865 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3866 if (getLangOptions().CPlusPlus)
3867 Builder.AddPlaceholderChunk("condition");
3868 else
3869 Builder.AddPlaceholderChunk("expression");
3870 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3871 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3872 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3873 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3874 Builder.AddPlaceholderChunk("statements");
3875 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3876 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3877 Results.AddResult(Builder.TakeString());
3878
3879 Results.ExitScope();
3880
3881 if (S->getFnParent())
3882 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3883
3884 if (CodeCompleter->includeMacros())
3885 AddMacroResults(PP, Results);
3886
3887 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3888 Results.data(),Results.size());
3889}
3890
Richard Trieuf81e5a92011-09-09 02:00:50 +00003891void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003892 if (LHS)
3893 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3894 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003895 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003896}
3897
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003898void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003899 bool EnteringContext) {
3900 if (!SS.getScopeRep() || !CodeCompleter)
3901 return;
3902
Douglas Gregor86d9a522009-09-21 16:56:56 +00003903 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3904 if (!Ctx)
3905 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003906
3907 // Try to instantiate any non-dependent declaration contexts before
3908 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003909 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003910 return;
3911
Douglas Gregor218937c2011-02-01 19:23:04 +00003912 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3913 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003914 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003915
Douglas Gregor86d9a522009-09-21 16:56:56 +00003916 // The "template" keyword can follow "::" in the grammar, but only
3917 // put it into the grammar if the nested-name-specifier is dependent.
3918 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3919 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003920 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003921
3922 // Add calls to overridden virtual functions, if there are any.
3923 //
3924 // FIXME: This isn't wonderful, because we don't know whether we're actually
3925 // in a context that permits expressions. This is a general issue with
3926 // qualified-id completions.
3927 if (!EnteringContext)
3928 MaybeAddOverrideCalls(*this, Ctx, Results);
3929 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003930
Douglas Gregorf6961522010-08-27 21:18:54 +00003931 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3932 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3933
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003934 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003935 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003936 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003937}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003938
3939void Sema::CodeCompleteUsing(Scope *S) {
3940 if (!CodeCompleter)
3941 return;
3942
Douglas Gregor218937c2011-02-01 19:23:04 +00003943 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003944 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3945 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003946 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003947
3948 // If we aren't in class scope, we could see the "namespace" keyword.
3949 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003950 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003951
3952 // After "using", we can see anything that would start a
3953 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003954 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003955 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3956 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003957 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003958
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003959 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003960 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003961 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003962}
3963
3964void Sema::CodeCompleteUsingDirective(Scope *S) {
3965 if (!CodeCompleter)
3966 return;
3967
Douglas Gregor86d9a522009-09-21 16:56:56 +00003968 // After "using namespace", we expect to see a namespace name or namespace
3969 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003970 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3971 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003972 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003973 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003974 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003975 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3976 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003977 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003978 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003979 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003980 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003981}
3982
3983void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3984 if (!CodeCompleter)
3985 return;
3986
Douglas Gregor86d9a522009-09-21 16:56:56 +00003987 DeclContext *Ctx = (DeclContext *)S->getEntity();
3988 if (!S->getParent())
3989 Ctx = Context.getTranslationUnitDecl();
3990
Douglas Gregor52779fb2010-09-23 23:01:17 +00003991 bool SuppressedGlobalResults
3992 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3993
Douglas Gregor218937c2011-02-01 19:23:04 +00003994 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003995 SuppressedGlobalResults
3996 ? CodeCompletionContext::CCC_Namespace
3997 : CodeCompletionContext::CCC_Other,
3998 &ResultBuilder::IsNamespace);
3999
4000 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004001 // We only want to see those namespaces that have already been defined
4002 // within this scope, because its likely that the user is creating an
4003 // extended namespace declaration. Keep track of the most recent
4004 // definition of each namespace.
4005 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4006 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4007 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4008 NS != NSEnd; ++NS)
4009 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4010
4011 // Add the most recent definition (or extended definition) of each
4012 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004013 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004014 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
4015 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
4016 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004017 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004018 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004019 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004020 }
4021
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004022 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004023 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004024 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004025}
4026
4027void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4028 if (!CodeCompleter)
4029 return;
4030
Douglas Gregor86d9a522009-09-21 16:56:56 +00004031 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004032 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4033 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004034 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004035 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004036 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4037 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004038 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004039 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004040 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004041}
4042
Douglas Gregored8d3222009-09-18 20:05:18 +00004043void Sema::CodeCompleteOperatorName(Scope *S) {
4044 if (!CodeCompleter)
4045 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004046
John McCall0a2c5e22010-08-25 06:19:51 +00004047 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004048 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4049 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004050 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004051 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004052
Douglas Gregor86d9a522009-09-21 16:56:56 +00004053 // Add the names of overloadable operators.
4054#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4055 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004056 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004057#include "clang/Basic/OperatorKinds.def"
4058
4059 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004060 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004061 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004062 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4063 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004064
4065 // Add any type specifiers
Douglas Gregorbca403c2010-01-13 23:51:12 +00004066 AddTypeSpecifierResults(getLangOptions(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004067 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004068
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004069 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004070 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004071 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004072}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004073
Douglas Gregor0133f522010-08-28 00:00:50 +00004074void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004075 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004076 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004077 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004078 CXXConstructorDecl *Constructor
4079 = static_cast<CXXConstructorDecl *>(ConstructorD);
4080 if (!Constructor)
4081 return;
4082
Douglas Gregor218937c2011-02-01 19:23:04 +00004083 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004084 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004085 Results.EnterNewScope();
4086
4087 // Fill in any already-initialized fields or base classes.
4088 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4089 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4090 for (unsigned I = 0; I != NumInitializers; ++I) {
4091 if (Initializers[I]->isBaseInitializer())
4092 InitializedBases.insert(
4093 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4094 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004095 InitializedFields.insert(cast<FieldDecl>(
4096 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004097 }
4098
4099 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00004100 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004101 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004102 CXXRecordDecl *ClassDecl = Constructor->getParent();
4103 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4104 BaseEnd = ClassDecl->bases_end();
4105 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004106 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4107 SawLastInitializer
4108 = NumInitializers > 0 &&
4109 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4110 Context.hasSameUnqualifiedType(Base->getType(),
4111 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004112 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004113 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004114
Douglas Gregor218937c2011-02-01 19:23:04 +00004115 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004116 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004117 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004118 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4119 Builder.AddPlaceholderChunk("args");
4120 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4121 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004122 SawLastInitializer? CCP_NextInitializer
4123 : CCP_MemberDeclaration));
4124 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004125 }
4126
4127 // Add completions for virtual base classes.
4128 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4129 BaseEnd = ClassDecl->vbases_end();
4130 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004131 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4132 SawLastInitializer
4133 = NumInitializers > 0 &&
4134 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4135 Context.hasSameUnqualifiedType(Base->getType(),
4136 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004137 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004138 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004139
Douglas Gregor218937c2011-02-01 19:23:04 +00004140 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004141 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004142 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004143 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4144 Builder.AddPlaceholderChunk("args");
4145 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4146 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004147 SawLastInitializer? CCP_NextInitializer
4148 : CCP_MemberDeclaration));
4149 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004150 }
4151
4152 // Add completions for members.
4153 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4154 FieldEnd = ClassDecl->field_end();
4155 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004156 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4157 SawLastInitializer
4158 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004159 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4160 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004161 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004162 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004163
4164 if (!Field->getDeclName())
4165 continue;
4166
Douglas Gregordae68752011-02-01 22:57:45 +00004167 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004168 Field->getIdentifier()->getName()));
4169 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4170 Builder.AddPlaceholderChunk("args");
4171 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4172 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004173 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004174 : CCP_MemberDeclaration,
4175 CXCursor_MemberRef));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004176 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004177 }
4178 Results.ExitScope();
4179
Douglas Gregor52779fb2010-09-23 23:01:17 +00004180 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004181 Results.data(), Results.size());
4182}
4183
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004184// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4185// true or false.
4186#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00004187static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004188 ResultBuilder &Results,
4189 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004190 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004191 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004192 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004193
Douglas Gregor218937c2011-02-01 19:23:04 +00004194 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004195 if (LangOpts.ObjC2) {
4196 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00004197 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4198 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4199 Builder.AddPlaceholderChunk("property");
4200 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004201
4202 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00004203 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4204 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4205 Builder.AddPlaceholderChunk("property");
4206 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004207 }
4208}
4209
Douglas Gregorbca403c2010-01-13 23:51:12 +00004210static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004211 ResultBuilder &Results,
4212 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004213 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004214
4215 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004216 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004217
4218 if (LangOpts.ObjC2) {
4219 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00004220 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004221
4222 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00004223 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004224
4225 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00004226 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004227 }
4228}
4229
Douglas Gregorbca403c2010-01-13 23:51:12 +00004230static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004231 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004232 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004233
4234 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00004235 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4236 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4237 Builder.AddPlaceholderChunk("name");
4238 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004239
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004240 if (Results.includeCodePatterns()) {
4241 // @interface name
4242 // FIXME: Could introduce the whole pattern, including superclasses and
4243 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00004244 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4245 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4246 Builder.AddPlaceholderChunk("class");
4247 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004248
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004249 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00004250 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4251 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4252 Builder.AddPlaceholderChunk("protocol");
4253 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004254
4255 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00004256 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4257 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4258 Builder.AddPlaceholderChunk("class");
4259 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004260 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004261
4262 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00004263 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4264 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4265 Builder.AddPlaceholderChunk("alias");
4266 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4267 Builder.AddPlaceholderChunk("class");
4268 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004269}
4270
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004271void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004272 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004273 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4274 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004275 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004276 if (isa<ObjCImplDecl>(CurContext))
Douglas Gregorbca403c2010-01-13 23:51:12 +00004277 AddObjCImplementationResults(getLangOptions(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004278 else if (CurContext->isObjCContainer())
Douglas Gregorbca403c2010-01-13 23:51:12 +00004279 AddObjCInterfaceResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004280 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004281 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004282 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004283 HandleCodeCompleteResults(this, CodeCompleter,
4284 CodeCompletionContext::CCC_Other,
4285 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004286}
4287
Douglas Gregorbca403c2010-01-13 23:51:12 +00004288static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004289 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004290 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004291
4292 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004293 const char *EncodeType = "char[]";
4294 if (Results.getSema().getLangOptions().CPlusPlus ||
4295 Results.getSema().getLangOptions().ConstStrings)
4296 EncodeType = " const char[]";
4297 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregor218937c2011-02-01 19:23:04 +00004298 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4299 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4300 Builder.AddPlaceholderChunk("type-name");
4301 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4302 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004303
4304 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004305 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregor218937c2011-02-01 19:23:04 +00004306 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4307 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4308 Builder.AddPlaceholderChunk("protocol-name");
4309 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4310 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004311
4312 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004313 Builder.AddResultTypeChunk("SEL");
Douglas Gregor218937c2011-02-01 19:23:04 +00004314 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4315 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4316 Builder.AddPlaceholderChunk("selector");
4317 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4318 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004319}
4320
Douglas Gregorbca403c2010-01-13 23:51:12 +00004321static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004322 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004323 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004324
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004325 if (Results.includeCodePatterns()) {
4326 // @try { statements } @catch ( declaration ) { statements } @finally
4327 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004328 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4329 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4330 Builder.AddPlaceholderChunk("statements");
4331 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4332 Builder.AddTextChunk("@catch");
4333 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4334 Builder.AddPlaceholderChunk("parameter");
4335 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4336 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4337 Builder.AddPlaceholderChunk("statements");
4338 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4339 Builder.AddTextChunk("@finally");
4340 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4341 Builder.AddPlaceholderChunk("statements");
4342 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4343 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004344 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004345
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004346 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00004347 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4348 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4349 Builder.AddPlaceholderChunk("expression");
4350 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004351
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004352 if (Results.includeCodePatterns()) {
4353 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004354 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4355 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4356 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4357 Builder.AddPlaceholderChunk("expression");
4358 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4359 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4360 Builder.AddPlaceholderChunk("statements");
4361 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4362 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004363 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004364}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004365
Douglas Gregorbca403c2010-01-13 23:51:12 +00004366static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004367 ResultBuilder &Results,
4368 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004369 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00004370 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4371 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4372 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004373 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00004374 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004375}
4376
4377void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004378 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4379 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004380 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004381 AddObjCVisibilityResults(getLangOptions(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004382 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004383 HandleCodeCompleteResults(this, CodeCompleter,
4384 CodeCompletionContext::CCC_Other,
4385 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004386}
4387
4388void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004389 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4390 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004391 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004392 AddObjCStatementResults(Results, false);
4393 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004394 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004395 HandleCodeCompleteResults(this, CodeCompleter,
4396 CodeCompletionContext::CCC_Other,
4397 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004398}
4399
4400void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004401 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4402 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004403 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004404 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004405 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004406 HandleCodeCompleteResults(this, CodeCompleter,
4407 CodeCompletionContext::CCC_Other,
4408 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004409}
4410
Douglas Gregor988358f2009-11-19 00:14:45 +00004411/// \brief Determine whether the addition of the given flag to an Objective-C
4412/// property's attributes will cause a conflict.
4413static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4414 // Check if we've already added this flag.
4415 if (Attributes & NewFlag)
4416 return true;
4417
4418 Attributes |= NewFlag;
4419
4420 // Check for collisions with "readonly".
4421 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4422 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4423 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004424 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004425 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004426 ObjCDeclSpec::DQ_PR_retain |
4427 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004428 return true;
4429
John McCallf85e1932011-06-15 23:02:42 +00004430 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004431 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004432 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004433 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004434 ObjCDeclSpec::DQ_PR_retain|
4435 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004436 if (AssignCopyRetMask &&
4437 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004438 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004439 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004440 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4441 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004442 return true;
4443
4444 return false;
4445}
4446
Douglas Gregora93b1082009-11-18 23:08:07 +00004447void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004448 if (!CodeCompleter)
4449 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004450
Steve Naroffece8e712009-10-08 21:55:05 +00004451 unsigned Attributes = ODS.getPropertyAttributes();
4452
John McCall0a2c5e22010-08-25 06:19:51 +00004453 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004454 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4455 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004456 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004457 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004458 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004459 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004460 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004461 if (!ObjCPropertyFlagConflicts(Attributes,
4462 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4463 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004464 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004465 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004466 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004467 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004468 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4469 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004470 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004471 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004472 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004473 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004474 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4475 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004476 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004477 CodeCompletionBuilder Setter(Results.getAllocator());
4478 Setter.AddTypedTextChunk("setter");
4479 Setter.AddTextChunk(" = ");
4480 Setter.AddPlaceholderChunk("method");
4481 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004482 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004483 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004484 CodeCompletionBuilder Getter(Results.getAllocator());
4485 Getter.AddTypedTextChunk("getter");
4486 Getter.AddTextChunk(" = ");
4487 Getter.AddPlaceholderChunk("method");
4488 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004489 }
Steve Naroffece8e712009-10-08 21:55:05 +00004490 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004491 HandleCodeCompleteResults(this, CodeCompleter,
4492 CodeCompletionContext::CCC_Other,
4493 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004494}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004495
Douglas Gregor4ad96852009-11-19 07:41:15 +00004496/// \brief Descripts the kind of Objective-C method that we want to find
4497/// via code completion.
4498enum ObjCMethodKind {
4499 MK_Any, //< Any kind of method, provided it means other specified criteria.
4500 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4501 MK_OneArgSelector //< One-argument selector.
4502};
4503
Douglas Gregor458433d2010-08-26 15:07:07 +00004504static bool isAcceptableObjCSelector(Selector Sel,
4505 ObjCMethodKind WantKind,
4506 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004507 unsigned NumSelIdents,
4508 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004509 if (NumSelIdents > Sel.getNumArgs())
4510 return false;
4511
4512 switch (WantKind) {
4513 case MK_Any: break;
4514 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4515 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4516 }
4517
Douglas Gregorcf544262010-11-17 21:36:08 +00004518 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4519 return false;
4520
Douglas Gregor458433d2010-08-26 15:07:07 +00004521 for (unsigned I = 0; I != NumSelIdents; ++I)
4522 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4523 return false;
4524
4525 return true;
4526}
4527
Douglas Gregor4ad96852009-11-19 07:41:15 +00004528static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4529 ObjCMethodKind WantKind,
4530 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004531 unsigned NumSelIdents,
4532 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004533 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004534 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004535}
Douglas Gregord36adf52010-09-16 16:06:31 +00004536
4537namespace {
4538 /// \brief A set of selectors, which is used to avoid introducing multiple
4539 /// completions with the same selector into the result set.
4540 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4541}
4542
Douglas Gregor36ecb042009-11-17 23:22:23 +00004543/// \brief Add all of the Objective-C methods in the given Objective-C
4544/// container to the set of results.
4545///
4546/// The container will be a class, protocol, category, or implementation of
4547/// any of the above. This mether will recurse to include methods from
4548/// the superclasses of classes along with their categories, protocols, and
4549/// implementations.
4550///
4551/// \param Container the container in which we'll look to find methods.
4552///
4553/// \param WantInstance whether to add instance methods (only); if false, this
4554/// routine will add factory methods (only).
4555///
4556/// \param CurContext the context in which we're performing the lookup that
4557/// finds methods.
4558///
Douglas Gregorcf544262010-11-17 21:36:08 +00004559/// \param AllowSameLength Whether we allow a method to be added to the list
4560/// when it has the same number of parameters as we have selector identifiers.
4561///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004562/// \param Results the structure into which we'll add results.
4563static void AddObjCMethods(ObjCContainerDecl *Container,
4564 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004565 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004566 IdentifierInfo **SelIdents,
4567 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004568 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004569 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004570 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004571 ResultBuilder &Results,
4572 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004573 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004574 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4575 MEnd = Container->meth_end();
4576 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004577 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4578 // Check whether the selector identifiers we've been given are a
4579 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004580 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4581 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004582 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004583
Douglas Gregord36adf52010-09-16 16:06:31 +00004584 if (!Selectors.insert((*M)->getSelector()))
4585 continue;
4586
Douglas Gregord3c68542009-11-19 01:08:35 +00004587 Result R = Result(*M, 0);
4588 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004589 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004590 if (!InOriginalClass)
4591 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004592 Results.MaybeAddResult(R, CurContext);
4593 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004594 }
4595
Douglas Gregore396c7b2010-09-16 15:34:59 +00004596 // Visit the protocols of protocols.
4597 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004598 if (Protocol->hasDefinition()) {
4599 const ObjCList<ObjCProtocolDecl> &Protocols
4600 = Protocol->getReferencedProtocols();
4601 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4602 E = Protocols.end();
4603 I != E; ++I)
4604 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4605 NumSelIdents, CurContext, Selectors, AllowSameLength,
4606 Results, false);
4607 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004608 }
4609
Douglas Gregor36ecb042009-11-17 23:22:23 +00004610 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004611 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004612 return;
4613
4614 // Add methods in protocols.
4615 const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
4616 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4617 E = Protocols.end();
4618 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004619 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004620 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004621
4622 // Add methods in categories.
4623 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4624 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004625 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004626 NumSelIdents, CurContext, Selectors, AllowSameLength,
4627 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004628
4629 // Add a categories protocol methods.
4630 const ObjCList<ObjCProtocolDecl> &Protocols
4631 = CatDecl->getReferencedProtocols();
4632 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4633 E = Protocols.end();
4634 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004635 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004636 NumSelIdents, CurContext, Selectors, AllowSameLength,
4637 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004638
4639 // Add methods in category implementations.
4640 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004641 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004642 NumSelIdents, CurContext, Selectors, AllowSameLength,
4643 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004644 }
4645
4646 // Add methods in superclass.
4647 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004648 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004649 SelIdents, NumSelIdents, CurContext, Selectors,
4650 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004651
4652 // Add methods in our implementation, if any.
4653 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004654 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004655 NumSelIdents, CurContext, Selectors, AllowSameLength,
4656 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004657}
4658
4659
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004660void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004661 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004662
4663 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004664 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004665 if (!Class) {
4666 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004667 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004668 Class = Category->getClassInterface();
4669
4670 if (!Class)
4671 return;
4672 }
4673
4674 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004675 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4676 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004677 Results.EnterNewScope();
4678
Douglas Gregord36adf52010-09-16 16:06:31 +00004679 VisitedSelectorSet Selectors;
4680 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004681 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004682 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004683 HandleCodeCompleteResults(this, CodeCompleter,
4684 CodeCompletionContext::CCC_Other,
4685 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004686}
4687
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004688void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004689 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004690
4691 // Try to find the interface where setters might live.
4692 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004693 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004694 if (!Class) {
4695 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004696 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004697 Class = Category->getClassInterface();
4698
4699 if (!Class)
4700 return;
4701 }
4702
4703 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004704 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4705 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004706 Results.EnterNewScope();
4707
Douglas Gregord36adf52010-09-16 16:06:31 +00004708 VisitedSelectorSet Selectors;
4709 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004710 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004711
4712 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004713 HandleCodeCompleteResults(this, CodeCompleter,
4714 CodeCompletionContext::CCC_Other,
4715 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004716}
4717
Douglas Gregorafc45782011-02-15 22:19:42 +00004718void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4719 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004720 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004721 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4722 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004723 Results.EnterNewScope();
4724
4725 // Add context-sensitive, Objective-C parameter-passing keywords.
4726 bool AddedInOut = false;
4727 if ((DS.getObjCDeclQualifier() &
4728 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4729 Results.AddResult("in");
4730 Results.AddResult("inout");
4731 AddedInOut = true;
4732 }
4733 if ((DS.getObjCDeclQualifier() &
4734 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4735 Results.AddResult("out");
4736 if (!AddedInOut)
4737 Results.AddResult("inout");
4738 }
4739 if ((DS.getObjCDeclQualifier() &
4740 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4741 ObjCDeclSpec::DQ_Oneway)) == 0) {
4742 Results.AddResult("bycopy");
4743 Results.AddResult("byref");
4744 Results.AddResult("oneway");
4745 }
4746
Douglas Gregorafc45782011-02-15 22:19:42 +00004747 // If we're completing the return type of an Objective-C method and the
4748 // identifier IBAction refers to a macro, provide a completion item for
4749 // an action, e.g.,
4750 // IBAction)<#selector#>:(id)sender
4751 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4752 Context.Idents.get("IBAction").hasMacroDefinition()) {
4753 typedef CodeCompletionString::Chunk Chunk;
4754 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4755 CXAvailability_Available);
4756 Builder.AddTypedTextChunk("IBAction");
4757 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4758 Builder.AddPlaceholderChunk("selector");
4759 Builder.AddChunk(Chunk(CodeCompletionString::CK_Colon));
4760 Builder.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
4761 Builder.AddTextChunk("id");
4762 Builder.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
4763 Builder.AddTextChunk("sender");
4764 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4765 }
4766
Douglas Gregord32b0222010-08-24 01:06:58 +00004767 // Add various builtin type names and specifiers.
4768 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4769 Results.ExitScope();
4770
4771 // Add the various type names
4772 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4773 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4774 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4775 CodeCompleter->includeGlobals());
4776
4777 if (CodeCompleter->includeMacros())
4778 AddMacroResults(PP, Results);
4779
4780 HandleCodeCompleteResults(this, CodeCompleter,
4781 CodeCompletionContext::CCC_Type,
4782 Results.data(), Results.size());
4783}
4784
Douglas Gregor22f56992010-04-06 19:22:33 +00004785/// \brief When we have an expression with type "id", we may assume
4786/// that it has some more-specific class type based on knowledge of
4787/// common uses of Objective-C. This routine returns that class type,
4788/// or NULL if no better result could be determined.
4789static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004790 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004791 if (!Msg)
4792 return 0;
4793
4794 Selector Sel = Msg->getSelector();
4795 if (Sel.isNull())
4796 return 0;
4797
4798 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4799 if (!Id)
4800 return 0;
4801
4802 ObjCMethodDecl *Method = Msg->getMethodDecl();
4803 if (!Method)
4804 return 0;
4805
4806 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004807 ObjCInterfaceDecl *IFace = 0;
4808 switch (Msg->getReceiverKind()) {
4809 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004810 if (const ObjCObjectType *ObjType
4811 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4812 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004813 break;
4814
4815 case ObjCMessageExpr::Instance: {
4816 QualType T = Msg->getInstanceReceiver()->getType();
4817 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4818 IFace = Ptr->getInterfaceDecl();
4819 break;
4820 }
4821
4822 case ObjCMessageExpr::SuperInstance:
4823 case ObjCMessageExpr::SuperClass:
4824 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004825 }
4826
4827 if (!IFace)
4828 return 0;
4829
4830 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4831 if (Method->isInstanceMethod())
4832 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4833 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00004834 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00004835 .Case("autorelease", IFace)
4836 .Case("copy", IFace)
4837 .Case("copyWithZone", IFace)
4838 .Case("mutableCopy", IFace)
4839 .Case("mutableCopyWithZone", IFace)
4840 .Case("awakeFromCoder", IFace)
4841 .Case("replacementObjectFromCoder", IFace)
4842 .Case("class", IFace)
4843 .Case("classForCoder", IFace)
4844 .Case("superclass", Super)
4845 .Default(0);
4846
4847 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4848 .Case("new", IFace)
4849 .Case("alloc", IFace)
4850 .Case("allocWithZone", IFace)
4851 .Case("class", IFace)
4852 .Case("superclass", Super)
4853 .Default(0);
4854}
4855
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004856// Add a special completion for a message send to "super", which fills in the
4857// most likely case of forwarding all of our arguments to the superclass
4858// function.
4859///
4860/// \param S The semantic analysis object.
4861///
4862/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4863/// the "super" keyword. Otherwise, we just need to provide the arguments.
4864///
4865/// \param SelIdents The identifiers in the selector that have already been
4866/// provided as arguments for a send to "super".
4867///
4868/// \param NumSelIdents The number of identifiers in \p SelIdents.
4869///
4870/// \param Results The set of results to augment.
4871///
4872/// \returns the Objective-C method declaration that would be invoked by
4873/// this "super" completion. If NULL, no completion was added.
4874static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4875 IdentifierInfo **SelIdents,
4876 unsigned NumSelIdents,
4877 ResultBuilder &Results) {
4878 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4879 if (!CurMethod)
4880 return 0;
4881
4882 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4883 if (!Class)
4884 return 0;
4885
4886 // Try to find a superclass method with the same selector.
4887 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00004888 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4889 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004890 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4891 CurMethod->isInstanceMethod());
4892
Douglas Gregor78bcd912011-02-16 00:51:18 +00004893 // Check in categories or class extensions.
4894 if (!SuperMethod) {
4895 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4896 Category = Category->getNextClassCategory())
4897 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4898 CurMethod->isInstanceMethod())))
4899 break;
4900 }
4901 }
4902
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004903 if (!SuperMethod)
4904 return 0;
4905
4906 // Check whether the superclass method has the same signature.
4907 if (CurMethod->param_size() != SuperMethod->param_size() ||
4908 CurMethod->isVariadic() != SuperMethod->isVariadic())
4909 return 0;
4910
4911 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4912 CurPEnd = CurMethod->param_end(),
4913 SuperP = SuperMethod->param_begin();
4914 CurP != CurPEnd; ++CurP, ++SuperP) {
4915 // Make sure the parameter types are compatible.
4916 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4917 (*SuperP)->getType()))
4918 return 0;
4919
4920 // Make sure we have a parameter name to forward!
4921 if (!(*CurP)->getIdentifier())
4922 return 0;
4923 }
4924
4925 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00004926 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004927
4928 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00004929 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
4930 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004931
4932 // If we need the "super" keyword, add it (plus some spacing).
4933 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004934 Builder.AddTypedTextChunk("super");
4935 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004936 }
4937
4938 Selector Sel = CurMethod->getSelector();
4939 if (Sel.isUnarySelector()) {
4940 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00004941 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004942 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004943 else
Douglas Gregordae68752011-02-01 22:57:45 +00004944 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004945 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004946 } else {
4947 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
4948 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
4949 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004950 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004951
4952 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004953 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004954 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004955 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004956 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004957 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004958 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004959 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004960 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004961 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004962 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00004963 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004964 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00004965 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004966 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004967 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004968 }
4969 }
4970 }
4971
Douglas Gregor218937c2011-02-01 19:23:04 +00004972 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004973 SuperMethod->isInstanceMethod()
4974 ? CXCursor_ObjCInstanceMethodDecl
4975 : CXCursor_ObjCClassMethodDecl));
4976 return SuperMethod;
4977}
4978
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004979void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004980 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004981 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4982 CodeCompletionContext::CCC_ObjCMessageReceiver,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004983 &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004984
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004985 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4986 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00004987 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4988 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004989
4990 // If we are in an Objective-C method inside a class that has a superclass,
4991 // add "super" as an option.
4992 if (ObjCMethodDecl *Method = getCurMethodDecl())
4993 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004994 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004995 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004996
4997 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
4998 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004999
5000 Results.ExitScope();
5001
5002 if (CodeCompleter->includeMacros())
5003 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005004 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005005 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005006
5007}
5008
Douglas Gregor2725ca82010-04-21 19:57:20 +00005009void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5010 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005011 unsigned NumSelIdents,
5012 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005013 ObjCInterfaceDecl *CDecl = 0;
5014 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5015 // Figure out which interface we're in.
5016 CDecl = CurMethod->getClassInterface();
5017 if (!CDecl)
5018 return;
5019
5020 // Find the superclass of this class.
5021 CDecl = CDecl->getSuperClass();
5022 if (!CDecl)
5023 return;
5024
5025 if (CurMethod->isInstanceMethod()) {
5026 // We are inside an instance method, which means that the message
5027 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005028 // current object.
5029 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005030 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005031 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005032 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005033 }
5034
5035 // Fall through to send to the superclass in CDecl.
5036 } else {
5037 // "super" may be the name of a type or variable. Figure out which
5038 // it is.
5039 IdentifierInfo *Super = &Context.Idents.get("super");
5040 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5041 LookupOrdinaryName);
5042 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5043 // "super" names an interface. Use it.
5044 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005045 if (const ObjCObjectType *Iface
5046 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5047 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005048 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5049 // "super" names an unresolved type; we can't be more specific.
5050 } else {
5051 // Assume that "super" names some kind of value and parse that way.
5052 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005053 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005054 UnqualifiedId id;
5055 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005056 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5057 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005058 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005059 SelIdents, NumSelIdents,
5060 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005061 }
5062
5063 // Fall through
5064 }
5065
John McCallb3d87482010-08-24 05:47:05 +00005066 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005067 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005068 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005069 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005070 NumSelIdents, AtArgumentExpression,
5071 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005072}
5073
Douglas Gregorb9d77572010-09-21 00:03:25 +00005074/// \brief Given a set of code-completion results for the argument of a message
5075/// send, determine the preferred type (if any) for that argument expression.
5076static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5077 unsigned NumSelIdents) {
5078 typedef CodeCompletionResult Result;
5079 ASTContext &Context = Results.getSema().Context;
5080
5081 QualType PreferredType;
5082 unsigned BestPriority = CCP_Unlikely * 2;
5083 Result *ResultsData = Results.data();
5084 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5085 Result &R = ResultsData[I];
5086 if (R.Kind == Result::RK_Declaration &&
5087 isa<ObjCMethodDecl>(R.Declaration)) {
5088 if (R.Priority <= BestPriority) {
5089 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5090 if (NumSelIdents <= Method->param_size()) {
5091 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5092 ->getType();
5093 if (R.Priority < BestPriority || PreferredType.isNull()) {
5094 BestPriority = R.Priority;
5095 PreferredType = MyPreferredType;
5096 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5097 MyPreferredType)) {
5098 PreferredType = QualType();
5099 }
5100 }
5101 }
5102 }
5103 }
5104
5105 return PreferredType;
5106}
5107
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005108static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5109 ParsedType Receiver,
5110 IdentifierInfo **SelIdents,
5111 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005112 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005113 bool IsSuper,
5114 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005115 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005116 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005117
Douglas Gregor24a069f2009-11-17 17:59:40 +00005118 // If the given name refers to an interface type, retrieve the
5119 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005120 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005121 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005122 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005123 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5124 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005125 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005126
Douglas Gregor36ecb042009-11-17 23:22:23 +00005127 // Add all of the factory methods in this Objective-C class, its protocols,
5128 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005129 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005130
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005131 // If this is a send-to-super, try to add the special "super" send
5132 // completion.
5133 if (IsSuper) {
5134 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005135 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5136 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005137 Results.Ignore(SuperMethod);
5138 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005139
Douglas Gregor265f7492010-08-27 15:29:55 +00005140 // If we're inside an Objective-C method definition, prefer its selector to
5141 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005142 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005143 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005144
Douglas Gregord36adf52010-09-16 16:06:31 +00005145 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005146 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005147 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005148 SemaRef.CurContext, Selectors, AtArgumentExpression,
5149 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005150 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005151 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005152
Douglas Gregor719770d2010-04-06 17:30:22 +00005153 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005154 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005155 if (SemaRef.ExternalSource) {
5156 for (uint32_t I = 0,
5157 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005158 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005159 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5160 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005161 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005162
5163 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005164 }
5165 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005166
5167 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5168 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005169 M != MEnd; ++M) {
5170 for (ObjCMethodList *MethList = &M->second.second;
5171 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005172 MethList = MethList->Next) {
5173 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5174 NumSelIdents))
5175 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005176
Douglas Gregor13438f92010-04-06 16:40:00 +00005177 Result R(MethList->Method, 0);
5178 R.StartParameter = NumSelIdents;
5179 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005180 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005181 }
5182 }
5183 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005184
5185 Results.ExitScope();
5186}
Douglas Gregor13438f92010-04-06 16:40:00 +00005187
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005188void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5189 IdentifierInfo **SelIdents,
5190 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005191 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005192 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005193
5194 QualType T = this->GetTypeFromParser(Receiver);
5195
Douglas Gregor218937c2011-02-01 19:23:04 +00005196 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005197 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005198 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005199
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005200 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5201 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005202
5203 // If we're actually at the argument expression (rather than prior to the
5204 // selector), we're actually performing code completion for an expression.
5205 // Determine whether we have a single, best method. If so, we can
5206 // code-complete the expression using the corresponding parameter type as
5207 // our preferred type, improving completion results.
5208 if (AtArgumentExpression) {
5209 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005210 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005211 if (PreferredType.isNull())
5212 CodeCompleteOrdinaryName(S, PCC_Expression);
5213 else
5214 CodeCompleteExpression(S, PreferredType);
5215 return;
5216 }
5217
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005218 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005219 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005220 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005221}
5222
Richard Trieuf81e5a92011-09-09 02:00:50 +00005223void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005224 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005225 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005226 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005227 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005228 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005229
5230 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005231
Douglas Gregor36ecb042009-11-17 23:22:23 +00005232 // If necessary, apply function/array conversion to the receiver.
5233 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005234 if (RecExpr) {
5235 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5236 if (Conv.isInvalid()) // conversion failed. bail.
5237 return;
5238 RecExpr = Conv.take();
5239 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005240 QualType ReceiverType = RecExpr? RecExpr->getType()
5241 : Super? Context.getObjCObjectPointerType(
5242 Context.getObjCInterfaceType(Super))
5243 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005244
Douglas Gregorda892642010-11-08 21:12:30 +00005245 // If we're messaging an expression with type "id" or "Class", check
5246 // whether we know something special about the receiver that allows
5247 // us to assume a more-specific receiver type.
5248 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5249 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5250 if (ReceiverType->isObjCClassType())
5251 return CodeCompleteObjCClassMessage(S,
5252 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5253 SelIdents, NumSelIdents,
5254 AtArgumentExpression, Super);
5255
5256 ReceiverType = Context.getObjCObjectPointerType(
5257 Context.getObjCInterfaceType(IFace));
5258 }
5259
Douglas Gregor36ecb042009-11-17 23:22:23 +00005260 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005261 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregore081a612011-07-21 01:05:26 +00005262 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005263 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005264
Douglas Gregor36ecb042009-11-17 23:22:23 +00005265 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005266
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005267 // If this is a send-to-super, try to add the special "super" send
5268 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005269 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005270 if (ObjCMethodDecl *SuperMethod
5271 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5272 Results))
5273 Results.Ignore(SuperMethod);
5274 }
5275
Douglas Gregor265f7492010-08-27 15:29:55 +00005276 // If we're inside an Objective-C method definition, prefer its selector to
5277 // others.
5278 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5279 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005280
Douglas Gregord36adf52010-09-16 16:06:31 +00005281 // Keep track of the selectors we've already added.
5282 VisitedSelectorSet Selectors;
5283
Douglas Gregorf74a4192009-11-18 00:06:18 +00005284 // Handle messages to Class. This really isn't a message to an instance
5285 // method, so we treat it the same way we would treat a message send to a
5286 // class method.
5287 if (ReceiverType->isObjCClassType() ||
5288 ReceiverType->isObjCQualifiedClassType()) {
5289 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5290 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005291 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005292 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005293 }
5294 }
5295 // Handle messages to a qualified ID ("id<foo>").
5296 else if (const ObjCObjectPointerType *QualID
5297 = ReceiverType->getAsObjCQualifiedIdType()) {
5298 // Search protocols for instance methods.
5299 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5300 E = QualID->qual_end();
5301 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005302 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005303 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005304 }
5305 // Handle messages to a pointer to interface type.
5306 else if (const ObjCObjectPointerType *IFacePtr
5307 = ReceiverType->getAsObjCInterfacePointerType()) {
5308 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005309 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005310 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5311 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005312
5313 // Search protocols for instance methods.
5314 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5315 E = IFacePtr->qual_end();
5316 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005317 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005318 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005319 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005320 // Handle messages to "id".
5321 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005322 // We're messaging "id", so provide all instance methods we know
5323 // about as code-completion results.
5324
5325 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005326 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005327 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005328 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5329 I != N; ++I) {
5330 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005331 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005332 continue;
5333
Sebastian Redldb9d2142010-08-02 23:18:59 +00005334 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005335 }
5336 }
5337
Sebastian Redldb9d2142010-08-02 23:18:59 +00005338 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5339 MEnd = MethodPool.end();
5340 M != MEnd; ++M) {
5341 for (ObjCMethodList *MethList = &M->second.first;
5342 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005343 MethList = MethList->Next) {
5344 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5345 NumSelIdents))
5346 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005347
5348 if (!Selectors.insert(MethList->Method->getSelector()))
5349 continue;
5350
Douglas Gregor13438f92010-04-06 16:40:00 +00005351 Result R(MethList->Method, 0);
5352 R.StartParameter = NumSelIdents;
5353 R.AllParametersAreInformative = false;
5354 Results.MaybeAddResult(R, CurContext);
5355 }
5356 }
5357 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005358 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005359
5360
5361 // If we're actually at the argument expression (rather than prior to the
5362 // selector), we're actually performing code completion for an expression.
5363 // Determine whether we have a single, best method. If so, we can
5364 // code-complete the expression using the corresponding parameter type as
5365 // our preferred type, improving completion results.
5366 if (AtArgumentExpression) {
5367 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5368 NumSelIdents);
5369 if (PreferredType.isNull())
5370 CodeCompleteOrdinaryName(S, PCC_Expression);
5371 else
5372 CodeCompleteExpression(S, PreferredType);
5373 return;
5374 }
5375
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005376 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005377 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005378 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005379}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005380
Douglas Gregorfb629412010-08-23 21:17:50 +00005381void Sema::CodeCompleteObjCForCollection(Scope *S,
5382 DeclGroupPtrTy IterationVar) {
5383 CodeCompleteExpressionData Data;
5384 Data.ObjCCollection = true;
5385
5386 if (IterationVar.getAsOpaquePtr()) {
5387 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5388 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5389 if (*I)
5390 Data.IgnoreDecls.push_back(*I);
5391 }
5392 }
5393
5394 CodeCompleteExpression(S, Data);
5395}
5396
Douglas Gregor458433d2010-08-26 15:07:07 +00005397void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5398 unsigned NumSelIdents) {
5399 // If we have an external source, load the entire class method
5400 // pool from the AST file.
5401 if (ExternalSource) {
5402 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5403 I != N; ++I) {
5404 Selector Sel = ExternalSource->GetExternalSelector(I);
5405 if (Sel.isNull() || MethodPool.count(Sel))
5406 continue;
5407
5408 ReadMethodPool(Sel);
5409 }
5410 }
5411
Douglas Gregor218937c2011-02-01 19:23:04 +00005412 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5413 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005414 Results.EnterNewScope();
5415 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5416 MEnd = MethodPool.end();
5417 M != MEnd; ++M) {
5418
5419 Selector Sel = M->first;
5420 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5421 continue;
5422
Douglas Gregor218937c2011-02-01 19:23:04 +00005423 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00005424 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005425 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005426 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005427 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005428 continue;
5429 }
5430
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005431 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005432 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005433 if (I == NumSelIdents) {
5434 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005435 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005436 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005437 Accumulator.clear();
5438 }
5439 }
5440
Benjamin Kramera0651c52011-07-26 16:59:25 +00005441 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005442 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005443 }
Douglas Gregordae68752011-02-01 22:57:45 +00005444 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005445 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005446 }
5447 Results.ExitScope();
5448
5449 HandleCodeCompleteResults(this, CodeCompleter,
5450 CodeCompletionContext::CCC_SelectorName,
5451 Results.data(), Results.size());
5452}
5453
Douglas Gregor55385fe2009-11-18 04:19:12 +00005454/// \brief Add all of the protocol declarations that we find in the given
5455/// (translation unit) context.
5456static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005457 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005458 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005459 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005460
5461 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5462 DEnd = Ctx->decls_end();
5463 D != DEnd; ++D) {
5464 // Record any protocols we find.
5465 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005466 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005467 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005468 }
5469}
5470
5471void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5472 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005473 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5474 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005475
Douglas Gregor70c23352010-12-09 21:44:02 +00005476 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5477 Results.EnterNewScope();
5478
5479 // Tell the result set to ignore all of the protocols we have
5480 // already seen.
5481 // FIXME: This doesn't work when caching code-completion results.
5482 for (unsigned I = 0; I != NumProtocols; ++I)
5483 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5484 Protocols[I].second))
5485 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005486
Douglas Gregor70c23352010-12-09 21:44:02 +00005487 // Add all protocols.
5488 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5489 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005490
Douglas Gregor70c23352010-12-09 21:44:02 +00005491 Results.ExitScope();
5492 }
5493
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005494 HandleCodeCompleteResults(this, CodeCompleter,
5495 CodeCompletionContext::CCC_ObjCProtocolName,
5496 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005497}
5498
5499void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005500 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5501 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005502
Douglas Gregor70c23352010-12-09 21:44:02 +00005503 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5504 Results.EnterNewScope();
5505
5506 // Add all protocols.
5507 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5508 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005509
Douglas Gregor70c23352010-12-09 21:44:02 +00005510 Results.ExitScope();
5511 }
5512
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005513 HandleCodeCompleteResults(this, CodeCompleter,
5514 CodeCompletionContext::CCC_ObjCProtocolName,
5515 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005516}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005517
5518/// \brief Add all of the Objective-C interface declarations that we find in
5519/// the given (translation unit) context.
5520static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5521 bool OnlyForwardDeclarations,
5522 bool OnlyUnimplemented,
5523 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005524 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005525
5526 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5527 DEnd = Ctx->decls_end();
5528 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005529 // Record any interfaces we find.
5530 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005531 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005532 (!OnlyUnimplemented || !Class->getImplementation()))
5533 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005534 }
5535}
5536
5537void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005538 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5539 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005540 Results.EnterNewScope();
5541
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005542 if (CodeCompleter->includeGlobals()) {
5543 // Add all classes.
5544 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5545 false, Results);
5546 }
5547
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005548 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005549
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005550 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005551 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005552 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005553}
5554
Douglas Gregorc83c6872010-04-15 22:33:43 +00005555void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5556 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005557 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005558 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005559 Results.EnterNewScope();
5560
5561 // Make sure that we ignore the class we're currently defining.
5562 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005563 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005564 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005565 Results.Ignore(CurClass);
5566
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005567 if (CodeCompleter->includeGlobals()) {
5568 // Add all classes.
5569 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5570 false, Results);
5571 }
5572
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005573 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005574
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005575 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005576 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005577 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005578}
5579
5580void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005581 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5582 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005583 Results.EnterNewScope();
5584
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005585 if (CodeCompleter->includeGlobals()) {
5586 // Add all unimplemented classes.
5587 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5588 true, Results);
5589 }
5590
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005591 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005592
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005593 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005594 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005595 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005596}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005597
5598void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005599 IdentifierInfo *ClassName,
5600 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005601 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005602
Douglas Gregor218937c2011-02-01 19:23:04 +00005603 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005604 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005605
5606 // Ignore any categories we find that have already been implemented by this
5607 // interface.
5608 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5609 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005610 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005611 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5612 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5613 Category = Category->getNextClassCategory())
5614 CategoryNames.insert(Category->getIdentifier());
5615
5616 // Add all of the categories we know about.
5617 Results.EnterNewScope();
5618 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5619 for (DeclContext::decl_iterator D = TU->decls_begin(),
5620 DEnd = TU->decls_end();
5621 D != DEnd; ++D)
5622 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5623 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005624 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005625 Results.ExitScope();
5626
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005627 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005628 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005629 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005630}
5631
5632void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005633 IdentifierInfo *ClassName,
5634 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005635 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005636
5637 // Find the corresponding interface. If we couldn't find the interface, the
5638 // program itself is ill-formed. However, we'll try to be helpful still by
5639 // providing the list of all of the categories we know about.
5640 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005641 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005642 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5643 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005644 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005645
Douglas Gregor218937c2011-02-01 19:23:04 +00005646 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005647 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005648
5649 // Add all of the categories that have have corresponding interface
5650 // declarations in this class and any of its superclasses, except for
5651 // already-implemented categories in the class itself.
5652 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5653 Results.EnterNewScope();
5654 bool IgnoreImplemented = true;
5655 while (Class) {
5656 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5657 Category = Category->getNextClassCategory())
5658 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5659 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005660 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005661
5662 Class = Class->getSuperClass();
5663 IgnoreImplemented = false;
5664 }
5665 Results.ExitScope();
5666
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005667 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005668 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005669 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005670}
Douglas Gregor322328b2009-11-18 22:32:06 +00005671
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005672void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005673 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005674 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5675 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005676
5677 // Figure out where this @synthesize lives.
5678 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005679 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005680 if (!Container ||
5681 (!isa<ObjCImplementationDecl>(Container) &&
5682 !isa<ObjCCategoryImplDecl>(Container)))
5683 return;
5684
5685 // Ignore any properties that have already been implemented.
5686 for (DeclContext::decl_iterator D = Container->decls_begin(),
5687 DEnd = Container->decls_end();
5688 D != DEnd; ++D)
5689 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5690 Results.Ignore(PropertyImpl->getPropertyDecl());
5691
5692 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005693 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005694 Results.EnterNewScope();
5695 if (ObjCImplementationDecl *ClassImpl
5696 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005697 AddObjCProperties(ClassImpl->getClassInterface(), false,
5698 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005699 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005700 else
5701 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005702 false, /*AllowNullaryMethods=*/false, CurContext,
5703 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005704 Results.ExitScope();
5705
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005706 HandleCodeCompleteResults(this, CodeCompleter,
5707 CodeCompletionContext::CCC_Other,
5708 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005709}
5710
5711void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005712 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005713 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005714 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5715 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005716
5717 // Figure out where this @synthesize lives.
5718 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005719 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005720 if (!Container ||
5721 (!isa<ObjCImplementationDecl>(Container) &&
5722 !isa<ObjCCategoryImplDecl>(Container)))
5723 return;
5724
5725 // Figure out which interface we're looking into.
5726 ObjCInterfaceDecl *Class = 0;
5727 if (ObjCImplementationDecl *ClassImpl
5728 = dyn_cast<ObjCImplementationDecl>(Container))
5729 Class = ClassImpl->getClassInterface();
5730 else
5731 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5732 ->getClassInterface();
5733
Douglas Gregore8426052011-04-18 14:40:46 +00005734 // Determine the type of the property we're synthesizing.
5735 QualType PropertyType = Context.getObjCIdType();
5736 if (Class) {
5737 if (ObjCPropertyDecl *Property
5738 = Class->FindPropertyDeclaration(PropertyName)) {
5739 PropertyType
5740 = Property->getType().getNonReferenceType().getUnqualifiedType();
5741
5742 // Give preference to ivars
5743 Results.setPreferredType(PropertyType);
5744 }
5745 }
5746
Douglas Gregor322328b2009-11-18 22:32:06 +00005747 // Add all of the instance variables in this class and its superclasses.
5748 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005749 bool SawSimilarlyNamedIvar = false;
5750 std::string NameWithPrefix;
5751 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005752 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005753 std::string NameWithSuffix = PropertyName->getName().str();
5754 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005755 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005756 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5757 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005758 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5759
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005760 // Determine whether we've seen an ivar with a name similar to the
5761 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005762 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005763 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005764 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005765 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005766
5767 // Reduce the priority of this result by one, to give it a slight
5768 // advantage over other results whose names don't match so closely.
5769 if (Results.size() &&
5770 Results.data()[Results.size() - 1].Kind
5771 == CodeCompletionResult::RK_Declaration &&
5772 Results.data()[Results.size() - 1].Declaration == Ivar)
5773 Results.data()[Results.size() - 1].Priority--;
5774 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005775 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005776 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005777
5778 if (!SawSimilarlyNamedIvar) {
5779 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005780 // an ivar of the appropriate type.
5781 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005782 typedef CodeCompletionResult Result;
5783 CodeCompletionAllocator &Allocator = Results.getAllocator();
5784 CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
5785
Douglas Gregor8987b232011-09-27 23:30:47 +00005786 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005787 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005788 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005789 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5790 Results.AddResult(Result(Builder.TakeString(), Priority,
5791 CXCursor_ObjCIvarDecl));
5792 }
5793
Douglas Gregor322328b2009-11-18 22:32:06 +00005794 Results.ExitScope();
5795
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005796 HandleCodeCompleteResults(this, CodeCompleter,
5797 CodeCompletionContext::CCC_Other,
5798 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005799}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005800
Douglas Gregor408be5a2010-08-25 01:08:01 +00005801// Mapping from selectors to the methods that implement that selector, along
5802// with the "in original class" flag.
5803typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5804 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005805
5806/// \brief Find all of the methods that reside in the given container
5807/// (and its superclasses, protocols, etc.) that meet the given
5808/// criteria. Insert those methods into the map of known methods,
5809/// indexed by selector so they can be easily found.
5810static void FindImplementableMethods(ASTContext &Context,
5811 ObjCContainerDecl *Container,
5812 bool WantInstanceMethods,
5813 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005814 KnownMethodsMap &KnownMethods,
5815 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005816 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5817 // Recurse into protocols.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00005818 if (!IFace->hasDefinition())
5819 return;
5820
Douglas Gregore8f5a172010-04-07 00:21:17 +00005821 const ObjCList<ObjCProtocolDecl> &Protocols
5822 = IFace->getReferencedProtocols();
5823 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005824 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005825 I != E; ++I)
5826 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005827 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005828
Douglas Gregorea766182010-10-18 18:21:28 +00005829 // Add methods from any class extensions and categories.
5830 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5831 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005832 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5833 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005834 KnownMethods, false);
5835
5836 // Visit the superclass.
5837 if (IFace->getSuperClass())
5838 FindImplementableMethods(Context, IFace->getSuperClass(),
5839 WantInstanceMethods, ReturnType,
5840 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005841 }
5842
5843 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5844 // Recurse into protocols.
5845 const ObjCList<ObjCProtocolDecl> &Protocols
5846 = Category->getReferencedProtocols();
5847 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005848 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005849 I != E; ++I)
5850 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005851 KnownMethods, InOriginalClass);
5852
5853 // If this category is the original class, jump to the interface.
5854 if (InOriginalClass && Category->getClassInterface())
5855 FindImplementableMethods(Context, Category->getClassInterface(),
5856 WantInstanceMethods, ReturnType, KnownMethods,
5857 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005858 }
5859
5860 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005861 if (Protocol->hasDefinition()) {
5862 // Recurse into protocols.
5863 const ObjCList<ObjCProtocolDecl> &Protocols
5864 = Protocol->getReferencedProtocols();
5865 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5866 E = Protocols.end();
5867 I != E; ++I)
5868 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
5869 KnownMethods, false);
5870 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005871 }
5872
5873 // Add methods in this container. This operation occurs last because
5874 // we want the methods from this container to override any methods
5875 // we've previously seen with the same selector.
5876 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5877 MEnd = Container->meth_end();
5878 M != MEnd; ++M) {
5879 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5880 if (!ReturnType.isNull() &&
5881 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5882 continue;
5883
Douglas Gregor408be5a2010-08-25 01:08:01 +00005884 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005885 }
5886 }
5887}
5888
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005889/// \brief Add the parenthesized return or parameter type chunk to a code
5890/// completion string.
5891static void AddObjCPassingTypeChunk(QualType Type,
5892 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005893 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005894 CodeCompletionBuilder &Builder) {
5895 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor8987b232011-09-27 23:30:47 +00005896 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005897 Builder.getAllocator()));
5898 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5899}
5900
5901/// \brief Determine whether the given class is or inherits from a class by
5902/// the given name.
5903static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00005904 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005905 if (!Class)
5906 return false;
5907
5908 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
5909 return true;
5910
5911 return InheritsFromClassNamed(Class->getSuperClass(), Name);
5912}
5913
5914/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
5915/// Key-Value Observing (KVO).
5916static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
5917 bool IsInstanceMethod,
5918 QualType ReturnType,
5919 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00005920 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005921 ResultBuilder &Results) {
5922 IdentifierInfo *PropName = Property->getIdentifier();
5923 if (!PropName || PropName->getLength() == 0)
5924 return;
5925
Douglas Gregor8987b232011-09-27 23:30:47 +00005926 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
5927
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005928 // Builder that will create each code completion.
5929 typedef CodeCompletionResult Result;
5930 CodeCompletionAllocator &Allocator = Results.getAllocator();
5931 CodeCompletionBuilder Builder(Allocator);
5932
5933 // The selector table.
5934 SelectorTable &Selectors = Context.Selectors;
5935
5936 // The property name, copied into the code completion allocation region
5937 // on demand.
5938 struct KeyHolder {
5939 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00005940 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005941 const char *CopiedKey;
5942
Chris Lattner5f9e2722011-07-23 10:55:15 +00005943 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005944 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
5945
5946 operator const char *() {
5947 if (CopiedKey)
5948 return CopiedKey;
5949
5950 return CopiedKey = Allocator.CopyString(Key);
5951 }
5952 } Key(Allocator, PropName->getName());
5953
5954 // The uppercased name of the property name.
5955 std::string UpperKey = PropName->getName();
5956 if (!UpperKey.empty())
5957 UpperKey[0] = toupper(UpperKey[0]);
5958
5959 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
5960 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
5961 Property->getType());
5962 bool ReturnTypeMatchesVoid
5963 = ReturnType.isNull() || ReturnType->isVoidType();
5964
5965 // Add the normal accessor -(type)key.
5966 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00005967 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005968 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
5969 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00005970 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005971
5972 Builder.AddTypedTextChunk(Key);
5973 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5974 CXCursor_ObjCInstanceMethodDecl));
5975 }
5976
5977 // If we have an integral or boolean property (or the user has provided
5978 // an integral or boolean return type), add the accessor -(type)isKey.
5979 if (IsInstanceMethod &&
5980 ((!ReturnType.isNull() &&
5981 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
5982 (ReturnType.isNull() &&
5983 (Property->getType()->isIntegerType() ||
5984 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00005985 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00005986 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00005987 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00005988 if (ReturnType.isNull()) {
5989 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5990 Builder.AddTextChunk("BOOL");
5991 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5992 }
5993
5994 Builder.AddTypedTextChunk(
5995 Allocator.CopyString(SelectorId->getName()));
5996 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
5997 CXCursor_ObjCInstanceMethodDecl));
5998 }
5999 }
6000
6001 // Add the normal mutator.
6002 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6003 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006004 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006005 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006006 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006007 if (ReturnType.isNull()) {
6008 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6009 Builder.AddTextChunk("void");
6010 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6011 }
6012
6013 Builder.AddTypedTextChunk(
6014 Allocator.CopyString(SelectorId->getName()));
6015 Builder.AddTypedTextChunk(":");
Douglas Gregor8987b232011-09-27 23:30:47 +00006016 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006017 Builder.AddTextChunk(Key);
6018 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6019 CXCursor_ObjCInstanceMethodDecl));
6020 }
6021 }
6022
6023 // Indexed and unordered accessors
6024 unsigned IndexedGetterPriority = CCP_CodePattern;
6025 unsigned IndexedSetterPriority = CCP_CodePattern;
6026 unsigned UnorderedGetterPriority = CCP_CodePattern;
6027 unsigned UnorderedSetterPriority = CCP_CodePattern;
6028 if (const ObjCObjectPointerType *ObjCPointer
6029 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6030 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6031 // If this interface type is not provably derived from a known
6032 // collection, penalize the corresponding completions.
6033 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6034 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6035 if (!InheritsFromClassNamed(IFace, "NSArray"))
6036 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6037 }
6038
6039 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6040 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6041 if (!InheritsFromClassNamed(IFace, "NSSet"))
6042 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6043 }
6044 }
6045 } else {
6046 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6047 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6048 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6049 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6050 }
6051
6052 // Add -(NSUInteger)countOf<key>
6053 if (IsInstanceMethod &&
6054 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006055 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006056 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006057 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006058 if (ReturnType.isNull()) {
6059 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6060 Builder.AddTextChunk("NSUInteger");
6061 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6062 }
6063
6064 Builder.AddTypedTextChunk(
6065 Allocator.CopyString(SelectorId->getName()));
6066 Results.AddResult(Result(Builder.TakeString(),
6067 std::min(IndexedGetterPriority,
6068 UnorderedGetterPriority),
6069 CXCursor_ObjCInstanceMethodDecl));
6070 }
6071 }
6072
6073 // Indexed getters
6074 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6075 if (IsInstanceMethod &&
6076 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006077 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006078 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006079 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006080 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006081 if (ReturnType.isNull()) {
6082 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6083 Builder.AddTextChunk("id");
6084 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6085 }
6086
6087 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6088 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6089 Builder.AddTextChunk("NSUInteger");
6090 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6091 Builder.AddTextChunk("index");
6092 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6093 CXCursor_ObjCInstanceMethodDecl));
6094 }
6095 }
6096
6097 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6098 if (IsInstanceMethod &&
6099 (ReturnType.isNull() ||
6100 (ReturnType->isObjCObjectPointerType() &&
6101 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6102 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6103 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006104 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006105 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006106 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006107 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006108 if (ReturnType.isNull()) {
6109 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6110 Builder.AddTextChunk("NSArray *");
6111 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6112 }
6113
6114 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6115 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6116 Builder.AddTextChunk("NSIndexSet *");
6117 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6118 Builder.AddTextChunk("indexes");
6119 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6120 CXCursor_ObjCInstanceMethodDecl));
6121 }
6122 }
6123
6124 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6125 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006126 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006127 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006128 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006129 &Context.Idents.get("range")
6130 };
6131
Douglas Gregore74c25c2011-05-04 23:50:46 +00006132 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006133 if (ReturnType.isNull()) {
6134 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6135 Builder.AddTextChunk("void");
6136 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6137 }
6138
6139 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6140 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6141 Builder.AddPlaceholderChunk("object-type");
6142 Builder.AddTextChunk(" **");
6143 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6144 Builder.AddTextChunk("buffer");
6145 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6146 Builder.AddTypedTextChunk("range:");
6147 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6148 Builder.AddTextChunk("NSRange");
6149 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6150 Builder.AddTextChunk("inRange");
6151 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6152 CXCursor_ObjCInstanceMethodDecl));
6153 }
6154 }
6155
6156 // Mutable indexed accessors
6157
6158 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6159 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006160 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006161 IdentifierInfo *SelectorIds[2] = {
6162 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006163 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006164 };
6165
Douglas Gregore74c25c2011-05-04 23:50:46 +00006166 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006167 if (ReturnType.isNull()) {
6168 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6169 Builder.AddTextChunk("void");
6170 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6171 }
6172
6173 Builder.AddTypedTextChunk("insertObject:");
6174 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6175 Builder.AddPlaceholderChunk("object-type");
6176 Builder.AddTextChunk(" *");
6177 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6178 Builder.AddTextChunk("object");
6179 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6180 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6181 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6182 Builder.AddPlaceholderChunk("NSUInteger");
6183 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6184 Builder.AddTextChunk("index");
6185 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6186 CXCursor_ObjCInstanceMethodDecl));
6187 }
6188 }
6189
6190 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6191 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006192 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006193 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006194 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006195 &Context.Idents.get("atIndexes")
6196 };
6197
Douglas Gregore74c25c2011-05-04 23:50:46 +00006198 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006199 if (ReturnType.isNull()) {
6200 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6201 Builder.AddTextChunk("void");
6202 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6203 }
6204
6205 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6206 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6207 Builder.AddTextChunk("NSArray *");
6208 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6209 Builder.AddTextChunk("array");
6210 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6211 Builder.AddTypedTextChunk("atIndexes:");
6212 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6213 Builder.AddPlaceholderChunk("NSIndexSet *");
6214 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6215 Builder.AddTextChunk("indexes");
6216 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6217 CXCursor_ObjCInstanceMethodDecl));
6218 }
6219 }
6220
6221 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6222 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006223 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006224 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006225 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006226 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006227 if (ReturnType.isNull()) {
6228 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6229 Builder.AddTextChunk("void");
6230 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6231 }
6232
6233 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6234 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6235 Builder.AddTextChunk("NSUInteger");
6236 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6237 Builder.AddTextChunk("index");
6238 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6239 CXCursor_ObjCInstanceMethodDecl));
6240 }
6241 }
6242
6243 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6244 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006245 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006246 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006247 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006248 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006249 if (ReturnType.isNull()) {
6250 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6251 Builder.AddTextChunk("void");
6252 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6253 }
6254
6255 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6256 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6257 Builder.AddTextChunk("NSIndexSet *");
6258 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6259 Builder.AddTextChunk("indexes");
6260 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6261 CXCursor_ObjCInstanceMethodDecl));
6262 }
6263 }
6264
6265 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6266 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006267 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006268 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006269 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006270 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006271 &Context.Idents.get("withObject")
6272 };
6273
Douglas Gregore74c25c2011-05-04 23:50:46 +00006274 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006275 if (ReturnType.isNull()) {
6276 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6277 Builder.AddTextChunk("void");
6278 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6279 }
6280
6281 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6282 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6283 Builder.AddPlaceholderChunk("NSUInteger");
6284 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6285 Builder.AddTextChunk("index");
6286 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6287 Builder.AddTypedTextChunk("withObject:");
6288 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6289 Builder.AddTextChunk("id");
6290 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6291 Builder.AddTextChunk("object");
6292 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6293 CXCursor_ObjCInstanceMethodDecl));
6294 }
6295 }
6296
6297 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6298 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006299 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006300 = (Twine("replace") + UpperKey + "AtIndexes").str();
6301 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006302 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006303 &Context.Idents.get(SelectorName1),
6304 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006305 };
6306
Douglas Gregore74c25c2011-05-04 23:50:46 +00006307 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006308 if (ReturnType.isNull()) {
6309 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6310 Builder.AddTextChunk("void");
6311 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6312 }
6313
6314 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6315 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6316 Builder.AddPlaceholderChunk("NSIndexSet *");
6317 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6318 Builder.AddTextChunk("indexes");
6319 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6320 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6321 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6322 Builder.AddTextChunk("NSArray *");
6323 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6324 Builder.AddTextChunk("array");
6325 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6326 CXCursor_ObjCInstanceMethodDecl));
6327 }
6328 }
6329
6330 // Unordered getters
6331 // - (NSEnumerator *)enumeratorOfKey
6332 if (IsInstanceMethod &&
6333 (ReturnType.isNull() ||
6334 (ReturnType->isObjCObjectPointerType() &&
6335 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6336 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6337 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006338 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006339 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006340 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006341 if (ReturnType.isNull()) {
6342 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6343 Builder.AddTextChunk("NSEnumerator *");
6344 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6345 }
6346
6347 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6348 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6349 CXCursor_ObjCInstanceMethodDecl));
6350 }
6351 }
6352
6353 // - (type *)memberOfKey:(type *)object
6354 if (IsInstanceMethod &&
6355 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006356 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006357 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006358 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006359 if (ReturnType.isNull()) {
6360 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6361 Builder.AddPlaceholderChunk("object-type");
6362 Builder.AddTextChunk(" *");
6363 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6364 }
6365
6366 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6367 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6368 if (ReturnType.isNull()) {
6369 Builder.AddPlaceholderChunk("object-type");
6370 Builder.AddTextChunk(" *");
6371 } else {
6372 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006373 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006374 Builder.getAllocator()));
6375 }
6376 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6377 Builder.AddTextChunk("object");
6378 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6379 CXCursor_ObjCInstanceMethodDecl));
6380 }
6381 }
6382
6383 // Mutable unordered accessors
6384 // - (void)addKeyObject:(type *)object
6385 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006386 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006387 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006388 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006389 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006390 if (ReturnType.isNull()) {
6391 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6392 Builder.AddTextChunk("void");
6393 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6394 }
6395
6396 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6397 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6398 Builder.AddPlaceholderChunk("object-type");
6399 Builder.AddTextChunk(" *");
6400 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6401 Builder.AddTextChunk("object");
6402 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6403 CXCursor_ObjCInstanceMethodDecl));
6404 }
6405 }
6406
6407 // - (void)addKey:(NSSet *)objects
6408 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006409 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006410 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006411 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006412 if (ReturnType.isNull()) {
6413 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6414 Builder.AddTextChunk("void");
6415 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6416 }
6417
6418 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6419 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6420 Builder.AddTextChunk("NSSet *");
6421 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6422 Builder.AddTextChunk("objects");
6423 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6424 CXCursor_ObjCInstanceMethodDecl));
6425 }
6426 }
6427
6428 // - (void)removeKeyObject:(type *)object
6429 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006430 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006431 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006432 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006433 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006434 if (ReturnType.isNull()) {
6435 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6436 Builder.AddTextChunk("void");
6437 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6438 }
6439
6440 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6441 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6442 Builder.AddPlaceholderChunk("object-type");
6443 Builder.AddTextChunk(" *");
6444 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6445 Builder.AddTextChunk("object");
6446 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6447 CXCursor_ObjCInstanceMethodDecl));
6448 }
6449 }
6450
6451 // - (void)removeKey:(NSSet *)objects
6452 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006453 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006454 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006455 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006456 if (ReturnType.isNull()) {
6457 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6458 Builder.AddTextChunk("void");
6459 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6460 }
6461
6462 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6463 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6464 Builder.AddTextChunk("NSSet *");
6465 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6466 Builder.AddTextChunk("objects");
6467 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6468 CXCursor_ObjCInstanceMethodDecl));
6469 }
6470 }
6471
6472 // - (void)intersectKey:(NSSet *)objects
6473 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006474 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006475 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006476 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006477 if (ReturnType.isNull()) {
6478 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6479 Builder.AddTextChunk("void");
6480 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6481 }
6482
6483 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6484 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6485 Builder.AddTextChunk("NSSet *");
6486 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6487 Builder.AddTextChunk("objects");
6488 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6489 CXCursor_ObjCInstanceMethodDecl));
6490 }
6491 }
6492
6493 // Key-Value Observing
6494 // + (NSSet *)keyPathsForValuesAffectingKey
6495 if (!IsInstanceMethod &&
6496 (ReturnType.isNull() ||
6497 (ReturnType->isObjCObjectPointerType() &&
6498 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6499 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6500 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006501 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006502 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006503 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006504 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006505 if (ReturnType.isNull()) {
6506 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6507 Builder.AddTextChunk("NSSet *");
6508 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6509 }
6510
6511 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6512 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006513 CXCursor_ObjCClassMethodDecl));
6514 }
6515 }
6516
6517 // + (BOOL)automaticallyNotifiesObserversForKey
6518 if (!IsInstanceMethod &&
6519 (ReturnType.isNull() ||
6520 ReturnType->isIntegerType() ||
6521 ReturnType->isBooleanType())) {
6522 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006523 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006524 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6525 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6526 if (ReturnType.isNull()) {
6527 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6528 Builder.AddTextChunk("BOOL");
6529 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6530 }
6531
6532 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6533 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6534 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006535 }
6536 }
6537}
6538
Douglas Gregore8f5a172010-04-07 00:21:17 +00006539void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6540 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006541 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006542 // Determine the return type of the method we're declaring, if
6543 // provided.
6544 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006545 Decl *IDecl = 0;
6546 if (CurContext->isObjCContainer()) {
6547 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6548 IDecl = cast<Decl>(OCD);
6549 }
Douglas Gregorea766182010-10-18 18:21:28 +00006550 // Determine where we should start searching for methods.
6551 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006552 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006553 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006554 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6555 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006556 IsInImplementation = true;
6557 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006558 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006559 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006560 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006561 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006562 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006563 }
6564
6565 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006566 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006567 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006568 }
6569
Douglas Gregorea766182010-10-18 18:21:28 +00006570 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006571 HandleCodeCompleteResults(this, CodeCompleter,
6572 CodeCompletionContext::CCC_Other,
6573 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006574 return;
6575 }
6576
6577 // Find all of the methods that we could declare/implement here.
6578 KnownMethodsMap KnownMethods;
6579 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006580 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006581
Douglas Gregore8f5a172010-04-07 00:21:17 +00006582 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006583 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006584 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6585 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006586 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006587 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006588 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6589 MEnd = KnownMethods.end();
6590 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006591 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00006592 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006593
6594 // If the result type was not already provided, add it to the
6595 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006596 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006597 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6598 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006599
6600 Selector Sel = Method->getSelector();
6601
6602 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006603 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006604 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006605
6606 // Add parameters to the pattern.
6607 unsigned I = 0;
6608 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6609 PEnd = Method->param_end();
6610 P != PEnd; (void)++P, ++I) {
6611 // Add the part of the selector name.
6612 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006613 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006614 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006615 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6616 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006617 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006618 } else
6619 break;
6620
6621 // Add the parameter type.
Douglas Gregor8987b232011-09-27 23:30:47 +00006622 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6623 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006624
6625 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006626 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006627 }
6628
6629 if (Method->isVariadic()) {
6630 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006631 Builder.AddChunk(CodeCompletionString::CK_Comma);
6632 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006633 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006634
Douglas Gregor447107d2010-05-28 00:57:46 +00006635 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006636 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006637 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6638 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6639 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006640 if (!Method->getResultType()->isVoidType()) {
6641 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006642 Builder.AddTextChunk("return");
6643 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6644 Builder.AddPlaceholderChunk("expression");
6645 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006646 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006647 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006648
Douglas Gregor218937c2011-02-01 19:23:04 +00006649 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6650 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006651 }
6652
Douglas Gregor408be5a2010-08-25 01:08:01 +00006653 unsigned Priority = CCP_CodePattern;
6654 if (!M->second.second)
6655 Priority += CCD_InBaseClass;
6656
Douglas Gregor218937c2011-02-01 19:23:04 +00006657 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor16ed9ad2010-08-17 16:06:07 +00006658 Method->isInstanceMethod()
6659 ? CXCursor_ObjCInstanceMethodDecl
6660 : CXCursor_ObjCClassMethodDecl));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006661 }
6662
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006663 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6664 // the properties in this class and its categories.
6665 if (Context.getLangOptions().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006666 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006667 Containers.push_back(SearchDecl);
6668
Douglas Gregore74c25c2011-05-04 23:50:46 +00006669 VisitedSelectorSet KnownSelectors;
6670 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6671 MEnd = KnownMethods.end();
6672 M != MEnd; ++M)
6673 KnownSelectors.insert(M->first);
6674
6675
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006676 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6677 if (!IFace)
6678 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6679 IFace = Category->getClassInterface();
6680
6681 if (IFace) {
6682 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6683 Category = Category->getNextClassCategory())
6684 Containers.push_back(Category);
6685 }
6686
6687 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6688 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6689 PEnd = Containers[I]->prop_end();
6690 P != PEnd; ++P) {
6691 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006692 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006693 }
6694 }
6695 }
6696
Douglas Gregore8f5a172010-04-07 00:21:17 +00006697 Results.ExitScope();
6698
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006699 HandleCodeCompleteResults(this, CodeCompleter,
6700 CodeCompletionContext::CCC_Other,
6701 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006702}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006703
6704void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6705 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006706 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006707 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006708 IdentifierInfo **SelIdents,
6709 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006710 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006711 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006712 if (ExternalSource) {
6713 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6714 I != N; ++I) {
6715 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006716 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006717 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006718
6719 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006720 }
6721 }
6722
6723 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006724 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006725 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6726 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006727
6728 if (ReturnTy)
6729 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006730
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006731 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006732 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6733 MEnd = MethodPool.end();
6734 M != MEnd; ++M) {
6735 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6736 &M->second.second;
6737 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006738 MethList = MethList->Next) {
6739 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6740 NumSelIdents))
6741 continue;
6742
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006743 if (AtParameterName) {
6744 // Suggest parameter names we've seen before.
6745 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6746 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6747 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006748 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregordae68752011-02-01 22:57:45 +00006749 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006750 Param->getIdentifier()->getName()));
6751 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006752 }
6753 }
6754
6755 continue;
6756 }
6757
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006758 Result R(MethList->Method, 0);
6759 R.StartParameter = NumSelIdents;
6760 R.AllParametersAreInformative = false;
6761 R.DeclaringEntity = true;
6762 Results.MaybeAddResult(R, CurContext);
6763 }
6764 }
6765
6766 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006767 HandleCodeCompleteResults(this, CodeCompleter,
6768 CodeCompletionContext::CCC_Other,
6769 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006770}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006771
Douglas Gregorf29c5232010-08-24 22:20:20 +00006772void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006773 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006774 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006775 Results.EnterNewScope();
6776
6777 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006778 CodeCompletionBuilder Builder(Results.getAllocator());
6779 Builder.AddTypedTextChunk("if");
6780 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6781 Builder.AddPlaceholderChunk("condition");
6782 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006783
6784 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006785 Builder.AddTypedTextChunk("ifdef");
6786 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6787 Builder.AddPlaceholderChunk("macro");
6788 Results.AddResult(Builder.TakeString());
6789
Douglas Gregorf44e8542010-08-24 19:08:16 +00006790 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006791 Builder.AddTypedTextChunk("ifndef");
6792 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6793 Builder.AddPlaceholderChunk("macro");
6794 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006795
6796 if (InConditional) {
6797 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006798 Builder.AddTypedTextChunk("elif");
6799 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6800 Builder.AddPlaceholderChunk("condition");
6801 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006802
6803 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00006804 Builder.AddTypedTextChunk("else");
6805 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006806
6807 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00006808 Builder.AddTypedTextChunk("endif");
6809 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006810 }
6811
6812 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006813 Builder.AddTypedTextChunk("include");
6814 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6815 Builder.AddTextChunk("\"");
6816 Builder.AddPlaceholderChunk("header");
6817 Builder.AddTextChunk("\"");
6818 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006819
6820 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006821 Builder.AddTypedTextChunk("include");
6822 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6823 Builder.AddTextChunk("<");
6824 Builder.AddPlaceholderChunk("header");
6825 Builder.AddTextChunk(">");
6826 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006827
6828 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006829 Builder.AddTypedTextChunk("define");
6830 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6831 Builder.AddPlaceholderChunk("macro");
6832 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006833
6834 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00006835 Builder.AddTypedTextChunk("define");
6836 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6837 Builder.AddPlaceholderChunk("macro");
6838 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6839 Builder.AddPlaceholderChunk("args");
6840 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6841 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006842
6843 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006844 Builder.AddTypedTextChunk("undef");
6845 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6846 Builder.AddPlaceholderChunk("macro");
6847 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006848
6849 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00006850 Builder.AddTypedTextChunk("line");
6851 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6852 Builder.AddPlaceholderChunk("number");
6853 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006854
6855 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00006856 Builder.AddTypedTextChunk("line");
6857 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6858 Builder.AddPlaceholderChunk("number");
6859 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6860 Builder.AddTextChunk("\"");
6861 Builder.AddPlaceholderChunk("filename");
6862 Builder.AddTextChunk("\"");
6863 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006864
6865 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006866 Builder.AddTypedTextChunk("error");
6867 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6868 Builder.AddPlaceholderChunk("message");
6869 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006870
6871 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00006872 Builder.AddTypedTextChunk("pragma");
6873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6874 Builder.AddPlaceholderChunk("arguments");
6875 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006876
6877 if (getLangOptions().ObjC1) {
6878 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006879 Builder.AddTypedTextChunk("import");
6880 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6881 Builder.AddTextChunk("\"");
6882 Builder.AddPlaceholderChunk("header");
6883 Builder.AddTextChunk("\"");
6884 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006885
6886 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006887 Builder.AddTypedTextChunk("import");
6888 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6889 Builder.AddTextChunk("<");
6890 Builder.AddPlaceholderChunk("header");
6891 Builder.AddTextChunk(">");
6892 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006893 }
6894
6895 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006896 Builder.AddTypedTextChunk("include_next");
6897 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6898 Builder.AddTextChunk("\"");
6899 Builder.AddPlaceholderChunk("header");
6900 Builder.AddTextChunk("\"");
6901 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006902
6903 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006904 Builder.AddTypedTextChunk("include_next");
6905 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6906 Builder.AddTextChunk("<");
6907 Builder.AddPlaceholderChunk("header");
6908 Builder.AddTextChunk(">");
6909 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006910
6911 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00006912 Builder.AddTypedTextChunk("warning");
6913 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6914 Builder.AddPlaceholderChunk("message");
6915 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006916
6917 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
6918 // completions for them. And __include_macros is a Clang-internal extension
6919 // that we don't want to encourage anyone to use.
6920
6921 // FIXME: we don't support #assert or #unassert, so don't suggest them.
6922 Results.ExitScope();
6923
Douglas Gregorf44e8542010-08-24 19:08:16 +00006924 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00006925 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00006926 Results.data(), Results.size());
6927}
6928
6929void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00006930 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00006931 S->getFnParent()? Sema::PCC_RecoveryInFunction
6932 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006933}
6934
Douglas Gregorf29c5232010-08-24 22:20:20 +00006935void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006936 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006937 IsDefinition? CodeCompletionContext::CCC_MacroName
6938 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006939 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
6940 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00006941 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006942 Results.EnterNewScope();
6943 for (Preprocessor::macro_iterator M = PP.macro_begin(),
6944 MEnd = PP.macro_end();
6945 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00006946 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006947 M->first->getName()));
6948 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006949 }
6950 Results.ExitScope();
6951 } else if (IsDefinition) {
6952 // FIXME: Can we detect when the user just wrote an include guard above?
6953 }
6954
Douglas Gregor52779fb2010-09-23 23:01:17 +00006955 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00006956 Results.data(), Results.size());
6957}
6958
Douglas Gregorf29c5232010-08-24 22:20:20 +00006959void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00006960 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006961 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00006962
6963 if (!CodeCompleter || CodeCompleter->includeMacros())
6964 AddMacroResults(PP, Results);
6965
6966 // defined (<macro>)
6967 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00006968 CodeCompletionBuilder Builder(Results.getAllocator());
6969 Builder.AddTypedTextChunk("defined");
6970 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6971 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6972 Builder.AddPlaceholderChunk("macro");
6973 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6974 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00006975 Results.ExitScope();
6976
6977 HandleCodeCompleteResults(this, CodeCompleter,
6978 CodeCompletionContext::CCC_PreprocessorExpression,
6979 Results.data(), Results.size());
6980}
6981
6982void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
6983 IdentifierInfo *Macro,
6984 MacroInfo *MacroInfo,
6985 unsigned Argument) {
6986 // FIXME: In the future, we could provide "overload" results, much like we
6987 // do for function calls.
6988
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00006989 // Now just ignore this. There will be another code-completion callback
6990 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00006991}
6992
Douglas Gregor55817af2010-08-25 17:04:25 +00006993void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00006994 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00006995 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00006996 0, 0);
6997}
6998
Douglas Gregordae68752011-02-01 22:57:45 +00006999void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007000 SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007001 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007002 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7003 CodeCompletionDeclConsumer Consumer(Builder,
7004 Context.getTranslationUnitDecl());
7005 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7006 Consumer);
7007 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007008
7009 if (!CodeCompleter || CodeCompleter->includeMacros())
7010 AddMacroResults(PP, Builder);
7011
7012 Results.clear();
7013 Results.insert(Results.end(),
7014 Builder.data(), Builder.data() + Builder.size());
7015}