blob: 32f36d455965a405fd41e356abd9768c25033c70 [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;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000126
127 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000128
129 /// \brief If non-NULL, a filter function used to remove any code-completion
130 /// results that are not desirable.
131 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000132
133 /// \brief Whether we should allow declarations as
134 /// nested-name-specifiers that would otherwise be filtered out.
135 bool AllowNestedNameSpecifiers;
136
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000137 /// \brief If set, the type that we would prefer our resulting value
138 /// declarations to have.
139 ///
140 /// Closely matching the preferred type gives a boost to a result's
141 /// priority.
142 CanQualType PreferredType;
143
Douglas Gregor86d9a522009-09-21 16:56:56 +0000144 /// \brief A list of shadow maps, which is used to model name hiding at
145 /// different levels of, e.g., the inheritance hierarchy.
146 std::list<ShadowMap> ShadowMaps;
147
Douglas Gregor3cdee122010-08-26 16:36:48 +0000148 /// \brief If we're potentially referring to a C++ member function, the set
149 /// of qualifiers applied to the object type.
150 Qualifiers ObjectTypeQualifiers;
151
152 /// \brief Whether the \p ObjectTypeQualifiers field is active.
153 bool HasObjectTypeQualifiers;
154
Douglas Gregor265f7492010-08-27 15:29:55 +0000155 /// \brief The selector that we prefer.
156 Selector PreferredSelector;
157
Douglas Gregorca45da02010-11-02 20:36:02 +0000158 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000159 CodeCompletionContext CompletionContext;
160
Douglas Gregorca45da02010-11-02 20:36:02 +0000161 /// \brief If we are in an instance method definition, the @implementation
162 /// object.
163 ObjCImplementationDecl *ObjCImplementation;
164
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000165 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000166
Douglas Gregor6f942b22010-09-21 16:06:22 +0000167 void MaybeAddConstructorResults(Result R);
168
Douglas Gregor86d9a522009-09-21 16:56:56 +0000169 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000170 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000171 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000172 const CodeCompletionContext &CompletionContext,
173 LookupFilter Filter = 0)
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000174 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
175 Filter(Filter),
Douglas Gregor218937c2011-02-01 19:23:04 +0000176 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000177 CompletionContext(CompletionContext),
178 ObjCImplementation(0)
179 {
180 // If this is an Objective-C instance method definition, dig out the
181 // corresponding implementation.
182 switch (CompletionContext.getKind()) {
183 case CodeCompletionContext::CCC_Expression:
184 case CodeCompletionContext::CCC_ObjCMessageReceiver:
185 case CodeCompletionContext::CCC_ParenthesizedExpression:
186 case CodeCompletionContext::CCC_Statement:
187 case CodeCompletionContext::CCC_Recovery:
188 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
189 if (Method->isInstanceMethod())
190 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
191 ObjCImplementation = Interface->getImplementation();
192 break;
193
194 default:
195 break;
196 }
197 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000198
Douglas Gregord8e8a582010-05-25 21:41:55 +0000199 /// \brief Whether we should include code patterns in the completion
200 /// results.
201 bool includeCodePatterns() const {
202 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000203 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000204 }
205
Douglas Gregor86d9a522009-09-21 16:56:56 +0000206 /// \brief Set the filter used for code-completion results.
207 void setFilter(LookupFilter Filter) {
208 this->Filter = Filter;
209 }
210
Douglas Gregor86d9a522009-09-21 16:56:56 +0000211 Result *data() { return Results.empty()? 0 : &Results.front(); }
212 unsigned size() const { return Results.size(); }
213 bool empty() const { return Results.empty(); }
214
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000215 /// \brief Specify the preferred type.
216 void setPreferredType(QualType T) {
217 PreferredType = SemaRef.Context.getCanonicalType(T);
218 }
219
Douglas Gregor3cdee122010-08-26 16:36:48 +0000220 /// \brief Set the cv-qualifiers on the object type, for us in filtering
221 /// calls to member functions.
222 ///
223 /// When there are qualifiers in this set, they will be used to filter
224 /// out member functions that aren't available (because there will be a
225 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
226 /// match.
227 void setObjectTypeQualifiers(Qualifiers Quals) {
228 ObjectTypeQualifiers = Quals;
229 HasObjectTypeQualifiers = true;
230 }
231
Douglas Gregor265f7492010-08-27 15:29:55 +0000232 /// \brief Set the preferred selector.
233 ///
234 /// When an Objective-C method declaration result is added, and that
235 /// method's selector matches this preferred selector, we give that method
236 /// a slight priority boost.
237 void setPreferredSelector(Selector Sel) {
238 PreferredSelector = Sel;
239 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000240
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000241 /// \brief Retrieve the code-completion context for which results are
242 /// being collected.
243 const CodeCompletionContext &getCompletionContext() const {
244 return CompletionContext;
245 }
246
Douglas Gregor45bcd432010-01-14 03:21:49 +0000247 /// \brief Specify whether nested-name-specifiers are allowed.
248 void allowNestedNameSpecifiers(bool Allow = true) {
249 AllowNestedNameSpecifiers = Allow;
250 }
251
Douglas Gregorb9d77572010-09-21 00:03:25 +0000252 /// \brief Return the semantic analysis object for which we are collecting
253 /// code completion results.
254 Sema &getSema() const { return SemaRef; }
255
Douglas Gregor218937c2011-02-01 19:23:04 +0000256 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000257 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000258
259 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000260
Douglas Gregore495b7f2010-01-14 00:20:49 +0000261 /// \brief Determine whether the given declaration is at all interesting
262 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000263 ///
264 /// \param ND the declaration that we are inspecting.
265 ///
266 /// \param AsNestedNameSpecifier will be set true if this declaration is
267 /// only interesting when it is a nested-name-specifier.
268 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000269
270 /// \brief Check whether the result is hidden by the Hiding declaration.
271 ///
272 /// \returns true if the result is hidden and cannot be found, false if
273 /// the hidden result could still be found. When false, \p R may be
274 /// modified to describe how the result can be found (e.g., via extra
275 /// qualification).
276 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
277 NamedDecl *Hiding);
278
Douglas Gregor86d9a522009-09-21 16:56:56 +0000279 /// \brief Add a new result to this result set (if it isn't already in one
280 /// of the shadow maps), or replace an existing result (for, e.g., a
281 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000282 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000283 /// \param R the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000284 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000285 /// \param CurContext the context in which this result will be named.
Douglas Gregor456c4a12009-09-21 20:12:40 +0000286 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000287
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000288 /// \brief Add a new result to this result set, where we already know
289 /// the hiding declation (if any).
290 ///
291 /// \param R the result to add (if it is unique).
292 ///
293 /// \param CurContext the context in which this result will be named.
294 ///
295 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000296 ///
297 /// \param InBaseClass whether the result was found in a base
298 /// class of the searched context.
299 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
300 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000301
Douglas Gregora4477812010-01-14 16:01:26 +0000302 /// \brief Add a new non-declaration result to this result set.
303 void AddResult(Result R);
304
Douglas Gregor86d9a522009-09-21 16:56:56 +0000305 /// \brief Enter into a new scope.
306 void EnterNewScope();
307
308 /// \brief Exit from the current scope.
309 void ExitScope();
310
Douglas Gregor55385fe2009-11-18 04:19:12 +0000311 /// \brief Ignore this declaration, if it is seen again.
312 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
313
Douglas Gregor86d9a522009-09-21 16:56:56 +0000314 /// \name Name lookup predicates
315 ///
316 /// These predicates can be passed to the name lookup functions to filter the
317 /// results of name lookup. All of the predicates have the same type, so that
318 ///
319 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000320 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000321 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000322 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000323 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000324 bool IsNestedNameSpecifier(NamedDecl *ND) const;
325 bool IsEnum(NamedDecl *ND) const;
326 bool IsClassOrStruct(NamedDecl *ND) const;
327 bool IsUnion(NamedDecl *ND) const;
328 bool IsNamespace(NamedDecl *ND) const;
329 bool IsNamespaceOrAlias(NamedDecl *ND) const;
330 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000331 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000332 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000333 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000334 bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000335 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000336 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000337 //@}
338 };
339}
340
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000341class ResultBuilder::ShadowMapEntry::iterator {
342 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
343 unsigned SingleDeclIndex;
344
345public:
346 typedef DeclIndexPair value_type;
347 typedef value_type reference;
348 typedef std::ptrdiff_t difference_type;
349 typedef std::input_iterator_tag iterator_category;
350
351 class pointer {
352 DeclIndexPair Value;
353
354 public:
355 pointer(const DeclIndexPair &Value) : Value(Value) { }
356
357 const DeclIndexPair *operator->() const {
358 return &Value;
359 }
360 };
361
362 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
363
364 iterator(NamedDecl *SingleDecl, unsigned Index)
365 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
366
367 iterator(const DeclIndexPair *Iterator)
368 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
369
370 iterator &operator++() {
371 if (DeclOrIterator.is<NamedDecl *>()) {
372 DeclOrIterator = (NamedDecl *)0;
373 SingleDeclIndex = 0;
374 return *this;
375 }
376
377 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
378 ++I;
379 DeclOrIterator = I;
380 return *this;
381 }
382
Chris Lattner66392d42010-09-04 18:12:20 +0000383 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000384 iterator tmp(*this);
385 ++(*this);
386 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000387 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000388
389 reference operator*() const {
390 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
391 return reference(ND, SingleDeclIndex);
392
Douglas Gregord490f952009-12-06 21:27:58 +0000393 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000394 }
395
396 pointer operator->() const {
397 return pointer(**this);
398 }
399
400 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000401 return X.DeclOrIterator.getOpaqueValue()
402 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000403 X.SingleDeclIndex == Y.SingleDeclIndex;
404 }
405
406 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000407 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000408 }
409};
410
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000411ResultBuilder::ShadowMapEntry::iterator
412ResultBuilder::ShadowMapEntry::begin() const {
413 if (DeclOrVector.isNull())
414 return iterator();
415
416 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
417 return iterator(ND, SingleDeclIndex);
418
419 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
420}
421
422ResultBuilder::ShadowMapEntry::iterator
423ResultBuilder::ShadowMapEntry::end() const {
424 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
425 return iterator();
426
427 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
428}
429
Douglas Gregor456c4a12009-09-21 20:12:40 +0000430/// \brief Compute the qualification required to get from the current context
431/// (\p CurContext) to the target context (\p TargetContext).
432///
433/// \param Context the AST context in which the qualification will be used.
434///
435/// \param CurContext the context where an entity is being named, which is
436/// typically based on the current scope.
437///
438/// \param TargetContext the context in which the named entity actually
439/// resides.
440///
441/// \returns a nested name specifier that refers into the target context, or
442/// NULL if no qualification is needed.
443static NestedNameSpecifier *
444getRequiredQualification(ASTContext &Context,
445 DeclContext *CurContext,
446 DeclContext *TargetContext) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000447 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000448
449 for (DeclContext *CommonAncestor = TargetContext;
450 CommonAncestor && !CommonAncestor->Encloses(CurContext);
451 CommonAncestor = CommonAncestor->getLookupParent()) {
452 if (CommonAncestor->isTransparentContext() ||
453 CommonAncestor->isFunctionOrMethod())
454 continue;
455
456 TargetParents.push_back(CommonAncestor);
457 }
458
459 NestedNameSpecifier *Result = 0;
460 while (!TargetParents.empty()) {
461 DeclContext *Parent = TargetParents.back();
462 TargetParents.pop_back();
463
Douglas Gregorfb629412010-08-23 21:17:50 +0000464 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
465 if (!Namespace->getIdentifier())
466 continue;
467
Douglas Gregor456c4a12009-09-21 20:12:40 +0000468 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000469 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000470 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
471 Result = NestedNameSpecifier::Create(Context, Result,
472 false,
473 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000474 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000475 return Result;
476}
477
Douglas Gregor45bcd432010-01-14 03:21:49 +0000478bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
479 bool &AsNestedNameSpecifier) const {
480 AsNestedNameSpecifier = false;
481
Douglas Gregore495b7f2010-01-14 00:20:49 +0000482 ND = ND->getUnderlyingDecl();
483 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000484
485 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000486 if (!ND->getDeclName())
487 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000488
489 // Friend declarations and declarations introduced due to friends are never
490 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000491 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000492 return false;
493
Douglas Gregor76282942009-12-11 17:31:05 +0000494 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000495 if (isa<ClassTemplateSpecializationDecl>(ND) ||
496 isa<ClassTemplatePartialSpecializationDecl>(ND))
497 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000498
Douglas Gregor76282942009-12-11 17:31:05 +0000499 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000500 if (isa<UsingDecl>(ND))
501 return false;
502
503 // Some declarations have reserved names that we don't want to ever show.
504 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000505 // __va_list_tag is a freak of nature. Find it and skip it.
506 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000507 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000508
Douglas Gregorf52cede2009-10-09 22:16:47 +0000509 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000510 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000511 //
512 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000513 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000514 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000515 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000516 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
517 (ND->getLocation().isInvalid() ||
518 SemaRef.SourceMgr.isInSystemHeader(
519 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000520 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000521 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000522 }
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000523
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000524 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
525 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
526 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000527 Filter != &ResultBuilder::IsNamespaceOrAlias &&
528 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000529 AsNestedNameSpecifier = true;
530
Douglas Gregor86d9a522009-09-21 16:56:56 +0000531 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000532 if (Filter && !(this->*Filter)(ND)) {
533 // Check whether it is interesting as a nested-name-specifier.
David Blaikie4e4d0842012-03-11 07:00:24 +0000534 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor45bcd432010-01-14 03:21:49 +0000535 IsNestedNameSpecifier(ND) &&
536 (Filter != &ResultBuilder::IsMember ||
537 (isa<CXXRecordDecl>(ND) &&
538 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
539 AsNestedNameSpecifier = true;
540 return true;
541 }
542
Douglas Gregore495b7f2010-01-14 00:20:49 +0000543 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000544 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000545 // ... then it must be interesting!
546 return true;
547}
548
Douglas Gregor6660d842010-01-14 00:41:07 +0000549bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
550 NamedDecl *Hiding) {
551 // In C, there is no way to refer to a hidden name.
552 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
553 // name if we introduce the tag type.
David Blaikie4e4d0842012-03-11 07:00:24 +0000554 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor6660d842010-01-14 00:41:07 +0000555 return true;
556
Sebastian Redl7a126a42010-08-31 00:36:30 +0000557 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000558
559 // There is no way to qualify a name declared in a function or method.
560 if (HiddenCtx->isFunctionOrMethod())
561 return true;
562
Sebastian Redl7a126a42010-08-31 00:36:30 +0000563 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000564 return true;
565
566 // We can refer to the result with the appropriate qualification. Do it.
567 R.Hidden = true;
568 R.QualifierIsInformative = false;
569
570 if (!R.Qualifier)
571 R.Qualifier = getRequiredQualification(SemaRef.Context,
572 CurContext,
573 R.Declaration->getDeclContext());
574 return false;
575}
576
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000577/// \brief A simplified classification of types used to determine whether two
578/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000579SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000580 switch (T->getTypeClass()) {
581 case Type::Builtin:
582 switch (cast<BuiltinType>(T)->getKind()) {
583 case BuiltinType::Void:
584 return STC_Void;
585
586 case BuiltinType::NullPtr:
587 return STC_Pointer;
588
589 case BuiltinType::Overload:
590 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000591 return STC_Other;
592
593 case BuiltinType::ObjCId:
594 case BuiltinType::ObjCClass:
595 case BuiltinType::ObjCSel:
596 return STC_ObjectiveC;
597
598 default:
599 return STC_Arithmetic;
600 }
David Blaikie7530c032012-01-17 06:56:22 +0000601
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000602 case Type::Complex:
603 return STC_Arithmetic;
604
605 case Type::Pointer:
606 return STC_Pointer;
607
608 case Type::BlockPointer:
609 return STC_Block;
610
611 case Type::LValueReference:
612 case Type::RValueReference:
613 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
614
615 case Type::ConstantArray:
616 case Type::IncompleteArray:
617 case Type::VariableArray:
618 case Type::DependentSizedArray:
619 return STC_Array;
620
621 case Type::DependentSizedExtVector:
622 case Type::Vector:
623 case Type::ExtVector:
624 return STC_Arithmetic;
625
626 case Type::FunctionProto:
627 case Type::FunctionNoProto:
628 return STC_Function;
629
630 case Type::Record:
631 return STC_Record;
632
633 case Type::Enum:
634 return STC_Arithmetic;
635
636 case Type::ObjCObject:
637 case Type::ObjCInterface:
638 case Type::ObjCObjectPointer:
639 return STC_ObjectiveC;
640
641 default:
642 return STC_Other;
643 }
644}
645
646/// \brief Get the type that a given expression will have if this declaration
647/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000648QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000649 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
650
651 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
652 return C.getTypeDeclType(Type);
653 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
654 return C.getObjCInterfaceType(Iface);
655
656 QualType T;
657 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000658 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000659 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000660 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000661 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000662 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000663 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
664 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
665 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
666 T = Property->getType();
667 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
668 T = Value->getType();
669 else
670 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000671
672 // Dig through references, function pointers, and block pointers to
673 // get down to the likely type of an expression when the entity is
674 // used.
675 do {
676 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
677 T = Ref->getPointeeType();
678 continue;
679 }
680
681 if (const PointerType *Pointer = T->getAs<PointerType>()) {
682 if (Pointer->getPointeeType()->isFunctionType()) {
683 T = Pointer->getPointeeType();
684 continue;
685 }
686
687 break;
688 }
689
690 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
691 T = Block->getPointeeType();
692 continue;
693 }
694
695 if (const FunctionType *Function = T->getAs<FunctionType>()) {
696 T = Function->getResultType();
697 continue;
698 }
699
700 break;
701 } while (true);
702
703 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000704}
705
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000706void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
707 // If this is an Objective-C method declaration whose selector matches our
708 // preferred selector, give it a priority boost.
709 if (!PreferredSelector.isNull())
710 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
711 if (PreferredSelector == Method->getSelector())
712 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000713
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000714 // If we have a preferred type, adjust the priority for results with exactly-
715 // matching or nearly-matching types.
716 if (!PreferredType.isNull()) {
717 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
718 if (!T.isNull()) {
719 CanQualType TC = SemaRef.Context.getCanonicalType(T);
720 // Check for exactly-matching types (modulo qualifiers).
721 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
722 R.Priority /= CCF_ExactTypeMatch;
723 // Check for nearly-matching types, based on classification of each.
724 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000725 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000726 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
727 R.Priority /= CCF_SimilarTypeMatch;
728 }
729 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000730}
731
Douglas Gregor6f942b22010-09-21 16:06:22 +0000732void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000733 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor6f942b22010-09-21 16:06:22 +0000734 !CompletionContext.wantConstructorResults())
735 return;
736
737 ASTContext &Context = SemaRef.Context;
738 NamedDecl *D = R.Declaration;
739 CXXRecordDecl *Record = 0;
740 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
741 Record = ClassTemplate->getTemplatedDecl();
742 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
743 // Skip specializations and partial specializations.
744 if (isa<ClassTemplateSpecializationDecl>(Record))
745 return;
746 } else {
747 // There are no constructors here.
748 return;
749 }
750
751 Record = Record->getDefinition();
752 if (!Record)
753 return;
754
755
756 QualType RecordTy = Context.getTypeDeclType(Record);
757 DeclarationName ConstructorName
758 = Context.DeclarationNames.getCXXConstructorName(
759 Context.getCanonicalType(RecordTy));
760 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
761 Ctors.first != Ctors.second; ++Ctors.first) {
762 R.Declaration = *Ctors.first;
763 R.CursorKind = getCursorKindForDecl(R.Declaration);
764 Results.push_back(R);
765 }
766}
767
Douglas Gregore495b7f2010-01-14 00:20:49 +0000768void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
769 assert(!ShadowMaps.empty() && "Must enter into a results scope");
770
771 if (R.Kind != Result::RK_Declaration) {
772 // For non-declaration results, just add the result.
773 Results.push_back(R);
774 return;
775 }
776
777 // Look through using declarations.
778 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
779 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
780 return;
781 }
782
783 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
784 unsigned IDNS = CanonDecl->getIdentifierNamespace();
785
Douglas Gregor45bcd432010-01-14 03:21:49 +0000786 bool AsNestedNameSpecifier = false;
787 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000788 return;
789
Douglas Gregor6f942b22010-09-21 16:06:22 +0000790 // C++ constructors are never found by name lookup.
791 if (isa<CXXConstructorDecl>(R.Declaration))
792 return;
793
Douglas Gregor86d9a522009-09-21 16:56:56 +0000794 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000795 ShadowMapEntry::iterator I, IEnd;
796 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
797 if (NamePos != SMap.end()) {
798 I = NamePos->second.begin();
799 IEnd = NamePos->second.end();
800 }
801
802 for (; I != IEnd; ++I) {
803 NamedDecl *ND = I->first;
804 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000805 if (ND->getCanonicalDecl() == CanonDecl) {
806 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000807 Results[Index].Declaration = R.Declaration;
808
Douglas Gregor86d9a522009-09-21 16:56:56 +0000809 // We're done.
810 return;
811 }
812 }
813
814 // This is a new declaration in this scope. However, check whether this
815 // declaration name is hidden by a similarly-named declaration in an outer
816 // scope.
817 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
818 --SMEnd;
819 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000820 ShadowMapEntry::iterator I, IEnd;
821 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
822 if (NamePos != SM->end()) {
823 I = NamePos->second.begin();
824 IEnd = NamePos->second.end();
825 }
826 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000827 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000828 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000829 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
830 Decl::IDNS_ObjCProtocol)))
831 continue;
832
833 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000834 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000835 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000836 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000837 continue;
838
839 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000840 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000841 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000842
843 break;
844 }
845 }
846
847 // Make sure that any given declaration only shows up in the result set once.
848 if (!AllDeclsFound.insert(CanonDecl))
849 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000850
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000851 // If the filter is for nested-name-specifiers, then this result starts a
852 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000853 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000854 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000855 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000856 } else
857 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000858
Douglas Gregor0563c262009-09-22 23:15:58 +0000859 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000860 if (R.QualifierIsInformative && !R.Qualifier &&
861 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000862 DeclContext *Ctx = R.Declaration->getDeclContext();
863 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
864 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
865 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
866 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
867 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
868 else
869 R.QualifierIsInformative = false;
870 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000871
Douglas Gregor86d9a522009-09-21 16:56:56 +0000872 // Insert this result into the set of results and into the current shadow
873 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000874 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000875 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000876
877 if (!AsNestedNameSpecifier)
878 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000879}
880
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000881void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000882 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000883 if (R.Kind != Result::RK_Declaration) {
884 // For non-declaration results, just add the result.
885 Results.push_back(R);
886 return;
887 }
888
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000889 // Look through using declarations.
890 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
891 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
892 return;
893 }
894
Douglas Gregor45bcd432010-01-14 03:21:49 +0000895 bool AsNestedNameSpecifier = false;
896 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000897 return;
898
Douglas Gregor6f942b22010-09-21 16:06:22 +0000899 // C++ constructors are never found by name lookup.
900 if (isa<CXXConstructorDecl>(R.Declaration))
901 return;
902
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000903 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
904 return;
Nick Lewycky173a37a2012-04-03 21:44:08 +0000905
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000906 // Make sure that any given declaration only shows up in the result set once.
907 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
908 return;
909
910 // If the filter is for nested-name-specifiers, then this result starts a
911 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000912 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000913 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000914 R.Priority = CCP_NestedNameSpecifier;
915 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000916 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
917 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000918 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000919 R.QualifierIsInformative = true;
920
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000921 // If this result is supposed to have an informative qualifier, add one.
922 if (R.QualifierIsInformative && !R.Qualifier &&
923 !R.StartsNestedNameSpecifier) {
924 DeclContext *Ctx = R.Declaration->getDeclContext();
925 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
926 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
927 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
928 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000929 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000930 else
931 R.QualifierIsInformative = false;
932 }
933
Douglas Gregor12e13132010-05-26 22:00:08 +0000934 // Adjust the priority if this result comes from a base class.
935 if (InBaseClass)
936 R.Priority += CCD_InBaseClass;
937
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000938 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000939
Douglas Gregor3cdee122010-08-26 16:36:48 +0000940 if (HasObjectTypeQualifiers)
941 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
942 if (Method->isInstance()) {
943 Qualifiers MethodQuals
944 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
945 if (ObjectTypeQualifiers == MethodQuals)
946 R.Priority += CCD_ObjectQualifierMatch;
947 else if (ObjectTypeQualifiers - MethodQuals) {
948 // The method cannot be invoked, because doing so would drop
949 // qualifiers.
950 return;
951 }
952 }
953
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000954 // Insert this result into the set of results.
955 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000956
957 if (!AsNestedNameSpecifier)
958 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000959}
960
Douglas Gregora4477812010-01-14 16:01:26 +0000961void ResultBuilder::AddResult(Result R) {
962 assert(R.Kind != Result::RK_Declaration &&
963 "Declaration results need more context");
964 Results.push_back(R);
965}
966
Douglas Gregor86d9a522009-09-21 16:56:56 +0000967/// \brief Enter into a new scope.
968void ResultBuilder::EnterNewScope() {
969 ShadowMaps.push_back(ShadowMap());
970}
971
972/// \brief Exit from the current scope.
973void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000974 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
975 EEnd = ShadowMaps.back().end();
976 E != EEnd;
977 ++E)
978 E->second.Destroy();
979
Douglas Gregor86d9a522009-09-21 16:56:56 +0000980 ShadowMaps.pop_back();
981}
982
Douglas Gregor791215b2009-09-21 20:51:25 +0000983/// \brief Determines whether this given declaration will be found by
984/// ordinary name lookup.
985bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000986 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
987
Douglas Gregor791215b2009-09-21 20:51:25 +0000988 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +0000989 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000990 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +0000991 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +0000992 if (isa<ObjCIvarDecl>(ND))
993 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +0000994 }
995
Douglas Gregor791215b2009-09-21 20:51:25 +0000996 return ND->getIdentifierNamespace() & IDNS;
997}
998
Douglas Gregor01dfea02010-01-10 23:08:15 +0000999/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001000/// ordinary name lookup but is not a type name.
1001bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
1002 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1003 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1004 return false;
1005
1006 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001007 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001008 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001009 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001010 if (isa<ObjCIvarDecl>(ND))
1011 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001012 }
1013
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001014 return ND->getIdentifierNamespace() & IDNS;
1015}
1016
Douglas Gregorf9578432010-07-28 21:50:18 +00001017bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1018 if (!IsOrdinaryNonTypeName(ND))
1019 return 0;
1020
1021 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1022 if (VD->getType()->isIntegralOrEnumerationType())
1023 return true;
1024
1025 return false;
1026}
1027
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001028/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001029/// ordinary name lookup.
1030bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001031 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1032
Douglas Gregor01dfea02010-01-10 23:08:15 +00001033 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001034 if (SemaRef.getLangOpts().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001035 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001036
1037 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001038 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1039 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001040}
1041
Douglas Gregor86d9a522009-09-21 16:56:56 +00001042/// \brief Determines whether the given declaration is suitable as the
1043/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1044bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1045 // Allow us to find class templates, too.
1046 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1047 ND = ClassTemplate->getTemplatedDecl();
1048
1049 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1050}
1051
1052/// \brief Determines whether the given declaration is an enumeration.
1053bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1054 return isa<EnumDecl>(ND);
1055}
1056
1057/// \brief Determines whether the given declaration is a class or struct.
1058bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1059 // Allow us to find class templates, too.
1060 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1061 ND = ClassTemplate->getTemplatedDecl();
1062
1063 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001064 return RD->getTagKind() == TTK_Class ||
1065 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001066
1067 return false;
1068}
1069
1070/// \brief Determines whether the given declaration is a union.
1071bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1072 // Allow us to find class templates, too.
1073 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1074 ND = ClassTemplate->getTemplatedDecl();
1075
1076 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001077 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001078
1079 return false;
1080}
1081
1082/// \brief Determines whether the given declaration is a namespace.
1083bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1084 return isa<NamespaceDecl>(ND);
1085}
1086
1087/// \brief Determines whether the given declaration is a namespace or
1088/// namespace alias.
1089bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1090 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1091}
1092
Douglas Gregor76282942009-12-11 17:31:05 +00001093/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001094bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001095 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1096 ND = Using->getTargetDecl();
1097
1098 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001099}
1100
Douglas Gregor76282942009-12-11 17:31:05 +00001101/// \brief Determines which members of a class should be visible via
1102/// "." or "->". Only value declarations, nested name specifiers, and
1103/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001104bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001105 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1106 ND = Using->getTargetDecl();
1107
Douglas Gregorce821962009-12-11 18:14:22 +00001108 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1109 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001110}
1111
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001112static bool isObjCReceiverType(ASTContext &C, QualType T) {
1113 T = C.getCanonicalType(T);
1114 switch (T->getTypeClass()) {
1115 case Type::ObjCObject:
1116 case Type::ObjCInterface:
1117 case Type::ObjCObjectPointer:
1118 return true;
1119
1120 case Type::Builtin:
1121 switch (cast<BuiltinType>(T)->getKind()) {
1122 case BuiltinType::ObjCId:
1123 case BuiltinType::ObjCClass:
1124 case BuiltinType::ObjCSel:
1125 return true;
1126
1127 default:
1128 break;
1129 }
1130 return false;
1131
1132 default:
1133 break;
1134 }
1135
David Blaikie4e4d0842012-03-11 07:00:24 +00001136 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001137 return false;
1138
1139 // FIXME: We could perform more analysis here to determine whether a
1140 // particular class type has any conversions to Objective-C types. For now,
1141 // just accept all class types.
1142 return T->isDependentType() || T->isRecordType();
1143}
1144
1145bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1146 QualType T = getDeclUsageType(SemaRef.Context, ND);
1147 if (T.isNull())
1148 return false;
1149
1150 T = SemaRef.Context.getBaseElementType(T);
1151 return isObjCReceiverType(SemaRef.Context, T);
1152}
1153
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001154bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
1155 if (IsObjCMessageReceiver(ND))
1156 return true;
1157
1158 VarDecl *Var = dyn_cast<VarDecl>(ND);
1159 if (!Var)
1160 return false;
1161
1162 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1163}
1164
Douglas Gregorfb629412010-08-23 21:17:50 +00001165bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001166 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1167 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001168 return false;
1169
1170 QualType T = getDeclUsageType(SemaRef.Context, ND);
1171 if (T.isNull())
1172 return false;
1173
1174 T = SemaRef.Context.getBaseElementType(T);
1175 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1176 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001177 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001178}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001179
Douglas Gregor52779fb2010-09-23 23:01:17 +00001180bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1181 return false;
1182}
1183
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001184/// \rief Determines whether the given declaration is an Objective-C
1185/// instance variable.
1186bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1187 return isa<ObjCIvarDecl>(ND);
1188}
1189
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001190namespace {
1191 /// \brief Visible declaration consumer that adds a code-completion result
1192 /// for each visible declaration.
1193 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1194 ResultBuilder &Results;
1195 DeclContext *CurContext;
1196
1197 public:
1198 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1199 : Results(Results), CurContext(CurContext) { }
1200
Erik Verbruggend1205962011-10-06 07:27:49 +00001201 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1202 bool InBaseClass) {
1203 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001204 if (Ctx)
1205 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1206
Erik Verbruggend1205962011-10-06 07:27:49 +00001207 ResultBuilder::Result Result(ND, 0, false, Accessible);
1208 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001209 }
1210 };
1211}
1212
Douglas Gregor86d9a522009-09-21 16:56:56 +00001213/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001214static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001215 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001216 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001217 Results.AddResult(Result("short", CCP_Type));
1218 Results.AddResult(Result("long", CCP_Type));
1219 Results.AddResult(Result("signed", CCP_Type));
1220 Results.AddResult(Result("unsigned", CCP_Type));
1221 Results.AddResult(Result("void", CCP_Type));
1222 Results.AddResult(Result("char", CCP_Type));
1223 Results.AddResult(Result("int", CCP_Type));
1224 Results.AddResult(Result("float", CCP_Type));
1225 Results.AddResult(Result("double", CCP_Type));
1226 Results.AddResult(Result("enum", CCP_Type));
1227 Results.AddResult(Result("struct", CCP_Type));
1228 Results.AddResult(Result("union", CCP_Type));
1229 Results.AddResult(Result("const", CCP_Type));
1230 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001231
Douglas Gregor86d9a522009-09-21 16:56:56 +00001232 if (LangOpts.C99) {
1233 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001234 Results.AddResult(Result("_Complex", CCP_Type));
1235 Results.AddResult(Result("_Imaginary", CCP_Type));
1236 Results.AddResult(Result("_Bool", CCP_Type));
1237 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001238 }
1239
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001240 CodeCompletionBuilder Builder(Results.getAllocator(),
1241 Results.getCodeCompletionTUInfo());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001242 if (LangOpts.CPlusPlus) {
1243 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001244 Results.AddResult(Result("bool", CCP_Type +
1245 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001246 Results.AddResult(Result("class", CCP_Type));
1247 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001248
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001249 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001250 Builder.AddTypedTextChunk("typename");
1251 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1252 Builder.AddPlaceholderChunk("qualifier");
1253 Builder.AddTextChunk("::");
1254 Builder.AddPlaceholderChunk("name");
1255 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001256
Douglas Gregor86d9a522009-09-21 16:56:56 +00001257 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001258 Results.AddResult(Result("auto", CCP_Type));
1259 Results.AddResult(Result("char16_t", CCP_Type));
1260 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001261
Douglas Gregor218937c2011-02-01 19:23:04 +00001262 Builder.AddTypedTextChunk("decltype");
1263 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1264 Builder.AddPlaceholderChunk("expression");
1265 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1266 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001267 }
1268 }
1269
1270 // GNU extensions
1271 if (LangOpts.GNUMode) {
1272 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001273 // Results.AddResult(Result("_Decimal32"));
1274 // Results.AddResult(Result("_Decimal64"));
1275 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001276
Douglas Gregor218937c2011-02-01 19:23:04 +00001277 Builder.AddTypedTextChunk("typeof");
1278 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1279 Builder.AddPlaceholderChunk("expression");
1280 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001281
Douglas Gregor218937c2011-02-01 19:23:04 +00001282 Builder.AddTypedTextChunk("typeof");
1283 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1284 Builder.AddPlaceholderChunk("type");
1285 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1286 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001287 }
1288}
1289
John McCallf312b1e2010-08-26 23:41:50 +00001290static void AddStorageSpecifiers(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 // Note: we don't suggest either "auto" or "register", because both
1295 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1296 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001297 Results.AddResult(Result("extern"));
1298 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001299}
1300
John McCallf312b1e2010-08-26 23:41:50 +00001301static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001302 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001303 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001304 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001305 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001306 case Sema::PCC_Class:
1307 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001308 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001309 Results.AddResult(Result("explicit"));
1310 Results.AddResult(Result("friend"));
1311 Results.AddResult(Result("mutable"));
1312 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001313 }
1314 // Fall through
1315
John McCallf312b1e2010-08-26 23:41:50 +00001316 case Sema::PCC_ObjCInterface:
1317 case Sema::PCC_ObjCImplementation:
1318 case Sema::PCC_Namespace:
1319 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001320 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001321 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001322 break;
1323
John McCallf312b1e2010-08-26 23:41:50 +00001324 case Sema::PCC_ObjCInstanceVariableList:
1325 case Sema::PCC_Expression:
1326 case Sema::PCC_Statement:
1327 case Sema::PCC_ForInit:
1328 case Sema::PCC_Condition:
1329 case Sema::PCC_RecoveryInFunction:
1330 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001331 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001332 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001333 break;
1334 }
1335}
1336
Douglas Gregorbca403c2010-01-13 23:51:12 +00001337static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1338static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1339static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001340 ResultBuilder &Results,
1341 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001342static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001343 ResultBuilder &Results,
1344 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001345static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001346 ResultBuilder &Results,
1347 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001348static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001349
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001350static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001351 CodeCompletionBuilder Builder(Results.getAllocator(),
1352 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00001353 Builder.AddTypedTextChunk("typedef");
1354 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1355 Builder.AddPlaceholderChunk("type");
1356 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1357 Builder.AddPlaceholderChunk("name");
1358 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001359}
1360
John McCallf312b1e2010-08-26 23:41:50 +00001361static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001362 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001363 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001364 case Sema::PCC_Namespace:
1365 case Sema::PCC_Class:
1366 case Sema::PCC_ObjCInstanceVariableList:
1367 case Sema::PCC_Template:
1368 case Sema::PCC_MemberTemplate:
1369 case Sema::PCC_Statement:
1370 case Sema::PCC_RecoveryInFunction:
1371 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001372 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001373 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001374 return true;
1375
John McCallf312b1e2010-08-26 23:41:50 +00001376 case Sema::PCC_Expression:
1377 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001378 return LangOpts.CPlusPlus;
1379
1380 case Sema::PCC_ObjCInterface:
1381 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001382 return false;
1383
John McCallf312b1e2010-08-26 23:41:50 +00001384 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001385 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001386 }
David Blaikie7530c032012-01-17 06:56:22 +00001387
1388 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001389}
1390
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001391static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1392 const Preprocessor &PP) {
1393 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001394 Policy.AnonymousTagLocations = false;
1395 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001396 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001397 return Policy;
1398}
1399
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001400/// \brief Retrieve a printing policy suitable for code completion.
1401static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1402 return getCompletionPrintingPolicy(S.Context, S.PP);
1403}
1404
Douglas Gregor8ca72082011-10-18 21:20:17 +00001405/// \brief Retrieve the string representation of the given type as a string
1406/// that has the appropriate lifetime for code completion.
1407///
1408/// This routine provides a fast path where we provide constant strings for
1409/// common type names.
1410static const char *GetCompletionTypeString(QualType T,
1411 ASTContext &Context,
1412 const PrintingPolicy &Policy,
1413 CodeCompletionAllocator &Allocator) {
1414 if (!T.getLocalQualifiers()) {
1415 // Built-in type names are constant strings.
1416 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
1417 return BT->getName(Policy);
1418
1419 // Anonymous tag types are constant strings.
1420 if (const TagType *TagT = dyn_cast<TagType>(T))
1421 if (TagDecl *Tag = TagT->getDecl())
1422 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1423 switch (Tag->getTagKind()) {
1424 case TTK_Struct: return "struct <anonymous>";
1425 case TTK_Class: return "class <anonymous>";
1426 case TTK_Union: return "union <anonymous>";
1427 case TTK_Enum: return "enum <anonymous>";
1428 }
1429 }
1430 }
1431
1432 // Slow path: format the type as a string.
1433 std::string Result;
1434 T.getAsStringInternal(Result, Policy);
1435 return Allocator.CopyString(Result);
1436}
1437
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001438/// \brief Add a completion for "this", if we're in a member function.
1439static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1440 QualType ThisTy = S.getCurrentThisType();
1441 if (ThisTy.isNull())
1442 return;
1443
1444 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001445 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001446 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1447 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1448 S.Context,
1449 Policy,
1450 Allocator));
1451 Builder.AddTypedTextChunk("this");
1452 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1453}
1454
Douglas Gregor01dfea02010-01-10 23:08:15 +00001455/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001456static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001457 Scope *S,
1458 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001459 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001460 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001461 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor8ca72082011-10-18 21:20:17 +00001462 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001463
John McCall0a2c5e22010-08-25 06:19:51 +00001464 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001465 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001466 case Sema::PCC_Namespace:
David Blaikie4e4d0842012-03-11 07:00:24 +00001467 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001468 if (Results.includeCodePatterns()) {
1469 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001470 Builder.AddTypedTextChunk("namespace");
1471 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1472 Builder.AddPlaceholderChunk("identifier");
1473 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1474 Builder.AddPlaceholderChunk("declarations");
1475 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1476 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1477 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001478 }
1479
Douglas Gregor01dfea02010-01-10 23:08:15 +00001480 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001481 Builder.AddTypedTextChunk("namespace");
1482 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1483 Builder.AddPlaceholderChunk("name");
1484 Builder.AddChunk(CodeCompletionString::CK_Equal);
1485 Builder.AddPlaceholderChunk("namespace");
1486 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001487
1488 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001489 Builder.AddTypedTextChunk("using");
1490 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1491 Builder.AddTextChunk("namespace");
1492 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1493 Builder.AddPlaceholderChunk("identifier");
1494 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001495
1496 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001497 Builder.AddTypedTextChunk("asm");
1498 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1499 Builder.AddPlaceholderChunk("string-literal");
1500 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1501 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001502
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001503 if (Results.includeCodePatterns()) {
1504 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001505 Builder.AddTypedTextChunk("template");
1506 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1507 Builder.AddPlaceholderChunk("declaration");
1508 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001509 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001510 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001511
David Blaikie4e4d0842012-03-11 07:00:24 +00001512 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001513 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001514
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001515 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001516 // Fall through
1517
John McCallf312b1e2010-08-26 23:41:50 +00001518 case Sema::PCC_Class:
David Blaikie4e4d0842012-03-11 07:00:24 +00001519 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001520 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001521 Builder.AddTypedTextChunk("using");
1522 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1523 Builder.AddPlaceholderChunk("qualifier");
1524 Builder.AddTextChunk("::");
1525 Builder.AddPlaceholderChunk("name");
1526 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001527
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001528 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001529 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001530 Builder.AddTypedTextChunk("using");
1531 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1532 Builder.AddTextChunk("typename");
1533 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1534 Builder.AddPlaceholderChunk("qualifier");
1535 Builder.AddTextChunk("::");
1536 Builder.AddPlaceholderChunk("name");
1537 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001538 }
1539
John McCallf312b1e2010-08-26 23:41:50 +00001540 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001541 AddTypedefResult(Results);
1542
Douglas Gregor01dfea02010-01-10 23:08:15 +00001543 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001544 Builder.AddTypedTextChunk("public");
1545 Builder.AddChunk(CodeCompletionString::CK_Colon);
1546 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001547
1548 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001549 Builder.AddTypedTextChunk("protected");
1550 Builder.AddChunk(CodeCompletionString::CK_Colon);
1551 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001552
1553 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001554 Builder.AddTypedTextChunk("private");
1555 Builder.AddChunk(CodeCompletionString::CK_Colon);
1556 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001557 }
1558 }
1559 // Fall through
1560
John McCallf312b1e2010-08-26 23:41:50 +00001561 case Sema::PCC_Template:
1562 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001563 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001564 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001565 Builder.AddTypedTextChunk("template");
1566 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1567 Builder.AddPlaceholderChunk("parameters");
1568 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1569 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001570 }
1571
David Blaikie4e4d0842012-03-11 07:00:24 +00001572 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1573 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001574 break;
1575
John McCallf312b1e2010-08-26 23:41:50 +00001576 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001577 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1578 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1579 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001580 break;
1581
John McCallf312b1e2010-08-26 23:41:50 +00001582 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001583 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1584 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1585 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001586 break;
1587
John McCallf312b1e2010-08-26 23:41:50 +00001588 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001589 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001590 break;
1591
John McCallf312b1e2010-08-26 23:41:50 +00001592 case Sema::PCC_RecoveryInFunction:
1593 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001594 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001595
David Blaikie4e4d0842012-03-11 07:00:24 +00001596 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1597 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001598 Builder.AddTypedTextChunk("try");
1599 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1600 Builder.AddPlaceholderChunk("statements");
1601 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1602 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1603 Builder.AddTextChunk("catch");
1604 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1605 Builder.AddPlaceholderChunk("declaration");
1606 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1607 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1608 Builder.AddPlaceholderChunk("statements");
1609 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1610 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1611 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001612 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001613 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001614 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001615
Douglas Gregord8e8a582010-05-25 21:41:55 +00001616 if (Results.includeCodePatterns()) {
1617 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001618 Builder.AddTypedTextChunk("if");
1619 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001620 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001621 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001622 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001623 Builder.AddPlaceholderChunk("expression");
1624 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1625 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1626 Builder.AddPlaceholderChunk("statements");
1627 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1628 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1629 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001630
Douglas Gregord8e8a582010-05-25 21:41:55 +00001631 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001632 Builder.AddTypedTextChunk("switch");
1633 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001634 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001635 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001636 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001637 Builder.AddPlaceholderChunk("expression");
1638 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1639 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1640 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1641 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1642 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001643 }
1644
Douglas Gregor01dfea02010-01-10 23:08:15 +00001645 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001646 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001647 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001648 Builder.AddTypedTextChunk("case");
1649 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1650 Builder.AddPlaceholderChunk("expression");
1651 Builder.AddChunk(CodeCompletionString::CK_Colon);
1652 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001653
1654 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001655 Builder.AddTypedTextChunk("default");
1656 Builder.AddChunk(CodeCompletionString::CK_Colon);
1657 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001658 }
1659
Douglas Gregord8e8a582010-05-25 21:41:55 +00001660 if (Results.includeCodePatterns()) {
1661 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001662 Builder.AddTypedTextChunk("while");
1663 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001664 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001665 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001666 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001667 Builder.AddPlaceholderChunk("expression");
1668 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1669 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1670 Builder.AddPlaceholderChunk("statements");
1671 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1672 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1673 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001674
1675 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001676 Builder.AddTypedTextChunk("do");
1677 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1678 Builder.AddPlaceholderChunk("statements");
1679 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1680 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1681 Builder.AddTextChunk("while");
1682 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1683 Builder.AddPlaceholderChunk("expression");
1684 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1685 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001686
Douglas Gregord8e8a582010-05-25 21:41:55 +00001687 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001688 Builder.AddTypedTextChunk("for");
1689 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001690 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001691 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001692 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001693 Builder.AddPlaceholderChunk("init-expression");
1694 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1695 Builder.AddPlaceholderChunk("condition");
1696 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1697 Builder.AddPlaceholderChunk("inc-expression");
1698 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1699 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1700 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1701 Builder.AddPlaceholderChunk("statements");
1702 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1703 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1704 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001705 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001706
1707 if (S->getContinueParent()) {
1708 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001709 Builder.AddTypedTextChunk("continue");
1710 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001711 }
1712
1713 if (S->getBreakParent()) {
1714 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("break");
1716 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001717 }
1718
1719 // "return expression ;" or "return ;", depending on whether we
1720 // know the function is void or not.
1721 bool isVoid = false;
1722 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1723 isVoid = Function->getResultType()->isVoidType();
1724 else if (ObjCMethodDecl *Method
1725 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1726 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001727 else if (SemaRef.getCurBlock() &&
1728 !SemaRef.getCurBlock()->ReturnType.isNull())
1729 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001730 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001731 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001732 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1733 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001734 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001735 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001736
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001737 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001738 Builder.AddTypedTextChunk("goto");
1739 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1740 Builder.AddPlaceholderChunk("label");
1741 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001742
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001743 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001744 Builder.AddTypedTextChunk("using");
1745 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1746 Builder.AddTextChunk("namespace");
1747 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1748 Builder.AddPlaceholderChunk("identifier");
1749 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001750 }
1751
1752 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001753 case Sema::PCC_ForInit:
1754 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001755 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001756 // Fall through: conditions and statements can have expressions.
1757
Douglas Gregor02688102010-09-14 23:59:36 +00001758 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001759 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001760 CCC == Sema::PCC_ParenthesizedExpression) {
1761 // (__bridge <type>)<expression>
1762 Builder.AddTypedTextChunk("__bridge");
1763 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1764 Builder.AddPlaceholderChunk("type");
1765 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1766 Builder.AddPlaceholderChunk("expression");
1767 Results.AddResult(Result(Builder.TakeString()));
1768
1769 // (__bridge_transfer <Objective-C type>)<expression>
1770 Builder.AddTypedTextChunk("__bridge_transfer");
1771 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1772 Builder.AddPlaceholderChunk("Objective-C type");
1773 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1774 Builder.AddPlaceholderChunk("expression");
1775 Results.AddResult(Result(Builder.TakeString()));
1776
1777 // (__bridge_retained <CF type>)<expression>
1778 Builder.AddTypedTextChunk("__bridge_retained");
1779 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1780 Builder.AddPlaceholderChunk("CF type");
1781 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1782 Builder.AddPlaceholderChunk("expression");
1783 Results.AddResult(Result(Builder.TakeString()));
1784 }
1785 // Fall through
1786
John McCallf312b1e2010-08-26 23:41:50 +00001787 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001788 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001789 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001790 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001791
Douglas Gregor8ca72082011-10-18 21:20:17 +00001792 // true
1793 Builder.AddResultTypeChunk("bool");
1794 Builder.AddTypedTextChunk("true");
1795 Results.AddResult(Result(Builder.TakeString()));
1796
1797 // false
1798 Builder.AddResultTypeChunk("bool");
1799 Builder.AddTypedTextChunk("false");
1800 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001801
David Blaikie4e4d0842012-03-11 07:00:24 +00001802 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001803 // dynamic_cast < type-id > ( expression )
1804 Builder.AddTypedTextChunk("dynamic_cast");
1805 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1806 Builder.AddPlaceholderChunk("type");
1807 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1808 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1809 Builder.AddPlaceholderChunk("expression");
1810 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1811 Results.AddResult(Result(Builder.TakeString()));
1812 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001813
1814 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001815 Builder.AddTypedTextChunk("static_cast");
1816 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1817 Builder.AddPlaceholderChunk("type");
1818 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1819 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1820 Builder.AddPlaceholderChunk("expression");
1821 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1822 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001823
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001824 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001825 Builder.AddTypedTextChunk("reinterpret_cast");
1826 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1827 Builder.AddPlaceholderChunk("type");
1828 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1829 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1830 Builder.AddPlaceholderChunk("expression");
1831 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1832 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001833
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001834 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001835 Builder.AddTypedTextChunk("const_cast");
1836 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1837 Builder.AddPlaceholderChunk("type");
1838 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1839 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1840 Builder.AddPlaceholderChunk("expression");
1841 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1842 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001843
David Blaikie4e4d0842012-03-11 07:00:24 +00001844 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001845 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001846 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001847 Builder.AddTypedTextChunk("typeid");
1848 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1849 Builder.AddPlaceholderChunk("expression-or-type");
1850 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1851 Results.AddResult(Result(Builder.TakeString()));
1852 }
1853
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001854 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001855 Builder.AddTypedTextChunk("new");
1856 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1857 Builder.AddPlaceholderChunk("type");
1858 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1859 Builder.AddPlaceholderChunk("expressions");
1860 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1861 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001862
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001863 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001864 Builder.AddTypedTextChunk("new");
1865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1866 Builder.AddPlaceholderChunk("type");
1867 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1868 Builder.AddPlaceholderChunk("size");
1869 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1870 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1871 Builder.AddPlaceholderChunk("expressions");
1872 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1873 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001874
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001875 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001876 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001877 Builder.AddTypedTextChunk("delete");
1878 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1879 Builder.AddPlaceholderChunk("expression");
1880 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001881
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001882 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001883 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001884 Builder.AddTypedTextChunk("delete");
1885 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1886 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1887 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1888 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1889 Builder.AddPlaceholderChunk("expression");
1890 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001891
David Blaikie4e4d0842012-03-11 07:00:24 +00001892 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001893 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001894 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001895 Builder.AddTypedTextChunk("throw");
1896 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1897 Builder.AddPlaceholderChunk("expression");
1898 Results.AddResult(Result(Builder.TakeString()));
1899 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001900
Douglas Gregor12e13132010-05-26 22:00:08 +00001901 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001902
David Blaikie4e4d0842012-03-11 07:00:24 +00001903 if (SemaRef.getLangOpts().CPlusPlus0x) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001904 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001905 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001906 Builder.AddTypedTextChunk("nullptr");
1907 Results.AddResult(Result(Builder.TakeString()));
1908
1909 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001910 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001911 Builder.AddTypedTextChunk("alignof");
1912 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1913 Builder.AddPlaceholderChunk("type");
1914 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1915 Results.AddResult(Result(Builder.TakeString()));
1916
1917 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001918 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001919 Builder.AddTypedTextChunk("noexcept");
1920 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1921 Builder.AddPlaceholderChunk("expression");
1922 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1923 Results.AddResult(Result(Builder.TakeString()));
1924
1925 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001926 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001927 Builder.AddTypedTextChunk("sizeof...");
1928 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1929 Builder.AddPlaceholderChunk("parameter-pack");
1930 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1931 Results.AddResult(Result(Builder.TakeString()));
1932 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001933 }
1934
David Blaikie4e4d0842012-03-11 07:00:24 +00001935 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001936 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001937 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1938 // The interface can be NULL.
1939 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001940 if (ID->getSuperClass()) {
1941 std::string SuperType;
1942 SuperType = ID->getSuperClass()->getNameAsString();
1943 if (Method->isInstanceMethod())
1944 SuperType += " *";
1945
1946 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1947 Builder.AddTypedTextChunk("super");
1948 Results.AddResult(Result(Builder.TakeString()));
1949 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001950 }
1951
Douglas Gregorbca403c2010-01-13 23:51:12 +00001952 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001953 }
1954
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001955 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001956 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001957 Builder.AddTypedTextChunk("sizeof");
1958 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1959 Builder.AddPlaceholderChunk("expression-or-type");
1960 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1961 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001962 break;
1963 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001964
John McCallf312b1e2010-08-26 23:41:50 +00001965 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001966 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001967 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001968 }
1969
David Blaikie4e4d0842012-03-11 07:00:24 +00001970 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1971 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001972
David Blaikie4e4d0842012-03-11 07:00:24 +00001973 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001974 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001975}
1976
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001977/// \brief If the given declaration has an associated type, add it as a result
1978/// type chunk.
1979static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00001980 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001981 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001982 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001983 if (!ND)
1984 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001985
1986 // Skip constructors and conversion functions, which have their return types
1987 // built into their names.
1988 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1989 return;
1990
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001991 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001992 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001993 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1994 T = Function->getResultType();
1995 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1996 T = Method->getResultType();
1997 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1998 T = FunTmpl->getTemplatedDecl()->getResultType();
1999 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
2000 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2001 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2002 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00002003 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002004 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00002005 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002006 T = Property->getType();
2007
2008 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2009 return;
2010
Douglas Gregor8987b232011-09-27 23:30:47 +00002011 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002012 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002013}
2014
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002015static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002016 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002017 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2018 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002019 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002020 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002021 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002022 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002023 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002024 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002025 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002026 }
2027}
2028
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002029static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2030 std::string Result;
2031 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002032 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002033 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002034 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002035 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002036 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002037 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002038 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002039 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002040 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002041 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002042 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002043 return Result;
2044}
2045
Douglas Gregor83482d12010-08-24 16:15:59 +00002046static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002047 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002048 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002049 bool SuppressName = false,
2050 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002051 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2052 if (Param->getType()->isDependentType() ||
2053 !Param->getType()->isBlockPointerType()) {
2054 // The argument for a dependent or non-block parameter is a placeholder
2055 // containing that parameter's type.
2056 std::string Result;
2057
Douglas Gregoraba48082010-08-29 19:47:46 +00002058 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002059 Result = Param->getIdentifier()->getName();
2060
John McCallf85e1932011-06-15 23:02:42 +00002061 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002062
2063 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002064 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2065 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002066 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002067 Result += Param->getIdentifier()->getName();
2068 }
2069 return Result;
2070 }
2071
2072 // The argument for a block pointer parameter is a block literal with
2073 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002074 FunctionTypeLoc *Block = 0;
2075 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002076 TypeLoc TL;
2077 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2078 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2079 while (true) {
2080 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002081 if (!SuppressBlock) {
2082 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2083 if (TypeSourceInfo *InnerTSInfo
2084 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2085 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2086 continue;
2087 }
2088 }
2089
2090 // Look through qualified types
2091 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2092 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002093 continue;
2094 }
2095 }
2096
Douglas Gregor83482d12010-08-24 16:15:59 +00002097 // Try to get the function prototype behind the block pointer type,
2098 // then we're done.
2099 if (BlockPointerTypeLoc *BlockPtr
2100 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002101 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002102 Block = dyn_cast<FunctionTypeLoc>(&TL);
2103 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002104 }
2105 break;
2106 }
2107 }
2108
2109 if (!Block) {
2110 // We were unable to find a FunctionProtoTypeLoc with parameter names
2111 // for the block; just use the parameter type as a placeholder.
2112 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002113 if (!ObjCMethodParam && Param->getIdentifier())
2114 Result = Param->getIdentifier()->getName();
2115
John McCallf85e1932011-06-15 23:02:42 +00002116 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002117
2118 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002119 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2120 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002121 if (Param->getIdentifier())
2122 Result += Param->getIdentifier()->getName();
2123 }
2124
2125 return Result;
2126 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002127
Douglas Gregor83482d12010-08-24 16:15:59 +00002128 // We have the function prototype behind the block pointer type, as it was
2129 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002130 std::string Result;
2131 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002132 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002133 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002134
2135 // Format the parameter list.
2136 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002137 if (!BlockProto || Block->getNumArgs() == 0) {
2138 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002139 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002140 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002141 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002142 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002143 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002144 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2145 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002146 Params += ", ";
2147 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2148 /*SuppressName=*/false,
2149 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002150
Douglas Gregor830072c2011-02-15 22:37:09 +00002151 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002152 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002153 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002154 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002155 }
Douglas Gregor38276252010-09-08 22:47:51 +00002156
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002157 if (SuppressBlock) {
2158 // Format as a parameter.
2159 Result = Result + " (^";
2160 if (Param->getIdentifier())
2161 Result += Param->getIdentifier()->getName();
2162 Result += ")";
2163 Result += Params;
2164 } else {
2165 // Format as a block literal argument.
2166 Result = '^' + Result;
2167 Result += Params;
2168
2169 if (Param->getIdentifier())
2170 Result += Param->getIdentifier()->getName();
2171 }
2172
Douglas Gregor83482d12010-08-24 16:15:59 +00002173 return Result;
2174}
2175
Douglas Gregor86d9a522009-09-21 16:56:56 +00002176/// \brief Add function parameter chunks to the given code completion string.
2177static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002178 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002179 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002180 CodeCompletionBuilder &Result,
2181 unsigned Start = 0,
2182 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002183 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002184
Douglas Gregor218937c2011-02-01 19:23:04 +00002185 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002186 ParmVarDecl *Param = Function->getParamDecl(P);
2187
Douglas Gregor218937c2011-02-01 19:23:04 +00002188 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002189 // When we see an optional default argument, put that argument and
2190 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002191 CodeCompletionBuilder Opt(Result.getAllocator(),
2192 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002193 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002194 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002195 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002196 Result.AddOptionalChunk(Opt.TakeString());
2197 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002198 }
2199
Douglas Gregor218937c2011-02-01 19:23:04 +00002200 if (FirstParameter)
2201 FirstParameter = false;
2202 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002203 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002204
2205 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002206
2207 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002208 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2209 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002210
Douglas Gregore17794f2010-08-31 05:13:43 +00002211 if (Function->isVariadic() && P == N - 1)
2212 PlaceholderStr += ", ...";
2213
Douglas Gregor86d9a522009-09-21 16:56:56 +00002214 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002215 Result.AddPlaceholderChunk(
2216 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002217 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002218
2219 if (const FunctionProtoType *Proto
2220 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002221 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002222 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002223 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002224
Douglas Gregor218937c2011-02-01 19:23:04 +00002225 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002226 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002227}
2228
2229/// \brief Add template parameter chunks to the given code completion string.
2230static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002231 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002232 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002233 CodeCompletionBuilder &Result,
2234 unsigned MaxParameters = 0,
2235 unsigned Start = 0,
2236 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002237 bool FirstParameter = true;
2238
2239 TemplateParameterList *Params = Template->getTemplateParameters();
2240 TemplateParameterList::iterator PEnd = Params->end();
2241 if (MaxParameters)
2242 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002243 for (TemplateParameterList::iterator P = Params->begin() + Start;
2244 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002245 bool HasDefaultArg = false;
2246 std::string PlaceholderStr;
2247 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2248 if (TTP->wasDeclaredWithTypename())
2249 PlaceholderStr = "typename";
2250 else
2251 PlaceholderStr = "class";
2252
2253 if (TTP->getIdentifier()) {
2254 PlaceholderStr += ' ';
2255 PlaceholderStr += TTP->getIdentifier()->getName();
2256 }
2257
2258 HasDefaultArg = TTP->hasDefaultArgument();
2259 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002260 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002261 if (NTTP->getIdentifier())
2262 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002263 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002264 HasDefaultArg = NTTP->hasDefaultArgument();
2265 } else {
2266 assert(isa<TemplateTemplateParmDecl>(*P));
2267 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2268
2269 // Since putting the template argument list into the placeholder would
2270 // be very, very long, we just use an abbreviation.
2271 PlaceholderStr = "template<...> class";
2272 if (TTP->getIdentifier()) {
2273 PlaceholderStr += ' ';
2274 PlaceholderStr += TTP->getIdentifier()->getName();
2275 }
2276
2277 HasDefaultArg = TTP->hasDefaultArgument();
2278 }
2279
Douglas Gregor218937c2011-02-01 19:23:04 +00002280 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002281 // When we see an optional default argument, put that argument and
2282 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002283 CodeCompletionBuilder Opt(Result.getAllocator(),
2284 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002285 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002286 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002287 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002288 P - Params->begin(), true);
2289 Result.AddOptionalChunk(Opt.TakeString());
2290 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002291 }
2292
Douglas Gregor218937c2011-02-01 19:23:04 +00002293 InDefaultArg = false;
2294
Douglas Gregor86d9a522009-09-21 16:56:56 +00002295 if (FirstParameter)
2296 FirstParameter = false;
2297 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002298 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002299
2300 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002301 Result.AddPlaceholderChunk(
2302 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002303 }
2304}
2305
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002306/// \brief Add a qualifier to the given code-completion string, if the
2307/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002308static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002309AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002310 NestedNameSpecifier *Qualifier,
2311 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002312 ASTContext &Context,
2313 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002314 if (!Qualifier)
2315 return;
2316
2317 std::string PrintedNNS;
2318 {
2319 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002320 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002321 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002322 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002323 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002324 else
Douglas Gregordae68752011-02-01 22:57:45 +00002325 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002326}
2327
Douglas Gregor218937c2011-02-01 19:23:04 +00002328static void
2329AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2330 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002331 const FunctionProtoType *Proto
2332 = Function->getType()->getAs<FunctionProtoType>();
2333 if (!Proto || !Proto->getTypeQuals())
2334 return;
2335
Douglas Gregora63f6de2011-02-01 21:15:40 +00002336 // FIXME: Add ref-qualifier!
2337
2338 // Handle single qualifiers without copying
2339 if (Proto->getTypeQuals() == Qualifiers::Const) {
2340 Result.AddInformativeChunk(" const");
2341 return;
2342 }
2343
2344 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2345 Result.AddInformativeChunk(" volatile");
2346 return;
2347 }
2348
2349 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2350 Result.AddInformativeChunk(" restrict");
2351 return;
2352 }
2353
2354 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002355 std::string QualsStr;
2356 if (Proto->getTypeQuals() & Qualifiers::Const)
2357 QualsStr += " const";
2358 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2359 QualsStr += " volatile";
2360 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2361 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002362 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002363}
2364
Douglas Gregor6f942b22010-09-21 16:06:22 +00002365/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002366static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2367 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002368 DeclarationName Name = ND->getDeclName();
2369 if (!Name)
2370 return;
2371
2372 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002373 case DeclarationName::CXXOperatorName: {
2374 const char *OperatorName = 0;
2375 switch (Name.getCXXOverloadedOperator()) {
2376 case OO_None:
2377 case OO_Conditional:
2378 case NUM_OVERLOADED_OPERATORS:
2379 OperatorName = "operator";
2380 break;
2381
2382#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2383 case OO_##Name: OperatorName = "operator" Spelling; break;
2384#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2385#include "clang/Basic/OperatorKinds.def"
2386
2387 case OO_New: OperatorName = "operator new"; break;
2388 case OO_Delete: OperatorName = "operator delete"; break;
2389 case OO_Array_New: OperatorName = "operator new[]"; break;
2390 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2391 case OO_Call: OperatorName = "operator()"; break;
2392 case OO_Subscript: OperatorName = "operator[]"; break;
2393 }
2394 Result.AddTypedTextChunk(OperatorName);
2395 break;
2396 }
2397
Douglas Gregor6f942b22010-09-21 16:06:22 +00002398 case DeclarationName::Identifier:
2399 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002400 case DeclarationName::CXXDestructorName:
2401 case DeclarationName::CXXLiteralOperatorName:
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 case DeclarationName::CXXUsingDirective:
2407 case DeclarationName::ObjCZeroArgSelector:
2408 case DeclarationName::ObjCOneArgSelector:
2409 case DeclarationName::ObjCMultiArgSelector:
2410 break;
2411
2412 case DeclarationName::CXXConstructorName: {
2413 CXXRecordDecl *Record = 0;
2414 QualType Ty = Name.getCXXNameType();
2415 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2416 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2417 else if (const InjectedClassNameType *InjectedTy
2418 = Ty->getAs<InjectedClassNameType>())
2419 Record = InjectedTy->getDecl();
2420 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002421 Result.AddTypedTextChunk(
2422 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002423 break;
2424 }
2425
Douglas Gregordae68752011-02-01 22:57:45 +00002426 Result.AddTypedTextChunk(
2427 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002428 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002429 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002430 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002431 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002432 }
2433 break;
2434 }
2435 }
2436}
2437
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002438CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002439 CodeCompletionAllocator &Allocator,
2440 CodeCompletionTUInfo &CCTUInfo) {
2441 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002442}
2443
Douglas Gregor86d9a522009-09-21 16:56:56 +00002444/// \brief If possible, create a new code completion string for the given
2445/// result.
2446///
2447/// \returns Either a new, heap-allocated code completion string describing
2448/// how to use this result, or NULL to indicate that the string or name of the
2449/// result is all that is needed.
2450CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002451CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2452 Preprocessor &PP,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002453 CodeCompletionAllocator &Allocator,
2454 CodeCompletionTUInfo &CCTUInfo) {
2455 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002456
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002457 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002458 if (Kind == RK_Pattern) {
2459 Pattern->Priority = Priority;
2460 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002461
2462 if (Declaration) {
2463 Result.addParentContext(Declaration->getDeclContext());
2464 Pattern->ParentKind = Result.getParentKind();
2465 Pattern->ParentName = Result.getParentName();
2466 }
2467
Douglas Gregor218937c2011-02-01 19:23:04 +00002468 return Pattern;
2469 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002470
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002471 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002472 Result.AddTypedTextChunk(Keyword);
2473 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002474 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002475
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002476 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002477 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002478 assert(MI && "Not a macro?");
2479
Douglas Gregordae68752011-02-01 22:57:45 +00002480 Result.AddTypedTextChunk(
2481 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002482
2483 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002484 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002485
2486 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002487 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002488 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002489
2490 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2491 if (MI->isC99Varargs()) {
2492 --AEnd;
2493
2494 if (A == AEnd) {
2495 Result.AddPlaceholderChunk("...");
2496 }
Douglas Gregore4244702011-07-30 08:17:44 +00002497 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002498
Douglas Gregore4244702011-07-30 08:17:44 +00002499 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002500 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002501 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002502
2503 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002504 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002505 if (MI->isC99Varargs())
2506 Arg += ", ...";
2507 else
2508 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002509 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002510 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002511 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002512
2513 // Non-variadic macros are simple.
2514 Result.AddPlaceholderChunk(
2515 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002516 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002517 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002518 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002519 }
2520
Douglas Gregord8e8a582010-05-25 21:41:55 +00002521 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002522 NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002523 Result.addParentContext(ND->getDeclContext());
2524
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002525 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002526 Result.AddTypedTextChunk(
2527 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002528 Result.AddTextChunk("::");
2529 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002530 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002531
2532 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2533 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2534 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2535 }
2536 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002537
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002538 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002539
Douglas Gregor86d9a522009-09-21 16:56:56 +00002540 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002541 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002542 Ctx, Policy);
2543 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002544 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002545 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002546 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002547 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002548 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002549 }
2550
2551 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002552 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002553 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002554 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002555 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002556
Douglas Gregor86d9a522009-09-21 16:56:56 +00002557 // Figure out which template parameters are deduced (or have default
2558 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002559 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002560 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002561 unsigned LastDeducibleArgument;
2562 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2563 --LastDeducibleArgument) {
2564 if (!Deduced[LastDeducibleArgument - 1]) {
2565 // C++0x: Figure out if the template argument has a default. If so,
2566 // the user doesn't need to type this argument.
2567 // FIXME: We need to abstract template parameters better!
2568 bool HasDefaultArg = false;
2569 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002570 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002571 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2572 HasDefaultArg = TTP->hasDefaultArgument();
2573 else if (NonTypeTemplateParmDecl *NTTP
2574 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2575 HasDefaultArg = NTTP->hasDefaultArgument();
2576 else {
2577 assert(isa<TemplateTemplateParmDecl>(Param));
2578 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002579 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002580 }
2581
2582 if (!HasDefaultArg)
2583 break;
2584 }
2585 }
2586
2587 if (LastDeducibleArgument) {
2588 // Some of the function template arguments cannot be deduced from a
2589 // function call, so we introduce an explicit template argument list
2590 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002591 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002592 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002593 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002594 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002595 }
2596
2597 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002598 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002599 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002600 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002601 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002602 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002603 }
2604
2605 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002606 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002607 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002608 Result.AddTypedTextChunk(
2609 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002610 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002611 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002612 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002613 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002614 }
2615
Douglas Gregor9630eb62009-11-17 16:44:22 +00002616 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002617 Selector Sel = Method->getSelector();
2618 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002619 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002620 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002621 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002622 }
2623
Douglas Gregor813d8342011-02-18 22:29:55 +00002624 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002625 SelName += ':';
2626 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002627 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002628 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002629 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002630
2631 // If there is only one parameter, and we're past it, add an empty
2632 // typed-text chunk since there is nothing to type.
2633 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002634 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002635 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002636 unsigned Idx = 0;
2637 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2638 PEnd = Method->param_end();
2639 P != PEnd; (void)++P, ++Idx) {
2640 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002641 std::string Keyword;
2642 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002643 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002644 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002645 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002646 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002647 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002648 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002649 else
Douglas Gregordae68752011-02-01 22:57:45 +00002650 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002651 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002652
2653 // If we're before the starting parameter, skip the placeholder.
2654 if (Idx < StartParameter)
2655 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002656
2657 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002658
2659 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002660 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002661 else {
John McCallf85e1932011-06-15 23:02:42 +00002662 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002663 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2664 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002665 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002666 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002667 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002668 }
2669
Douglas Gregore17794f2010-08-31 05:13:43 +00002670 if (Method->isVariadic() && (P + 1) == PEnd)
2671 Arg += ", ...";
2672
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002673 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002674 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002675 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002676 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002677 else
Douglas Gregordae68752011-02-01 22:57:45 +00002678 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002679 }
2680
Douglas Gregor2a17af02009-12-23 00:21:46 +00002681 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002682 if (Method->param_size() == 0) {
2683 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002684 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002685 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002686 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002687 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002688 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002689 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002690
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002691 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002692 }
2693
Douglas Gregor218937c2011-02-01 19:23:04 +00002694 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002695 }
2696
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002697 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002698 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002699 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002700
Douglas Gregordae68752011-02-01 22:57:45 +00002701 Result.AddTypedTextChunk(
2702 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002703 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002704}
2705
Douglas Gregor86d802e2009-09-23 00:34:09 +00002706CodeCompletionString *
2707CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2708 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002709 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002710 CodeCompletionAllocator &Allocator,
2711 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002712 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002713
Douglas Gregor218937c2011-02-01 19:23:04 +00002714 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002715 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002716 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002717 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002718 const FunctionProtoType *Proto
2719 = dyn_cast<FunctionProtoType>(getFunctionType());
2720 if (!FDecl && !Proto) {
2721 // Function without a prototype. Just give the return type and a
2722 // highlighted ellipsis.
2723 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002724 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002725 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002726 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002727 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2728 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2729 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002730 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002731 }
2732
2733 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002734 Result.AddTextChunk(
2735 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002736 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002737 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002738 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002739 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002740
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002741 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002742 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2743 for (unsigned I = 0; I != NumParams; ++I) {
2744 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002745 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002746
2747 std::string ArgString;
2748 QualType ArgType;
2749
2750 if (FDecl) {
2751 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2752 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2753 } else {
2754 ArgType = Proto->getArgType(I);
2755 }
2756
John McCallf85e1932011-06-15 23:02:42 +00002757 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002758
2759 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002760 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2761 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002762 else
Douglas Gregordae68752011-02-01 22:57:45 +00002763 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002764 }
2765
2766 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002767 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002768 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002769 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002770 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002771 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002772 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002773 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002774
Douglas Gregor218937c2011-02-01 19:23:04 +00002775 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002776}
2777
Chris Lattner5f9e2722011-07-23 10:55:15 +00002778unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002779 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002780 bool PreferredTypeIsPointer) {
2781 unsigned Priority = CCP_Macro;
2782
Douglas Gregorb05496d2010-09-20 21:11:48 +00002783 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2784 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2785 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002786 Priority = CCP_Constant;
2787 if (PreferredTypeIsPointer)
2788 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002789 }
2790 // Treat "YES", "NO", "true", and "false" as constants.
2791 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2792 MacroName.equals("true") || MacroName.equals("false"))
2793 Priority = CCP_Constant;
2794 // Treat "bool" as a type.
2795 else if (MacroName.equals("bool"))
2796 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2797
Douglas Gregor1827e102010-08-16 16:18:59 +00002798
2799 return Priority;
2800}
2801
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002802CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2803 if (!D)
2804 return CXCursor_UnexposedDecl;
2805
2806 switch (D->getKind()) {
2807 case Decl::Enum: return CXCursor_EnumDecl;
2808 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2809 case Decl::Field: return CXCursor_FieldDecl;
2810 case Decl::Function:
2811 return CXCursor_FunctionDecl;
2812 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2813 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002814 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002815
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002816 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002817 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2818 case Decl::ObjCMethod:
2819 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2820 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2821 case Decl::CXXMethod: return CXCursor_CXXMethod;
2822 case Decl::CXXConstructor: return CXCursor_Constructor;
2823 case Decl::CXXDestructor: return CXCursor_Destructor;
2824 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2825 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002826 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002827 case Decl::ParmVar: return CXCursor_ParmDecl;
2828 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002829 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002830 case Decl::Var: return CXCursor_VarDecl;
2831 case Decl::Namespace: return CXCursor_Namespace;
2832 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2833 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2834 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2835 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2836 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2837 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002838 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002839 case Decl::ClassTemplatePartialSpecialization:
2840 return CXCursor_ClassTemplatePartialSpecialization;
2841 case Decl::UsingDirective: return CXCursor_UsingDirective;
2842
2843 case Decl::Using:
2844 case Decl::UnresolvedUsingValue:
2845 case Decl::UnresolvedUsingTypename:
2846 return CXCursor_UsingDeclaration;
2847
Douglas Gregor352697a2011-06-03 23:08:58 +00002848 case Decl::ObjCPropertyImpl:
2849 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2850 case ObjCPropertyImplDecl::Dynamic:
2851 return CXCursor_ObjCDynamicDecl;
2852
2853 case ObjCPropertyImplDecl::Synthesize:
2854 return CXCursor_ObjCSynthesizeDecl;
2855 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002856
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002857 default:
2858 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2859 switch (TD->getTagKind()) {
2860 case TTK_Struct: return CXCursor_StructDecl;
2861 case TTK_Class: return CXCursor_ClassDecl;
2862 case TTK_Union: return CXCursor_UnionDecl;
2863 case TTK_Enum: return CXCursor_EnumDecl;
2864 }
2865 }
2866 }
2867
2868 return CXCursor_UnexposedDecl;
2869}
2870
Douglas Gregor590c7d52010-07-08 20:55:51 +00002871static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2872 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002873 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002874
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002875 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002876
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002877 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2878 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002879 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002880 Results.AddResult(Result(M->first,
2881 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002882 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002883 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002884 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002885
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002886 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002887
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002888}
2889
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002890static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2891 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002892 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002893
2894 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002895
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002896 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2897 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2898 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2899 Results.AddResult(Result("__func__", CCP_Constant));
2900 Results.ExitScope();
2901}
2902
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002903static void HandleCodeCompleteResults(Sema *S,
2904 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002905 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002906 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002907 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002908 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002909 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002910}
2911
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002912static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2913 Sema::ParserCompletionContext PCC) {
2914 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002915 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002916 return CodeCompletionContext::CCC_TopLevel;
2917
John McCallf312b1e2010-08-26 23:41:50 +00002918 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002919 return CodeCompletionContext::CCC_ClassStructUnion;
2920
John McCallf312b1e2010-08-26 23:41:50 +00002921 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002922 return CodeCompletionContext::CCC_ObjCInterface;
2923
John McCallf312b1e2010-08-26 23:41:50 +00002924 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002925 return CodeCompletionContext::CCC_ObjCImplementation;
2926
John McCallf312b1e2010-08-26 23:41:50 +00002927 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002928 return CodeCompletionContext::CCC_ObjCIvarList;
2929
John McCallf312b1e2010-08-26 23:41:50 +00002930 case Sema::PCC_Template:
2931 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002932 if (S.CurContext->isFileContext())
2933 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002934 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002935 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002936 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002937
John McCallf312b1e2010-08-26 23:41:50 +00002938 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002939 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002940
John McCallf312b1e2010-08-26 23:41:50 +00002941 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002942 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2943 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002944 return CodeCompletionContext::CCC_ParenthesizedExpression;
2945 else
2946 return CodeCompletionContext::CCC_Expression;
2947
2948 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002949 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002950 return CodeCompletionContext::CCC_Expression;
2951
John McCallf312b1e2010-08-26 23:41:50 +00002952 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002953 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002954
John McCallf312b1e2010-08-26 23:41:50 +00002955 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002956 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002957
2958 case Sema::PCC_ParenthesizedExpression:
2959 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002960
2961 case Sema::PCC_LocalDeclarationSpecifiers:
2962 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002963 }
David Blaikie7530c032012-01-17 06:56:22 +00002964
2965 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002966}
2967
Douglas Gregorf6961522010-08-27 21:18:54 +00002968/// \brief If we're in a C++ virtual member function, add completion results
2969/// that invoke the functions we override, since it's common to invoke the
2970/// overridden function as well as adding new functionality.
2971///
2972/// \param S The semantic analysis object for which we are generating results.
2973///
2974/// \param InContext This context in which the nested-name-specifier preceding
2975/// the code-completion point
2976static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2977 ResultBuilder &Results) {
2978 // Look through blocks.
2979 DeclContext *CurContext = S.CurContext;
2980 while (isa<BlockDecl>(CurContext))
2981 CurContext = CurContext->getParent();
2982
2983
2984 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2985 if (!Method || !Method->isVirtual())
2986 return;
2987
2988 // We need to have names for all of the parameters, if we're going to
2989 // generate a forwarding call.
2990 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2991 PEnd = Method->param_end();
2992 P != PEnd;
2993 ++P) {
2994 if (!(*P)->getDeclName())
2995 return;
2996 }
2997
Douglas Gregor8987b232011-09-27 23:30:47 +00002998 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00002999 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3000 MEnd = Method->end_overridden_methods();
3001 M != MEnd; ++M) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003002 CodeCompletionBuilder Builder(Results.getAllocator(),
3003 Results.getCodeCompletionTUInfo());
Douglas Gregorf6961522010-08-27 21:18:54 +00003004 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3005 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3006 continue;
3007
3008 // If we need a nested-name-specifier, add one now.
3009 if (!InContext) {
3010 NestedNameSpecifier *NNS
3011 = getRequiredQualification(S.Context, CurContext,
3012 Overridden->getDeclContext());
3013 if (NNS) {
3014 std::string Str;
3015 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003016 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003017 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003018 }
3019 } else if (!InContext->Equals(Overridden->getDeclContext()))
3020 continue;
3021
Douglas Gregordae68752011-02-01 22:57:45 +00003022 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003023 Overridden->getNameAsString()));
3024 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003025 bool FirstParam = true;
3026 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3027 PEnd = Method->param_end();
3028 P != PEnd; ++P) {
3029 if (FirstParam)
3030 FirstParam = false;
3031 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003032 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003033
Douglas Gregordae68752011-02-01 22:57:45 +00003034 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003035 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003036 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003037 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3038 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003039 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003040 CXCursor_CXXMethod,
3041 CXAvailability_Available,
3042 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003043 Results.Ignore(Overridden);
3044 }
3045}
3046
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003047void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3048 ModuleIdPath Path) {
3049 typedef CodeCompletionResult Result;
3050 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003051 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003052 CodeCompletionContext::CCC_Other);
3053 Results.EnterNewScope();
3054
3055 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003056 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003057 typedef CodeCompletionResult Result;
3058 if (Path.empty()) {
3059 // Enumerate all top-level modules.
3060 llvm::SmallVector<Module *, 8> Modules;
3061 PP.getHeaderSearchInfo().collectAllModules(Modules);
3062 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3063 Builder.AddTypedTextChunk(
3064 Builder.getAllocator().CopyString(Modules[I]->Name));
3065 Results.AddResult(Result(Builder.TakeString(),
3066 CCP_Declaration,
3067 CXCursor_NotImplemented,
3068 Modules[I]->isAvailable()
3069 ? CXAvailability_Available
3070 : CXAvailability_NotAvailable));
3071 }
3072 } else {
3073 // Load the named module.
3074 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3075 Module::AllVisible,
3076 /*IsInclusionDirective=*/false);
3077 // Enumerate submodules.
3078 if (Mod) {
3079 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3080 SubEnd = Mod->submodule_end();
3081 Sub != SubEnd; ++Sub) {
3082
3083 Builder.AddTypedTextChunk(
3084 Builder.getAllocator().CopyString((*Sub)->Name));
3085 Results.AddResult(Result(Builder.TakeString(),
3086 CCP_Declaration,
3087 CXCursor_NotImplemented,
3088 (*Sub)->isAvailable()
3089 ? CXAvailability_Available
3090 : CXAvailability_NotAvailable));
3091 }
3092 }
3093 }
3094 Results.ExitScope();
3095 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3096 Results.data(),Results.size());
3097}
3098
Douglas Gregor01dfea02010-01-10 23:08:15 +00003099void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003100 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003101 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003102 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003103 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003104 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003105 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003106
Douglas Gregor01dfea02010-01-10 23:08:15 +00003107 // Determine how to filter results, e.g., so that the names of
3108 // values (functions, enumerators, function templates, etc.) are
3109 // only allowed where we can have an expression.
3110 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003111 case PCC_Namespace:
3112 case PCC_Class:
3113 case PCC_ObjCInterface:
3114 case PCC_ObjCImplementation:
3115 case PCC_ObjCInstanceVariableList:
3116 case PCC_Template:
3117 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003118 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003119 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003120 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3121 break;
3122
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003123 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003124 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003125 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003126 case PCC_ForInit:
3127 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003128 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003129 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3130 else
3131 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003132
David Blaikie4e4d0842012-03-11 07:00:24 +00003133 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003134 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003135 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003136
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003137 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003138 // Unfiltered
3139 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003140 }
3141
Douglas Gregor3cdee122010-08-26 16:36:48 +00003142 // If we are in a C++ non-static member function, check the qualifiers on
3143 // the member function to filter/prioritize the results list.
3144 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3145 if (CurMethod->isInstance())
3146 Results.setObjectTypeQualifiers(
3147 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3148
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003149 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003150 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3151 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003152
Douglas Gregorbca403c2010-01-13 23:51:12 +00003153 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003154 Results.ExitScope();
3155
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003156 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003157 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003158 case PCC_Expression:
3159 case PCC_Statement:
3160 case PCC_RecoveryInFunction:
3161 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003162 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003163 break;
3164
3165 case PCC_Namespace:
3166 case PCC_Class:
3167 case PCC_ObjCInterface:
3168 case PCC_ObjCImplementation:
3169 case PCC_ObjCInstanceVariableList:
3170 case PCC_Template:
3171 case PCC_MemberTemplate:
3172 case PCC_ForInit:
3173 case PCC_Condition:
3174 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003175 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003176 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003177 }
3178
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003179 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003180 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003181
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003182 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003183 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003184}
3185
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003186static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3187 ParsedType Receiver,
3188 IdentifierInfo **SelIdents,
3189 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003190 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003191 bool IsSuper,
3192 ResultBuilder &Results);
3193
3194void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3195 bool AllowNonIdentifiers,
3196 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003197 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003198 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003199 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003200 AllowNestedNameSpecifiers
3201 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3202 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003203 Results.EnterNewScope();
3204
3205 // Type qualifiers can come after names.
3206 Results.AddResult(Result("const"));
3207 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003208 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003209 Results.AddResult(Result("restrict"));
3210
David Blaikie4e4d0842012-03-11 07:00:24 +00003211 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003212 if (AllowNonIdentifiers) {
3213 Results.AddResult(Result("operator"));
3214 }
3215
3216 // Add nested-name-specifiers.
3217 if (AllowNestedNameSpecifiers) {
3218 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003219 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003220 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3221 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3222 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003223 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003224 }
3225 }
3226 Results.ExitScope();
3227
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003228 // If we're in a context where we might have an expression (rather than a
3229 // declaration), and what we've seen so far is an Objective-C type that could
3230 // be a receiver of a class message, this may be a class message send with
3231 // the initial opening bracket '[' missing. Add appropriate completions.
3232 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3233 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3234 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3235 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3236 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3237 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3238 DS.getTypeQualifiers() == 0 &&
3239 S &&
3240 (S->getFlags() & Scope::DeclScope) != 0 &&
3241 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3242 Scope::FunctionPrototypeScope |
3243 Scope::AtCatchScope)) == 0) {
3244 ParsedType T = DS.getRepAsType();
3245 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003246 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003247 }
3248
Douglas Gregor4497dd42010-08-24 04:59:56 +00003249 // Note that we intentionally suppress macro results here, since we do not
3250 // encourage using macros to produce the names of entities.
3251
Douglas Gregor52779fb2010-09-23 23:01:17 +00003252 HandleCodeCompleteResults(this, CodeCompleter,
3253 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003254 Results.data(), Results.size());
3255}
3256
Douglas Gregorfb629412010-08-23 21:17:50 +00003257struct Sema::CodeCompleteExpressionData {
3258 CodeCompleteExpressionData(QualType PreferredType = QualType())
3259 : PreferredType(PreferredType), IntegralConstantExpression(false),
3260 ObjCCollection(false) { }
3261
3262 QualType PreferredType;
3263 bool IntegralConstantExpression;
3264 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003265 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003266};
3267
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003268/// \brief Perform code-completion in an expression context when we know what
3269/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00003270///
3271/// \param IntegralConstantExpression Only permit integral constant
3272/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00003273void Sema::CodeCompleteExpression(Scope *S,
3274 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003275 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003276 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003277 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003278 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003279 if (Data.ObjCCollection)
3280 Results.setFilter(&ResultBuilder::IsObjCCollection);
3281 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003282 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003283 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003284 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3285 else
3286 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003287
3288 if (!Data.PreferredType.isNull())
3289 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3290
3291 // Ignore any declarations that we were told that we don't care about.
3292 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3293 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003294
3295 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003296 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3297 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003298
3299 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003300 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003301 Results.ExitScope();
3302
Douglas Gregor590c7d52010-07-08 20:55:51 +00003303 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003304 if (!Data.PreferredType.isNull())
3305 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3306 || Data.PreferredType->isMemberPointerType()
3307 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003308
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003309 if (S->getFnParent() &&
3310 !Data.ObjCCollection &&
3311 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003312 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003313
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003314 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003315 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003316 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003317 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3318 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003319 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003320}
3321
Douglas Gregorac5fd842010-09-18 01:28:11 +00003322void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3323 if (E.isInvalid())
3324 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003325 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003326 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003327}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003328
Douglas Gregor73449212010-12-09 23:01:55 +00003329/// \brief The set of properties that have already been added, referenced by
3330/// property name.
3331typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3332
Douglas Gregor95ac6552009-11-18 01:29:26 +00003333static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003334 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003335 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003336 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003337 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003338 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003339 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003340
3341 // Add properties in this container.
3342 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3343 PEnd = Container->prop_end();
3344 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003345 ++P) {
3346 if (AddedProperties.insert(P->getIdentifier()))
3347 Results.MaybeAddResult(Result(*P, 0), CurContext);
3348 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003349
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003350 // Add nullary methods
3351 if (AllowNullaryMethods) {
3352 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003353 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003354 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3355 MEnd = Container->meth_end();
3356 M != MEnd; ++M) {
3357 if (M->getSelector().isUnarySelector())
3358 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3359 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003360 CodeCompletionBuilder Builder(Results.getAllocator(),
3361 Results.getCodeCompletionTUInfo());
Douglas Gregor8987b232011-09-27 23:30:47 +00003362 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003363 Builder.AddTypedTextChunk(
3364 Results.getAllocator().CopyString(Name->getName()));
3365
Douglas Gregorba103062012-03-27 23:34:16 +00003366 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
3367 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003368 CurContext);
3369 }
3370 }
3371 }
3372
3373
Douglas Gregor95ac6552009-11-18 01:29:26 +00003374 // Add properties in referenced protocols.
3375 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3376 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3377 PEnd = Protocol->protocol_end();
3378 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003379 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3380 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003381 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003382 if (AllowCategories) {
3383 // Look through categories.
3384 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3385 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003386 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3387 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003388 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003389
3390 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003391 for (ObjCInterfaceDecl::all_protocol_iterator
3392 I = IFace->all_referenced_protocol_begin(),
3393 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003394 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3395 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003396
3397 // Look in the superclass.
3398 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003399 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3400 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003401 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003402 } else if (const ObjCCategoryDecl *Category
3403 = dyn_cast<ObjCCategoryDecl>(Container)) {
3404 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003405 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3406 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003407 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003408 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3409 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003410 }
3411}
3412
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003413void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003414 SourceLocation OpLoc,
3415 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003416 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003417 return;
3418
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003419 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3420 if (ConvertedBase.isInvalid())
3421 return;
3422 Base = ConvertedBase.get();
3423
John McCall0a2c5e22010-08-25 06:19:51 +00003424 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003425
Douglas Gregor81b747b2009-09-17 21:32:03 +00003426 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003427
3428 if (IsArrow) {
3429 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3430 BaseType = Ptr->getPointeeType();
3431 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003432 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003433 else
3434 return;
3435 }
3436
Douglas Gregor3da626b2011-07-07 16:03:39 +00003437 enum CodeCompletionContext::Kind contextKind;
3438
3439 if (IsArrow) {
3440 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3441 }
3442 else {
3443 if (BaseType->isObjCObjectPointerType() ||
3444 BaseType->isObjCObjectOrInterfaceType()) {
3445 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3446 }
3447 else {
3448 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3449 }
3450 }
3451
Douglas Gregor218937c2011-02-01 19:23:04 +00003452 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003453 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003454 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003455 BaseType),
3456 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003457 Results.EnterNewScope();
3458 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003459 // Indicate that we are performing a member access, and the cv-qualifiers
3460 // for the base object type.
3461 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3462
Douglas Gregor95ac6552009-11-18 01:29:26 +00003463 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003464 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003465 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003466 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3467 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003468
David Blaikie4e4d0842012-03-11 07:00:24 +00003469 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003470 if (!Results.empty()) {
3471 // The "template" keyword can follow "->" or "." in the grammar.
3472 // However, we only want to suggest the template keyword if something
3473 // is dependent.
3474 bool IsDependent = BaseType->isDependentType();
3475 if (!IsDependent) {
3476 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3477 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3478 IsDependent = Ctx->isDependentContext();
3479 break;
3480 }
3481 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003482
Douglas Gregor95ac6552009-11-18 01:29:26 +00003483 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003484 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003485 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003486 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003487 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3488 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003489 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003490
3491 // Add property results based on our interface.
3492 const ObjCObjectPointerType *ObjCPtr
3493 = BaseType->getAsObjCInterfacePointerType();
3494 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003495 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3496 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003497 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003498
3499 // Add properties from the protocols in a qualified interface.
3500 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3501 E = ObjCPtr->qual_end();
3502 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003503 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3504 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003505 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003506 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003507 // Objective-C instance variable access.
3508 ObjCInterfaceDecl *Class = 0;
3509 if (const ObjCObjectPointerType *ObjCPtr
3510 = BaseType->getAs<ObjCObjectPointerType>())
3511 Class = ObjCPtr->getInterfaceDecl();
3512 else
John McCallc12c5bb2010-05-15 11:32:37 +00003513 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003514
3515 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003516 if (Class) {
3517 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3518 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003519 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3520 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003521 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003522 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003523
3524 // FIXME: How do we cope with isa?
3525
3526 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003527
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003528 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003529 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003530 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003531 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003532}
3533
Douglas Gregor374929f2009-09-18 15:37:17 +00003534void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3535 if (!CodeCompleter)
3536 return;
3537
John McCall0a2c5e22010-08-25 06:19:51 +00003538 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003539 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003540 enum CodeCompletionContext::Kind ContextKind
3541 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003542 switch ((DeclSpec::TST)TagSpec) {
3543 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003544 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003545 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003546 break;
3547
3548 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003549 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003550 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003551 break;
3552
3553 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003554 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003555 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003556 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003557 break;
3558
3559 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003560 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003561 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003562
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003563 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3564 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003565 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003566
3567 // First pass: look for tags.
3568 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003569 LookupVisibleDecls(S, LookupTagName, Consumer,
3570 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003571
Douglas Gregor8071e422010-08-15 06:18:01 +00003572 if (CodeCompleter->includeGlobals()) {
3573 // Second pass: look for nested name specifiers.
3574 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3575 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3576 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003577
Douglas Gregor52779fb2010-09-23 23:01:17 +00003578 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003579 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003580}
3581
Douglas Gregor1a480c42010-08-27 17:35:51 +00003582void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003583 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003584 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003585 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003586 Results.EnterNewScope();
3587 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3588 Results.AddResult("const");
3589 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3590 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003591 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003592 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3593 Results.AddResult("restrict");
3594 Results.ExitScope();
3595 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003596 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003597 Results.data(), Results.size());
3598}
3599
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003600void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003601 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003602 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003603
John McCall781472f2010-08-25 08:40:02 +00003604 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003605 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3606 if (!type->isEnumeralType()) {
3607 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003608 Data.IntegralConstantExpression = true;
3609 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003610 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003611 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003612
3613 // Code-complete the cases of a switch statement over an enumeration type
3614 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003615 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003616
3617 // Determine which enumerators we have already seen in the switch statement.
3618 // FIXME: Ideally, we would also be able to look *past* the code-completion
3619 // token, in case we are code-completing in the middle of the switch and not
3620 // at the end. However, we aren't able to do so at the moment.
3621 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003622 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003623 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3624 SC = SC->getNextSwitchCase()) {
3625 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3626 if (!Case)
3627 continue;
3628
3629 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3630 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3631 if (EnumConstantDecl *Enumerator
3632 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3633 // We look into the AST of the case statement to determine which
3634 // enumerator was named. Alternatively, we could compute the value of
3635 // the integral constant expression, then compare it against the
3636 // values of each enumerator. However, value-based approach would not
3637 // work as well with C++ templates where enumerators declared within a
3638 // template are type- and value-dependent.
3639 EnumeratorsSeen.insert(Enumerator);
3640
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003641 // If this is a qualified-id, keep track of the nested-name-specifier
3642 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003643 //
3644 // switch (TagD.getKind()) {
3645 // case TagDecl::TK_enum:
3646 // break;
3647 // case XXX
3648 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003649 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003650 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3651 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003652 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003653 }
3654 }
3655
David Blaikie4e4d0842012-03-11 07:00:24 +00003656 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003657 // If there are no prior enumerators in C++, check whether we have to
3658 // qualify the names of the enumerators that we suggest, because they
3659 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003660 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003661 }
3662
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003663 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003664 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003665 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003666 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003667 Results.EnterNewScope();
3668 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3669 EEnd = Enum->enumerator_end();
3670 E != EEnd; ++E) {
3671 if (EnumeratorsSeen.count(*E))
3672 continue;
3673
Douglas Gregor5c722c702011-02-18 23:30:37 +00003674 CodeCompletionResult R(*E, Qualifier);
3675 R.Priority = CCP_EnumInCase;
3676 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003677 }
3678 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003679
Douglas Gregor3da626b2011-07-07 16:03:39 +00003680 //We need to make sure we're setting the right context,
3681 //so only say we include macros if the code completer says we do
3682 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3683 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003684 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003685 kind = CodeCompletionContext::CCC_OtherWithMacros;
3686 }
3687
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003688 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003689 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003690 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003691}
3692
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003693namespace {
3694 struct IsBetterOverloadCandidate {
3695 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003696 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003697
3698 public:
John McCall5769d612010-02-08 23:07:23 +00003699 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3700 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003701
3702 bool
3703 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003704 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003705 }
3706 };
3707}
3708
Ahmed Charles13a140c2012-02-25 11:00:22 +00003709static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3710 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003711 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003712
3713 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003714 if (!Args[I])
3715 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003716
Douglas Gregord28dcd72010-05-30 06:10:08 +00003717 return false;
3718}
3719
Richard Trieuf81e5a92011-09-09 02:00:50 +00003720void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003721 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003722 if (!CodeCompleter)
3723 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003724
3725 // When we're code-completing for a call, we fall back to ordinary
3726 // name code-completion whenever we can't produce specific
3727 // results. We may want to revisit this strategy in the future,
3728 // e.g., by merging the two kinds of results.
3729
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003730 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003731
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003732 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003733 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3734 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003735 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003736 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003737 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003738
John McCall3b4294e2009-12-16 12:17:52 +00003739 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003740 SourceLocation Loc = Fn->getExprLoc();
3741 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003742
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003743 // FIXME: What if we're calling something that isn't a function declaration?
3744 // FIXME: What if we're calling a pseudo-destructor?
3745 // FIXME: What if we're calling a member function?
3746
Douglas Gregorc0265402010-01-21 15:46:19 +00003747 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003748 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003749
John McCall3b4294e2009-12-16 12:17:52 +00003750 Expr *NakedFn = Fn->IgnoreParenCasts();
3751 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003752 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003753 /*PartialOverloading=*/ true);
3754 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3755 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003756 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003757 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003758 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003759 Results.push_back(ResultCandidate(FDecl));
3760 else
John McCall86820f52010-01-26 01:37:31 +00003761 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003762 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3763 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003764 }
John McCall3b4294e2009-12-16 12:17:52 +00003765 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003766
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003767 QualType ParamType;
3768
Douglas Gregorc0265402010-01-21 15:46:19 +00003769 if (!CandidateSet.empty()) {
3770 // Sort the overload candidate set by placing the best overloads first.
3771 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003772 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003773
Douglas Gregorc0265402010-01-21 15:46:19 +00003774 // Add the remaining viable overload candidates as code-completion reslults.
3775 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3776 CandEnd = CandidateSet.end();
3777 Cand != CandEnd; ++Cand) {
3778 if (Cand->Viable)
3779 Results.push_back(ResultCandidate(Cand->Function));
3780 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003781
3782 // From the viable candidates, try to determine the type of this parameter.
3783 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3784 if (const FunctionType *FType = Results[I].getFunctionType())
3785 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003786 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003787 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003788 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003789 else if (!Context.hasSameUnqualifiedType(
3790 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003791 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003792 ParamType = QualType();
3793 break;
3794 }
3795 }
3796 }
3797 } else {
3798 // Try to determine the parameter type from the type of the expression
3799 // being called.
3800 QualType FunctionType = Fn->getType();
3801 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3802 FunctionType = Ptr->getPointeeType();
3803 else if (const BlockPointerType *BlockPtr
3804 = FunctionType->getAs<BlockPointerType>())
3805 FunctionType = BlockPtr->getPointeeType();
3806 else if (const MemberPointerType *MemPtr
3807 = FunctionType->getAs<MemberPointerType>())
3808 FunctionType = MemPtr->getPointeeType();
3809
3810 if (const FunctionProtoType *Proto
3811 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003812 if (Args.size() < Proto->getNumArgs())
3813 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003814 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003815 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003816
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003817 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003818 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003819 else
3820 CodeCompleteExpression(S, ParamType);
3821
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003822 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003823 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003824 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003825}
3826
John McCalld226f652010-08-21 09:40:31 +00003827void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3828 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003829 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003830 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003831 return;
3832 }
3833
3834 CodeCompleteExpression(S, VD->getType());
3835}
3836
3837void Sema::CodeCompleteReturn(Scope *S) {
3838 QualType ResultType;
3839 if (isa<BlockDecl>(CurContext)) {
3840 if (BlockScopeInfo *BSI = getCurBlock())
3841 ResultType = BSI->ReturnType;
3842 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3843 ResultType = Function->getResultType();
3844 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3845 ResultType = Method->getResultType();
3846
3847 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003848 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003849 else
3850 CodeCompleteExpression(S, ResultType);
3851}
3852
Douglas Gregord2d8be62011-07-30 08:36:53 +00003853void Sema::CodeCompleteAfterIf(Scope *S) {
3854 typedef CodeCompletionResult Result;
3855 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003856 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003857 mapCodeCompletionContext(*this, PCC_Statement));
3858 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3859 Results.EnterNewScope();
3860
3861 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3862 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3863 CodeCompleter->includeGlobals());
3864
3865 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3866
3867 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003868 CodeCompletionBuilder Builder(Results.getAllocator(),
3869 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003870 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003871 if (Results.includeCodePatterns()) {
3872 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3873 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3874 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3875 Builder.AddPlaceholderChunk("statements");
3876 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3877 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3878 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003879 Results.AddResult(Builder.TakeString());
3880
3881 // "else if" block
3882 Builder.AddTypedTextChunk("else");
3883 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3884 Builder.AddTextChunk("if");
3885 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3886 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003887 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003888 Builder.AddPlaceholderChunk("condition");
3889 else
3890 Builder.AddPlaceholderChunk("expression");
3891 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003892 if (Results.includeCodePatterns()) {
3893 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3894 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3895 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3896 Builder.AddPlaceholderChunk("statements");
3897 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3898 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3899 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003900 Results.AddResult(Builder.TakeString());
3901
3902 Results.ExitScope();
3903
3904 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003905 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003906
3907 if (CodeCompleter->includeMacros())
3908 AddMacroResults(PP, Results);
3909
3910 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3911 Results.data(),Results.size());
3912}
3913
Richard Trieuf81e5a92011-09-09 02:00:50 +00003914void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003915 if (LHS)
3916 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3917 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003918 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003919}
3920
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003921void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003922 bool EnteringContext) {
3923 if (!SS.getScopeRep() || !CodeCompleter)
3924 return;
3925
Douglas Gregor86d9a522009-09-21 16:56:56 +00003926 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3927 if (!Ctx)
3928 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003929
3930 // Try to instantiate any non-dependent declaration contexts before
3931 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003932 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003933 return;
3934
Douglas Gregor218937c2011-02-01 19:23:04 +00003935 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003936 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003937 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003938 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003939
Douglas Gregor86d9a522009-09-21 16:56:56 +00003940 // The "template" keyword can follow "::" in the grammar, but only
3941 // put it into the grammar if the nested-name-specifier is dependent.
3942 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3943 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003944 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003945
3946 // Add calls to overridden virtual functions, if there are any.
3947 //
3948 // FIXME: This isn't wonderful, because we don't know whether we're actually
3949 // in a context that permits expressions. This is a general issue with
3950 // qualified-id completions.
3951 if (!EnteringContext)
3952 MaybeAddOverrideCalls(*this, Ctx, Results);
3953 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003954
Douglas Gregorf6961522010-08-27 21:18:54 +00003955 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3956 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3957
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003958 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003959 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003960 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003961}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003962
3963void Sema::CodeCompleteUsing(Scope *S) {
3964 if (!CodeCompleter)
3965 return;
3966
Douglas Gregor218937c2011-02-01 19:23:04 +00003967 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003968 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003969 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3970 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003971 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003972
3973 // If we aren't in class scope, we could see the "namespace" keyword.
3974 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003975 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003976
3977 // After "using", we can see anything that would start a
3978 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003979 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003980 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3981 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003982 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003983
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003984 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003985 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003986 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003987}
3988
3989void Sema::CodeCompleteUsingDirective(Scope *S) {
3990 if (!CodeCompleter)
3991 return;
3992
Douglas Gregor86d9a522009-09-21 16:56:56 +00003993 // After "using namespace", we expect to see a namespace name or namespace
3994 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003995 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003996 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003997 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003998 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003999 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004000 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004001 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4002 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004003 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004004 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004005 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004006 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004007}
4008
4009void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4010 if (!CodeCompleter)
4011 return;
4012
Douglas Gregor86d9a522009-09-21 16:56:56 +00004013 DeclContext *Ctx = (DeclContext *)S->getEntity();
4014 if (!S->getParent())
4015 Ctx = Context.getTranslationUnitDecl();
4016
Douglas Gregor52779fb2010-09-23 23:01:17 +00004017 bool SuppressedGlobalResults
4018 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4019
Douglas Gregor218937c2011-02-01 19:23:04 +00004020 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004021 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004022 SuppressedGlobalResults
4023 ? CodeCompletionContext::CCC_Namespace
4024 : CodeCompletionContext::CCC_Other,
4025 &ResultBuilder::IsNamespace);
4026
4027 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004028 // We only want to see those namespaces that have already been defined
4029 // within this scope, because its likely that the user is creating an
4030 // extended namespace declaration. Keep track of the most recent
4031 // definition of each namespace.
4032 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4033 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4034 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4035 NS != NSEnd; ++NS)
4036 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4037
4038 // Add the most recent definition (or extended definition) of each
4039 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004040 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004041 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004042 NS = OrigToLatest.begin(),
4043 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004044 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004045 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004046 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004047 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004048 }
4049
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004050 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004051 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004052 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004053}
4054
4055void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4056 if (!CodeCompleter)
4057 return;
4058
Douglas Gregor86d9a522009-09-21 16:56:56 +00004059 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004060 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004061 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004062 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004063 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004064 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004065 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4066 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004067 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004068 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004069 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004070}
4071
Douglas Gregored8d3222009-09-18 20:05:18 +00004072void Sema::CodeCompleteOperatorName(Scope *S) {
4073 if (!CodeCompleter)
4074 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004075
John McCall0a2c5e22010-08-25 06:19:51 +00004076 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004077 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004078 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004079 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004080 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004081 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004082
Douglas Gregor86d9a522009-09-21 16:56:56 +00004083 // Add the names of overloadable operators.
4084#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4085 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004086 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004087#include "clang/Basic/OperatorKinds.def"
4088
4089 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004090 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004091 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004092 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4093 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004094
4095 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004096 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004097 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004098
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004099 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004100 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004101 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004102}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004103
Douglas Gregor0133f522010-08-28 00:00:50 +00004104void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004105 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004106 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004107 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004108 CXXConstructorDecl *Constructor
4109 = static_cast<CXXConstructorDecl *>(ConstructorD);
4110 if (!Constructor)
4111 return;
4112
Douglas Gregor218937c2011-02-01 19:23:04 +00004113 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004114 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004115 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004116 Results.EnterNewScope();
4117
4118 // Fill in any already-initialized fields or base classes.
4119 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4120 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4121 for (unsigned I = 0; I != NumInitializers; ++I) {
4122 if (Initializers[I]->isBaseInitializer())
4123 InitializedBases.insert(
4124 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4125 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004126 InitializedFields.insert(cast<FieldDecl>(
4127 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004128 }
4129
4130 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004131 CodeCompletionBuilder Builder(Results.getAllocator(),
4132 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004133 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004134 CXXRecordDecl *ClassDecl = Constructor->getParent();
4135 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4136 BaseEnd = ClassDecl->bases_end();
4137 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004138 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4139 SawLastInitializer
4140 = NumInitializers > 0 &&
4141 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4142 Context.hasSameUnqualifiedType(Base->getType(),
4143 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004144 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004145 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004146
Douglas Gregor218937c2011-02-01 19:23:04 +00004147 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004148 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004149 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004150 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4151 Builder.AddPlaceholderChunk("args");
4152 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4153 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004154 SawLastInitializer? CCP_NextInitializer
4155 : CCP_MemberDeclaration));
4156 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004157 }
4158
4159 // Add completions for virtual base classes.
4160 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4161 BaseEnd = ClassDecl->vbases_end();
4162 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004163 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4164 SawLastInitializer
4165 = NumInitializers > 0 &&
4166 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4167 Context.hasSameUnqualifiedType(Base->getType(),
4168 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004169 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004170 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004171
Douglas Gregor218937c2011-02-01 19:23:04 +00004172 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004173 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004174 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004175 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4176 Builder.AddPlaceholderChunk("args");
4177 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4178 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004179 SawLastInitializer? CCP_NextInitializer
4180 : CCP_MemberDeclaration));
4181 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004182 }
4183
4184 // Add completions for members.
4185 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4186 FieldEnd = ClassDecl->field_end();
4187 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004188 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4189 SawLastInitializer
4190 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004191 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4192 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004193 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004194 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004195
4196 if (!Field->getDeclName())
4197 continue;
4198
Douglas Gregordae68752011-02-01 22:57:45 +00004199 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004200 Field->getIdentifier()->getName()));
4201 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4202 Builder.AddPlaceholderChunk("args");
4203 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4204 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004205 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004206 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004207 CXCursor_MemberRef,
4208 CXAvailability_Available,
4209 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004210 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004211 }
4212 Results.ExitScope();
4213
Douglas Gregor52779fb2010-09-23 23:01:17 +00004214 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004215 Results.data(), Results.size());
4216}
4217
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004218/// \brief Determine whether this scope denotes a namespace.
4219static bool isNamespaceScope(Scope *S) {
4220 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4221 if (!DC)
4222 return false;
4223
4224 return DC->isFileContext();
4225}
4226
4227void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4228 bool AfterAmpersand) {
4229 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004230 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004231 CodeCompletionContext::CCC_Other);
4232 Results.EnterNewScope();
4233
4234 // Note what has already been captured.
4235 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4236 bool IncludedThis = false;
4237 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4238 CEnd = Intro.Captures.end();
4239 C != CEnd; ++C) {
4240 if (C->Kind == LCK_This) {
4241 IncludedThis = true;
4242 continue;
4243 }
4244
4245 Known.insert(C->Id);
4246 }
4247
4248 // Look for other capturable variables.
4249 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4250 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4251 D != DEnd; ++D) {
4252 VarDecl *Var = dyn_cast<VarDecl>(*D);
4253 if (!Var ||
4254 !Var->hasLocalStorage() ||
4255 Var->hasAttr<BlocksAttr>())
4256 continue;
4257
4258 if (Known.insert(Var->getIdentifier()))
4259 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4260 }
4261 }
4262
4263 // Add 'this', if it would be valid.
4264 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4265 addThisCompletion(*this, Results);
4266
4267 Results.ExitScope();
4268
4269 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4270 Results.data(), Results.size());
4271}
4272
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004273// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4274// true or false.
4275#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00004276static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004277 ResultBuilder &Results,
4278 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004279 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004280 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004281 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004282
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004283 CodeCompletionBuilder Builder(Results.getAllocator(),
4284 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004285 if (LangOpts.ObjC2) {
4286 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00004287 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4288 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4289 Builder.AddPlaceholderChunk("property");
4290 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004291
4292 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00004293 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4294 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4295 Builder.AddPlaceholderChunk("property");
4296 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004297 }
4298}
4299
Douglas Gregorbca403c2010-01-13 23:51:12 +00004300static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004301 ResultBuilder &Results,
4302 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004303 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004304
4305 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00004306 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004307
4308 if (LangOpts.ObjC2) {
4309 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00004310 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004311
4312 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00004313 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004314
4315 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00004316 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004317 }
4318}
4319
Douglas Gregorbca403c2010-01-13 23:51:12 +00004320static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004321 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004322 CodeCompletionBuilder Builder(Results.getAllocator(),
4323 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004324
4325 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00004326 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4327 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4328 Builder.AddPlaceholderChunk("name");
4329 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004330
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004331 if (Results.includeCodePatterns()) {
4332 // @interface name
4333 // FIXME: Could introduce the whole pattern, including superclasses and
4334 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00004335 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4336 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4337 Builder.AddPlaceholderChunk("class");
4338 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004339
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004340 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00004341 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4342 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4343 Builder.AddPlaceholderChunk("protocol");
4344 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004345
4346 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00004347 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4348 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4349 Builder.AddPlaceholderChunk("class");
4350 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004351 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004352
4353 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00004354 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4355 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4356 Builder.AddPlaceholderChunk("alias");
4357 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4358 Builder.AddPlaceholderChunk("class");
4359 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004360}
4361
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004362void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004363 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004364 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004365 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004366 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004367 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004368 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004369 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004370 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004371 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004372 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004373 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004374 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004375 HandleCodeCompleteResults(this, CodeCompleter,
4376 CodeCompletionContext::CCC_Other,
4377 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004378}
4379
Douglas Gregorbca403c2010-01-13 23:51:12 +00004380static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004381 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004382 CodeCompletionBuilder Builder(Results.getAllocator(),
4383 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004384
4385 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004386 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004387 if (Results.getSema().getLangOpts().CPlusPlus ||
4388 Results.getSema().getLangOpts().ConstStrings)
Douglas Gregor8ca72082011-10-18 21:20:17 +00004389 EncodeType = " const char[]";
4390 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregor218937c2011-02-01 19:23:04 +00004391 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4392 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4393 Builder.AddPlaceholderChunk("type-name");
4394 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4395 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004396
4397 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004398 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregor218937c2011-02-01 19:23:04 +00004399 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4400 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4401 Builder.AddPlaceholderChunk("protocol-name");
4402 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4403 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004404
4405 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004406 Builder.AddResultTypeChunk("SEL");
Douglas Gregor218937c2011-02-01 19:23:04 +00004407 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4408 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4409 Builder.AddPlaceholderChunk("selector");
4410 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4411 Results.AddResult(Result(Builder.TakeString()));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004412
4413 // @[ objects, ... ]
4414 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[));
4415 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4416 Builder.AddPlaceholderChunk("objects, ...");
4417 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4418 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4419 Results.AddResult(Result(Builder.TakeString()));
4420
4421 // @{ key : object, ... }
4422 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{));
4423 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4424 Builder.AddPlaceholderChunk("key");
4425 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4426 Builder.AddChunk(CodeCompletionString::CK_Colon);
4427 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4428 Builder.AddPlaceholderChunk("object, ...");
4429 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4430 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4431 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004432}
4433
Douglas Gregorbca403c2010-01-13 23:51:12 +00004434static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004435 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004436 CodeCompletionBuilder Builder(Results.getAllocator(),
4437 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004438
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004439 if (Results.includeCodePatterns()) {
4440 // @try { statements } @catch ( declaration ) { statements } @finally
4441 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004442 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4443 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4444 Builder.AddPlaceholderChunk("statements");
4445 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4446 Builder.AddTextChunk("@catch");
4447 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4448 Builder.AddPlaceholderChunk("parameter");
4449 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4450 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4451 Builder.AddPlaceholderChunk("statements");
4452 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4453 Builder.AddTextChunk("@finally");
4454 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4455 Builder.AddPlaceholderChunk("statements");
4456 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4457 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004458 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004459
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004460 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00004461 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4462 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4463 Builder.AddPlaceholderChunk("expression");
4464 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004465
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004466 if (Results.includeCodePatterns()) {
4467 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00004468 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4469 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4470 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4471 Builder.AddPlaceholderChunk("expression");
4472 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4473 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4474 Builder.AddPlaceholderChunk("statements");
4475 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4476 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004477 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004478}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004479
Douglas Gregorbca403c2010-01-13 23:51:12 +00004480static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004481 ResultBuilder &Results,
4482 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004483 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00004484 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4485 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4486 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004487 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00004488 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004489}
4490
4491void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004492 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004493 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004494 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004495 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004496 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004497 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004498 HandleCodeCompleteResults(this, CodeCompleter,
4499 CodeCompletionContext::CCC_Other,
4500 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004501}
4502
4503void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004504 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004505 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004506 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004507 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004508 AddObjCStatementResults(Results, false);
4509 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004510 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004511 HandleCodeCompleteResults(this, CodeCompleter,
4512 CodeCompletionContext::CCC_Other,
4513 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004514}
4515
4516void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004517 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004518 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004519 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004520 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004521 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004522 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004523 HandleCodeCompleteResults(this, CodeCompleter,
4524 CodeCompletionContext::CCC_Other,
4525 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004526}
4527
Douglas Gregor988358f2009-11-19 00:14:45 +00004528/// \brief Determine whether the addition of the given flag to an Objective-C
4529/// property's attributes will cause a conflict.
4530static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4531 // Check if we've already added this flag.
4532 if (Attributes & NewFlag)
4533 return true;
4534
4535 Attributes |= NewFlag;
4536
4537 // Check for collisions with "readonly".
4538 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4539 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4540 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004541 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004542 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004543 ObjCDeclSpec::DQ_PR_retain |
4544 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004545 return true;
4546
John McCallf85e1932011-06-15 23:02:42 +00004547 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004548 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004549 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004550 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004551 ObjCDeclSpec::DQ_PR_retain|
4552 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004553 if (AssignCopyRetMask &&
4554 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004555 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004556 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004557 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4558 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004559 return true;
4560
4561 return false;
4562}
4563
Douglas Gregora93b1082009-11-18 23:08:07 +00004564void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004565 if (!CodeCompleter)
4566 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004567
Steve Naroffece8e712009-10-08 21:55:05 +00004568 unsigned Attributes = ODS.getPropertyAttributes();
4569
John McCall0a2c5e22010-08-25 06:19:51 +00004570 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004571 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004572 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004573 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004574 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004575 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004576 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004577 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004578 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004579 if (!ObjCPropertyFlagConflicts(Attributes,
4580 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4581 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004582 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004583 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004584 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004585 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004586 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4587 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004588 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004589 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004590 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004591 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004592 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4593 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004594 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004595 CodeCompletionBuilder Setter(Results.getAllocator(),
4596 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004597 Setter.AddTypedTextChunk("setter");
4598 Setter.AddTextChunk(" = ");
4599 Setter.AddPlaceholderChunk("method");
4600 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004601 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004602 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004603 CodeCompletionBuilder Getter(Results.getAllocator(),
4604 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004605 Getter.AddTypedTextChunk("getter");
4606 Getter.AddTextChunk(" = ");
4607 Getter.AddPlaceholderChunk("method");
4608 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004609 }
Steve Naroffece8e712009-10-08 21:55:05 +00004610 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004611 HandleCodeCompleteResults(this, CodeCompleter,
4612 CodeCompletionContext::CCC_Other,
4613 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004614}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004615
Douglas Gregor4ad96852009-11-19 07:41:15 +00004616/// \brief Descripts the kind of Objective-C method that we want to find
4617/// via code completion.
4618enum ObjCMethodKind {
4619 MK_Any, //< Any kind of method, provided it means other specified criteria.
4620 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4621 MK_OneArgSelector //< One-argument selector.
4622};
4623
Douglas Gregor458433d2010-08-26 15:07:07 +00004624static bool isAcceptableObjCSelector(Selector Sel,
4625 ObjCMethodKind WantKind,
4626 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004627 unsigned NumSelIdents,
4628 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004629 if (NumSelIdents > Sel.getNumArgs())
4630 return false;
4631
4632 switch (WantKind) {
4633 case MK_Any: break;
4634 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4635 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4636 }
4637
Douglas Gregorcf544262010-11-17 21:36:08 +00004638 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4639 return false;
4640
Douglas Gregor458433d2010-08-26 15:07:07 +00004641 for (unsigned I = 0; I != NumSelIdents; ++I)
4642 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4643 return false;
4644
4645 return true;
4646}
4647
Douglas Gregor4ad96852009-11-19 07:41:15 +00004648static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4649 ObjCMethodKind WantKind,
4650 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004651 unsigned NumSelIdents,
4652 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004653 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004654 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004655}
Douglas Gregord36adf52010-09-16 16:06:31 +00004656
4657namespace {
4658 /// \brief A set of selectors, which is used to avoid introducing multiple
4659 /// completions with the same selector into the result set.
4660 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4661}
4662
Douglas Gregor36ecb042009-11-17 23:22:23 +00004663/// \brief Add all of the Objective-C methods in the given Objective-C
4664/// container to the set of results.
4665///
4666/// The container will be a class, protocol, category, or implementation of
4667/// any of the above. This mether will recurse to include methods from
4668/// the superclasses of classes along with their categories, protocols, and
4669/// implementations.
4670///
4671/// \param Container the container in which we'll look to find methods.
4672///
4673/// \param WantInstance whether to add instance methods (only); if false, this
4674/// routine will add factory methods (only).
4675///
4676/// \param CurContext the context in which we're performing the lookup that
4677/// finds methods.
4678///
Douglas Gregorcf544262010-11-17 21:36:08 +00004679/// \param AllowSameLength Whether we allow a method to be added to the list
4680/// when it has the same number of parameters as we have selector identifiers.
4681///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004682/// \param Results the structure into which we'll add results.
4683static void AddObjCMethods(ObjCContainerDecl *Container,
4684 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004685 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004686 IdentifierInfo **SelIdents,
4687 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004688 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004689 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004690 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004691 ResultBuilder &Results,
4692 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004693 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004694 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4695 MEnd = Container->meth_end();
4696 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004697 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4698 // Check whether the selector identifiers we've been given are a
4699 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004700 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4701 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004702 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004703
Douglas Gregord36adf52010-09-16 16:06:31 +00004704 if (!Selectors.insert((*M)->getSelector()))
4705 continue;
4706
Douglas Gregord3c68542009-11-19 01:08:35 +00004707 Result R = Result(*M, 0);
4708 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004709 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004710 if (!InOriginalClass)
4711 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004712 Results.MaybeAddResult(R, CurContext);
4713 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004714 }
4715
Douglas Gregore396c7b2010-09-16 15:34:59 +00004716 // Visit the protocols of protocols.
4717 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004718 if (Protocol->hasDefinition()) {
4719 const ObjCList<ObjCProtocolDecl> &Protocols
4720 = Protocol->getReferencedProtocols();
4721 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4722 E = Protocols.end();
4723 I != E; ++I)
4724 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4725 NumSelIdents, CurContext, Selectors, AllowSameLength,
4726 Results, false);
4727 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004728 }
4729
Douglas Gregor36ecb042009-11-17 23:22:23 +00004730 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004731 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004732 return;
4733
4734 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004735 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4736 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004737 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004738 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004739 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004740
4741 // Add methods in categories.
4742 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4743 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004744 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004745 NumSelIdents, CurContext, Selectors, AllowSameLength,
4746 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004747
4748 // Add a categories protocol methods.
4749 const ObjCList<ObjCProtocolDecl> &Protocols
4750 = CatDecl->getReferencedProtocols();
4751 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4752 E = Protocols.end();
4753 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004754 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004755 NumSelIdents, CurContext, Selectors, AllowSameLength,
4756 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004757
4758 // Add methods in category implementations.
4759 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004760 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004761 NumSelIdents, CurContext, Selectors, AllowSameLength,
4762 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004763 }
4764
4765 // Add methods in superclass.
4766 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004767 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004768 SelIdents, NumSelIdents, CurContext, Selectors,
4769 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004770
4771 // Add methods in our implementation, if any.
4772 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004773 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004774 NumSelIdents, CurContext, Selectors, AllowSameLength,
4775 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004776}
4777
4778
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004779void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004780 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004781
4782 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004783 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004784 if (!Class) {
4785 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004786 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004787 Class = Category->getClassInterface();
4788
4789 if (!Class)
4790 return;
4791 }
4792
4793 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004794 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004795 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004796 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004797 Results.EnterNewScope();
4798
Douglas Gregord36adf52010-09-16 16:06:31 +00004799 VisitedSelectorSet Selectors;
4800 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004801 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004802 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004803 HandleCodeCompleteResults(this, CodeCompleter,
4804 CodeCompletionContext::CCC_Other,
4805 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004806}
4807
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004808void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004809 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004810
4811 // Try to find the interface where setters might live.
4812 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004813 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004814 if (!Class) {
4815 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004816 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004817 Class = Category->getClassInterface();
4818
4819 if (!Class)
4820 return;
4821 }
4822
4823 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004824 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004825 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004826 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004827 Results.EnterNewScope();
4828
Douglas Gregord36adf52010-09-16 16:06:31 +00004829 VisitedSelectorSet Selectors;
4830 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004831 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004832
4833 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004834 HandleCodeCompleteResults(this, CodeCompleter,
4835 CodeCompletionContext::CCC_Other,
4836 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004837}
4838
Douglas Gregorafc45782011-02-15 22:19:42 +00004839void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4840 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004841 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004842 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004843 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004844 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004845 Results.EnterNewScope();
4846
4847 // Add context-sensitive, Objective-C parameter-passing keywords.
4848 bool AddedInOut = false;
4849 if ((DS.getObjCDeclQualifier() &
4850 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4851 Results.AddResult("in");
4852 Results.AddResult("inout");
4853 AddedInOut = true;
4854 }
4855 if ((DS.getObjCDeclQualifier() &
4856 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4857 Results.AddResult("out");
4858 if (!AddedInOut)
4859 Results.AddResult("inout");
4860 }
4861 if ((DS.getObjCDeclQualifier() &
4862 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4863 ObjCDeclSpec::DQ_Oneway)) == 0) {
4864 Results.AddResult("bycopy");
4865 Results.AddResult("byref");
4866 Results.AddResult("oneway");
4867 }
4868
Douglas Gregorafc45782011-02-15 22:19:42 +00004869 // If we're completing the return type of an Objective-C method and the
4870 // identifier IBAction refers to a macro, provide a completion item for
4871 // an action, e.g.,
4872 // IBAction)<#selector#>:(id)sender
4873 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4874 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004875 CodeCompletionBuilder Builder(Results.getAllocator(),
4876 Results.getCodeCompletionTUInfo(),
4877 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004878 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004879 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004880 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004881 Builder.AddChunk(CodeCompletionString::CK_Colon);
4882 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004883 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004884 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004885 Builder.AddTextChunk("sender");
4886 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4887 }
4888
Douglas Gregord32b0222010-08-24 01:06:58 +00004889 // Add various builtin type names and specifiers.
4890 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4891 Results.ExitScope();
4892
4893 // Add the various type names
4894 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4895 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4896 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4897 CodeCompleter->includeGlobals());
4898
4899 if (CodeCompleter->includeMacros())
4900 AddMacroResults(PP, Results);
4901
4902 HandleCodeCompleteResults(this, CodeCompleter,
4903 CodeCompletionContext::CCC_Type,
4904 Results.data(), Results.size());
4905}
4906
Douglas Gregor22f56992010-04-06 19:22:33 +00004907/// \brief When we have an expression with type "id", we may assume
4908/// that it has some more-specific class type based on knowledge of
4909/// common uses of Objective-C. This routine returns that class type,
4910/// or NULL if no better result could be determined.
4911static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004912 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004913 if (!Msg)
4914 return 0;
4915
4916 Selector Sel = Msg->getSelector();
4917 if (Sel.isNull())
4918 return 0;
4919
4920 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4921 if (!Id)
4922 return 0;
4923
4924 ObjCMethodDecl *Method = Msg->getMethodDecl();
4925 if (!Method)
4926 return 0;
4927
4928 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004929 ObjCInterfaceDecl *IFace = 0;
4930 switch (Msg->getReceiverKind()) {
4931 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004932 if (const ObjCObjectType *ObjType
4933 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4934 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004935 break;
4936
4937 case ObjCMessageExpr::Instance: {
4938 QualType T = Msg->getInstanceReceiver()->getType();
4939 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4940 IFace = Ptr->getInterfaceDecl();
4941 break;
4942 }
4943
4944 case ObjCMessageExpr::SuperInstance:
4945 case ObjCMessageExpr::SuperClass:
4946 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004947 }
4948
4949 if (!IFace)
4950 return 0;
4951
4952 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4953 if (Method->isInstanceMethod())
4954 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4955 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00004956 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00004957 .Case("autorelease", IFace)
4958 .Case("copy", IFace)
4959 .Case("copyWithZone", IFace)
4960 .Case("mutableCopy", IFace)
4961 .Case("mutableCopyWithZone", IFace)
4962 .Case("awakeFromCoder", IFace)
4963 .Case("replacementObjectFromCoder", IFace)
4964 .Case("class", IFace)
4965 .Case("classForCoder", IFace)
4966 .Case("superclass", Super)
4967 .Default(0);
4968
4969 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4970 .Case("new", IFace)
4971 .Case("alloc", IFace)
4972 .Case("allocWithZone", IFace)
4973 .Case("class", IFace)
4974 .Case("superclass", Super)
4975 .Default(0);
4976}
4977
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004978// Add a special completion for a message send to "super", which fills in the
4979// most likely case of forwarding all of our arguments to the superclass
4980// function.
4981///
4982/// \param S The semantic analysis object.
4983///
4984/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4985/// the "super" keyword. Otherwise, we just need to provide the arguments.
4986///
4987/// \param SelIdents The identifiers in the selector that have already been
4988/// provided as arguments for a send to "super".
4989///
4990/// \param NumSelIdents The number of identifiers in \p SelIdents.
4991///
4992/// \param Results The set of results to augment.
4993///
4994/// \returns the Objective-C method declaration that would be invoked by
4995/// this "super" completion. If NULL, no completion was added.
4996static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4997 IdentifierInfo **SelIdents,
4998 unsigned NumSelIdents,
4999 ResultBuilder &Results) {
5000 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5001 if (!CurMethod)
5002 return 0;
5003
5004 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5005 if (!Class)
5006 return 0;
5007
5008 // Try to find a superclass method with the same selector.
5009 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005010 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5011 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005012 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5013 CurMethod->isInstanceMethod());
5014
Douglas Gregor78bcd912011-02-16 00:51:18 +00005015 // Check in categories or class extensions.
5016 if (!SuperMethod) {
5017 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5018 Category = Category->getNextClassCategory())
5019 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
5020 CurMethod->isInstanceMethod())))
5021 break;
5022 }
5023 }
5024
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005025 if (!SuperMethod)
5026 return 0;
5027
5028 // Check whether the superclass method has the same signature.
5029 if (CurMethod->param_size() != SuperMethod->param_size() ||
5030 CurMethod->isVariadic() != SuperMethod->isVariadic())
5031 return 0;
5032
5033 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5034 CurPEnd = CurMethod->param_end(),
5035 SuperP = SuperMethod->param_begin();
5036 CurP != CurPEnd; ++CurP, ++SuperP) {
5037 // Make sure the parameter types are compatible.
5038 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5039 (*SuperP)->getType()))
5040 return 0;
5041
5042 // Make sure we have a parameter name to forward!
5043 if (!(*CurP)->getIdentifier())
5044 return 0;
5045 }
5046
5047 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005048 CodeCompletionBuilder Builder(Results.getAllocator(),
5049 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005050
5051 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005052 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5053 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005054
5055 // If we need the "super" keyword, add it (plus some spacing).
5056 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005057 Builder.AddTypedTextChunk("super");
5058 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005059 }
5060
5061 Selector Sel = CurMethod->getSelector();
5062 if (Sel.isUnarySelector()) {
5063 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005064 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005065 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005066 else
Douglas Gregordae68752011-02-01 22:57:45 +00005067 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005068 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005069 } else {
5070 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5071 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5072 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005073 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005074
5075 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005076 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005077 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005078 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005079 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005080 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005081 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005082 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005083 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005084 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005085 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005086 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005087 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005088 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005089 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005090 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005091 }
5092 }
5093 }
5094
Douglas Gregorba103062012-03-27 23:34:16 +00005095 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5096 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005097 return SuperMethod;
5098}
5099
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005100void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005101 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005102 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005103 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005104 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005105 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005106 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5107 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005108
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005109 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5110 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005111 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5112 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005113
5114 // If we are in an Objective-C method inside a class that has a superclass,
5115 // add "super" as an option.
5116 if (ObjCMethodDecl *Method = getCurMethodDecl())
5117 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005118 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005119 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005120
5121 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5122 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005123
David Blaikie4e4d0842012-03-11 07:00:24 +00005124 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005125 addThisCompletion(*this, Results);
5126
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005127 Results.ExitScope();
5128
5129 if (CodeCompleter->includeMacros())
5130 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005131 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005132 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005133
5134}
5135
Douglas Gregor2725ca82010-04-21 19:57:20 +00005136void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5137 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005138 unsigned NumSelIdents,
5139 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005140 ObjCInterfaceDecl *CDecl = 0;
5141 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5142 // Figure out which interface we're in.
5143 CDecl = CurMethod->getClassInterface();
5144 if (!CDecl)
5145 return;
5146
5147 // Find the superclass of this class.
5148 CDecl = CDecl->getSuperClass();
5149 if (!CDecl)
5150 return;
5151
5152 if (CurMethod->isInstanceMethod()) {
5153 // We are inside an instance method, which means that the message
5154 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005155 // current object.
5156 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005157 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005158 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005159 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005160 }
5161
5162 // Fall through to send to the superclass in CDecl.
5163 } else {
5164 // "super" may be the name of a type or variable. Figure out which
5165 // it is.
5166 IdentifierInfo *Super = &Context.Idents.get("super");
5167 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5168 LookupOrdinaryName);
5169 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5170 // "super" names an interface. Use it.
5171 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005172 if (const ObjCObjectType *Iface
5173 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5174 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005175 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5176 // "super" names an unresolved type; we can't be more specific.
5177 } else {
5178 // Assume that "super" names some kind of value and parse that way.
5179 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005180 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005181 UnqualifiedId id;
5182 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005183 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5184 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005185 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005186 SelIdents, NumSelIdents,
5187 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005188 }
5189
5190 // Fall through
5191 }
5192
John McCallb3d87482010-08-24 05:47:05 +00005193 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005194 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005195 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005196 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005197 NumSelIdents, AtArgumentExpression,
5198 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005199}
5200
Douglas Gregorb9d77572010-09-21 00:03:25 +00005201/// \brief Given a set of code-completion results for the argument of a message
5202/// send, determine the preferred type (if any) for that argument expression.
5203static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5204 unsigned NumSelIdents) {
5205 typedef CodeCompletionResult Result;
5206 ASTContext &Context = Results.getSema().Context;
5207
5208 QualType PreferredType;
5209 unsigned BestPriority = CCP_Unlikely * 2;
5210 Result *ResultsData = Results.data();
5211 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5212 Result &R = ResultsData[I];
5213 if (R.Kind == Result::RK_Declaration &&
5214 isa<ObjCMethodDecl>(R.Declaration)) {
5215 if (R.Priority <= BestPriority) {
5216 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5217 if (NumSelIdents <= Method->param_size()) {
5218 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5219 ->getType();
5220 if (R.Priority < BestPriority || PreferredType.isNull()) {
5221 BestPriority = R.Priority;
5222 PreferredType = MyPreferredType;
5223 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5224 MyPreferredType)) {
5225 PreferredType = QualType();
5226 }
5227 }
5228 }
5229 }
5230 }
5231
5232 return PreferredType;
5233}
5234
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005235static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5236 ParsedType Receiver,
5237 IdentifierInfo **SelIdents,
5238 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005239 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005240 bool IsSuper,
5241 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005242 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005243 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005244
Douglas Gregor24a069f2009-11-17 17:59:40 +00005245 // If the given name refers to an interface type, retrieve the
5246 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005247 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005248 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005249 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005250 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5251 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005252 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005253
Douglas Gregor36ecb042009-11-17 23:22:23 +00005254 // Add all of the factory methods in this Objective-C class, its protocols,
5255 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005256 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005257
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005258 // If this is a send-to-super, try to add the special "super" send
5259 // completion.
5260 if (IsSuper) {
5261 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005262 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5263 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005264 Results.Ignore(SuperMethod);
5265 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005266
Douglas Gregor265f7492010-08-27 15:29:55 +00005267 // If we're inside an Objective-C method definition, prefer its selector to
5268 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005269 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005270 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005271
Douglas Gregord36adf52010-09-16 16:06:31 +00005272 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005273 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005274 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005275 SemaRef.CurContext, Selectors, AtArgumentExpression,
5276 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005277 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005278 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005279
Douglas Gregor719770d2010-04-06 17:30:22 +00005280 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005281 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005282 if (SemaRef.ExternalSource) {
5283 for (uint32_t I = 0,
5284 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005285 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005286 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5287 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005288 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005289
5290 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005291 }
5292 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005293
5294 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5295 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005296 M != MEnd; ++M) {
5297 for (ObjCMethodList *MethList = &M->second.second;
5298 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005299 MethList = MethList->Next) {
5300 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5301 NumSelIdents))
5302 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005303
Douglas Gregor13438f92010-04-06 16:40:00 +00005304 Result R(MethList->Method, 0);
5305 R.StartParameter = NumSelIdents;
5306 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005307 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005308 }
5309 }
5310 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005311
5312 Results.ExitScope();
5313}
Douglas Gregor13438f92010-04-06 16:40:00 +00005314
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005315void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5316 IdentifierInfo **SelIdents,
5317 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005318 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005319 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005320
5321 QualType T = this->GetTypeFromParser(Receiver);
5322
Douglas Gregor218937c2011-02-01 19:23:04 +00005323 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005324 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005325 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005326 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005327
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005328 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5329 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005330
5331 // If we're actually at the argument expression (rather than prior to the
5332 // selector), we're actually performing code completion for an expression.
5333 // Determine whether we have a single, best method. If so, we can
5334 // code-complete the expression using the corresponding parameter type as
5335 // our preferred type, improving completion results.
5336 if (AtArgumentExpression) {
5337 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005338 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005339 if (PreferredType.isNull())
5340 CodeCompleteOrdinaryName(S, PCC_Expression);
5341 else
5342 CodeCompleteExpression(S, PreferredType);
5343 return;
5344 }
5345
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005346 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005347 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005348 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005349}
5350
Richard Trieuf81e5a92011-09-09 02:00:50 +00005351void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005352 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005353 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005354 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005355 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005356 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005357
5358 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005359
Douglas Gregor36ecb042009-11-17 23:22:23 +00005360 // If necessary, apply function/array conversion to the receiver.
5361 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005362 if (RecExpr) {
5363 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5364 if (Conv.isInvalid()) // conversion failed. bail.
5365 return;
5366 RecExpr = Conv.take();
5367 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005368 QualType ReceiverType = RecExpr? RecExpr->getType()
5369 : Super? Context.getObjCObjectPointerType(
5370 Context.getObjCInterfaceType(Super))
5371 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005372
Douglas Gregorda892642010-11-08 21:12:30 +00005373 // If we're messaging an expression with type "id" or "Class", check
5374 // whether we know something special about the receiver that allows
5375 // us to assume a more-specific receiver type.
5376 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5377 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5378 if (ReceiverType->isObjCClassType())
5379 return CodeCompleteObjCClassMessage(S,
5380 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5381 SelIdents, NumSelIdents,
5382 AtArgumentExpression, Super);
5383
5384 ReceiverType = Context.getObjCObjectPointerType(
5385 Context.getObjCInterfaceType(IFace));
5386 }
5387
Douglas Gregor36ecb042009-11-17 23:22:23 +00005388 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005389 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005390 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005391 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005392 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005393
Douglas Gregor36ecb042009-11-17 23:22:23 +00005394 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005395
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005396 // If this is a send-to-super, try to add the special "super" send
5397 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005398 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005399 if (ObjCMethodDecl *SuperMethod
5400 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5401 Results))
5402 Results.Ignore(SuperMethod);
5403 }
5404
Douglas Gregor265f7492010-08-27 15:29:55 +00005405 // If we're inside an Objective-C method definition, prefer its selector to
5406 // others.
5407 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5408 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005409
Douglas Gregord36adf52010-09-16 16:06:31 +00005410 // Keep track of the selectors we've already added.
5411 VisitedSelectorSet Selectors;
5412
Douglas Gregorf74a4192009-11-18 00:06:18 +00005413 // Handle messages to Class. This really isn't a message to an instance
5414 // method, so we treat it the same way we would treat a message send to a
5415 // class method.
5416 if (ReceiverType->isObjCClassType() ||
5417 ReceiverType->isObjCQualifiedClassType()) {
5418 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5419 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005420 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005421 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005422 }
5423 }
5424 // Handle messages to a qualified ID ("id<foo>").
5425 else if (const ObjCObjectPointerType *QualID
5426 = ReceiverType->getAsObjCQualifiedIdType()) {
5427 // Search protocols for instance methods.
5428 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5429 E = QualID->qual_end();
5430 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005431 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005432 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005433 }
5434 // Handle messages to a pointer to interface type.
5435 else if (const ObjCObjectPointerType *IFacePtr
5436 = ReceiverType->getAsObjCInterfacePointerType()) {
5437 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005438 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005439 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5440 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005441
5442 // Search protocols for instance methods.
5443 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5444 E = IFacePtr->qual_end();
5445 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005446 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005447 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005448 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005449 // Handle messages to "id".
5450 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005451 // We're messaging "id", so provide all instance methods we know
5452 // about as code-completion results.
5453
5454 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005455 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005456 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005457 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5458 I != N; ++I) {
5459 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005460 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005461 continue;
5462
Sebastian Redldb9d2142010-08-02 23:18:59 +00005463 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005464 }
5465 }
5466
Sebastian Redldb9d2142010-08-02 23:18:59 +00005467 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5468 MEnd = MethodPool.end();
5469 M != MEnd; ++M) {
5470 for (ObjCMethodList *MethList = &M->second.first;
5471 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005472 MethList = MethList->Next) {
5473 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5474 NumSelIdents))
5475 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005476
5477 if (!Selectors.insert(MethList->Method->getSelector()))
5478 continue;
5479
Douglas Gregor13438f92010-04-06 16:40:00 +00005480 Result R(MethList->Method, 0);
5481 R.StartParameter = NumSelIdents;
5482 R.AllParametersAreInformative = false;
5483 Results.MaybeAddResult(R, CurContext);
5484 }
5485 }
5486 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005487 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005488
5489
5490 // If we're actually at the argument expression (rather than prior to the
5491 // selector), we're actually performing code completion for an expression.
5492 // Determine whether we have a single, best method. If so, we can
5493 // code-complete the expression using the corresponding parameter type as
5494 // our preferred type, improving completion results.
5495 if (AtArgumentExpression) {
5496 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5497 NumSelIdents);
5498 if (PreferredType.isNull())
5499 CodeCompleteOrdinaryName(S, PCC_Expression);
5500 else
5501 CodeCompleteExpression(S, PreferredType);
5502 return;
5503 }
5504
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005505 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005506 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005507 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005508}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005509
Douglas Gregorfb629412010-08-23 21:17:50 +00005510void Sema::CodeCompleteObjCForCollection(Scope *S,
5511 DeclGroupPtrTy IterationVar) {
5512 CodeCompleteExpressionData Data;
5513 Data.ObjCCollection = true;
5514
5515 if (IterationVar.getAsOpaquePtr()) {
5516 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5517 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5518 if (*I)
5519 Data.IgnoreDecls.push_back(*I);
5520 }
5521 }
5522
5523 CodeCompleteExpression(S, Data);
5524}
5525
Douglas Gregor458433d2010-08-26 15:07:07 +00005526void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5527 unsigned NumSelIdents) {
5528 // If we have an external source, load the entire class method
5529 // pool from the AST file.
5530 if (ExternalSource) {
5531 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5532 I != N; ++I) {
5533 Selector Sel = ExternalSource->GetExternalSelector(I);
5534 if (Sel.isNull() || MethodPool.count(Sel))
5535 continue;
5536
5537 ReadMethodPool(Sel);
5538 }
5539 }
5540
Douglas Gregor218937c2011-02-01 19:23:04 +00005541 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005542 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005543 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005544 Results.EnterNewScope();
5545 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5546 MEnd = MethodPool.end();
5547 M != MEnd; ++M) {
5548
5549 Selector Sel = M->first;
5550 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5551 continue;
5552
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005553 CodeCompletionBuilder Builder(Results.getAllocator(),
5554 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005555 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005556 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005557 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005558 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005559 continue;
5560 }
5561
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005562 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005563 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005564 if (I == NumSelIdents) {
5565 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005566 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005567 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005568 Accumulator.clear();
5569 }
5570 }
5571
Benjamin Kramera0651c52011-07-26 16:59:25 +00005572 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005573 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005574 }
Douglas Gregordae68752011-02-01 22:57:45 +00005575 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005576 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005577 }
5578 Results.ExitScope();
5579
5580 HandleCodeCompleteResults(this, CodeCompleter,
5581 CodeCompletionContext::CCC_SelectorName,
5582 Results.data(), Results.size());
5583}
5584
Douglas Gregor55385fe2009-11-18 04:19:12 +00005585/// \brief Add all of the protocol declarations that we find in the given
5586/// (translation unit) context.
5587static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005588 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005589 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005590 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005591
5592 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5593 DEnd = Ctx->decls_end();
5594 D != DEnd; ++D) {
5595 // Record any protocols we find.
5596 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005597 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005598 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005599 }
5600}
5601
5602void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5603 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005604 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005605 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005606 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005607
Douglas Gregor70c23352010-12-09 21:44:02 +00005608 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5609 Results.EnterNewScope();
5610
5611 // Tell the result set to ignore all of the protocols we have
5612 // already seen.
5613 // FIXME: This doesn't work when caching code-completion results.
5614 for (unsigned I = 0; I != NumProtocols; ++I)
5615 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5616 Protocols[I].second))
5617 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005618
Douglas Gregor70c23352010-12-09 21:44:02 +00005619 // Add all protocols.
5620 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5621 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005622
Douglas Gregor70c23352010-12-09 21:44:02 +00005623 Results.ExitScope();
5624 }
5625
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005626 HandleCodeCompleteResults(this, CodeCompleter,
5627 CodeCompletionContext::CCC_ObjCProtocolName,
5628 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005629}
5630
5631void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005632 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005633 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005634 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005635
Douglas Gregor70c23352010-12-09 21:44:02 +00005636 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5637 Results.EnterNewScope();
5638
5639 // Add all protocols.
5640 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5641 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005642
Douglas Gregor70c23352010-12-09 21:44:02 +00005643 Results.ExitScope();
5644 }
5645
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005646 HandleCodeCompleteResults(this, CodeCompleter,
5647 CodeCompletionContext::CCC_ObjCProtocolName,
5648 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005649}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005650
5651/// \brief Add all of the Objective-C interface declarations that we find in
5652/// the given (translation unit) context.
5653static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5654 bool OnlyForwardDeclarations,
5655 bool OnlyUnimplemented,
5656 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005657 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005658
5659 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5660 DEnd = Ctx->decls_end();
5661 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005662 // Record any interfaces we find.
5663 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005664 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005665 (!OnlyUnimplemented || !Class->getImplementation()))
5666 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005667 }
5668}
5669
5670void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005671 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005672 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005673 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005674 Results.EnterNewScope();
5675
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005676 if (CodeCompleter->includeGlobals()) {
5677 // Add all classes.
5678 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5679 false, Results);
5680 }
5681
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005682 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005683
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005684 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005685 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005686 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005687}
5688
Douglas Gregorc83c6872010-04-15 22:33:43 +00005689void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5690 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005691 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005692 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005693 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005694 Results.EnterNewScope();
5695
5696 // Make sure that we ignore the class we're currently defining.
5697 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005698 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005699 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005700 Results.Ignore(CurClass);
5701
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005702 if (CodeCompleter->includeGlobals()) {
5703 // Add all classes.
5704 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5705 false, Results);
5706 }
5707
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005708 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005709
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005710 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005711 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005712 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005713}
5714
5715void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005716 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005717 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005718 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005719 Results.EnterNewScope();
5720
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005721 if (CodeCompleter->includeGlobals()) {
5722 // Add all unimplemented classes.
5723 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5724 true, Results);
5725 }
5726
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005727 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005728
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005729 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005730 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005731 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005732}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005733
5734void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005735 IdentifierInfo *ClassName,
5736 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005737 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005738
Douglas Gregor218937c2011-02-01 19:23:04 +00005739 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005740 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005741 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005742
5743 // Ignore any categories we find that have already been implemented by this
5744 // interface.
5745 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5746 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005747 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005748 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5749 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5750 Category = Category->getNextClassCategory())
5751 CategoryNames.insert(Category->getIdentifier());
5752
5753 // Add all of the categories we know about.
5754 Results.EnterNewScope();
5755 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5756 for (DeclContext::decl_iterator D = TU->decls_begin(),
5757 DEnd = TU->decls_end();
5758 D != DEnd; ++D)
5759 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5760 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005761 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005762 Results.ExitScope();
5763
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005764 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005765 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005766 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005767}
5768
5769void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005770 IdentifierInfo *ClassName,
5771 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005772 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005773
5774 // Find the corresponding interface. If we couldn't find the interface, the
5775 // program itself is ill-formed. However, we'll try to be helpful still by
5776 // providing the list of all of the categories we know about.
5777 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005778 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005779 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5780 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005781 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005782
Douglas Gregor218937c2011-02-01 19:23:04 +00005783 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005784 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005785 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005786
5787 // Add all of the categories that have have corresponding interface
5788 // declarations in this class and any of its superclasses, except for
5789 // already-implemented categories in the class itself.
5790 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5791 Results.EnterNewScope();
5792 bool IgnoreImplemented = true;
5793 while (Class) {
5794 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5795 Category = Category->getNextClassCategory())
5796 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5797 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005798 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005799
5800 Class = Class->getSuperClass();
5801 IgnoreImplemented = false;
5802 }
5803 Results.ExitScope();
5804
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005805 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005806 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005807 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005808}
Douglas Gregor322328b2009-11-18 22:32:06 +00005809
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005810void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005811 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005812 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005813 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005814 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005815
5816 // Figure out where this @synthesize lives.
5817 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005818 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005819 if (!Container ||
5820 (!isa<ObjCImplementationDecl>(Container) &&
5821 !isa<ObjCCategoryImplDecl>(Container)))
5822 return;
5823
5824 // Ignore any properties that have already been implemented.
5825 for (DeclContext::decl_iterator D = Container->decls_begin(),
5826 DEnd = Container->decls_end();
5827 D != DEnd; ++D)
5828 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5829 Results.Ignore(PropertyImpl->getPropertyDecl());
5830
5831 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005832 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005833 Results.EnterNewScope();
5834 if (ObjCImplementationDecl *ClassImpl
5835 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005836 AddObjCProperties(ClassImpl->getClassInterface(), false,
5837 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005838 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005839 else
5840 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005841 false, /*AllowNullaryMethods=*/false, CurContext,
5842 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005843 Results.ExitScope();
5844
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005845 HandleCodeCompleteResults(this, CodeCompleter,
5846 CodeCompletionContext::CCC_Other,
5847 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005848}
5849
5850void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005851 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005852 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005853 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005854 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005855 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005856
5857 // Figure out where this @synthesize lives.
5858 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005859 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005860 if (!Container ||
5861 (!isa<ObjCImplementationDecl>(Container) &&
5862 !isa<ObjCCategoryImplDecl>(Container)))
5863 return;
5864
5865 // Figure out which interface we're looking into.
5866 ObjCInterfaceDecl *Class = 0;
5867 if (ObjCImplementationDecl *ClassImpl
5868 = dyn_cast<ObjCImplementationDecl>(Container))
5869 Class = ClassImpl->getClassInterface();
5870 else
5871 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5872 ->getClassInterface();
5873
Douglas Gregore8426052011-04-18 14:40:46 +00005874 // Determine the type of the property we're synthesizing.
5875 QualType PropertyType = Context.getObjCIdType();
5876 if (Class) {
5877 if (ObjCPropertyDecl *Property
5878 = Class->FindPropertyDeclaration(PropertyName)) {
5879 PropertyType
5880 = Property->getType().getNonReferenceType().getUnqualifiedType();
5881
5882 // Give preference to ivars
5883 Results.setPreferredType(PropertyType);
5884 }
5885 }
5886
Douglas Gregor322328b2009-11-18 22:32:06 +00005887 // Add all of the instance variables in this class and its superclasses.
5888 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005889 bool SawSimilarlyNamedIvar = false;
5890 std::string NameWithPrefix;
5891 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005892 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005893 std::string NameWithSuffix = PropertyName->getName().str();
5894 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005895 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005896 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5897 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005898 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5899
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005900 // Determine whether we've seen an ivar with a name similar to the
5901 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005902 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005903 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005904 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005905 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005906
5907 // Reduce the priority of this result by one, to give it a slight
5908 // advantage over other results whose names don't match so closely.
5909 if (Results.size() &&
5910 Results.data()[Results.size() - 1].Kind
5911 == CodeCompletionResult::RK_Declaration &&
5912 Results.data()[Results.size() - 1].Declaration == Ivar)
5913 Results.data()[Results.size() - 1].Priority--;
5914 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005915 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005916 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005917
5918 if (!SawSimilarlyNamedIvar) {
5919 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005920 // an ivar of the appropriate type.
5921 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005922 typedef CodeCompletionResult Result;
5923 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005924 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
5925 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005926
Douglas Gregor8987b232011-09-27 23:30:47 +00005927 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005928 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005929 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005930 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5931 Results.AddResult(Result(Builder.TakeString(), Priority,
5932 CXCursor_ObjCIvarDecl));
5933 }
5934
Douglas Gregor322328b2009-11-18 22:32:06 +00005935 Results.ExitScope();
5936
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005937 HandleCodeCompleteResults(this, CodeCompleter,
5938 CodeCompletionContext::CCC_Other,
5939 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005940}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005941
Douglas Gregor408be5a2010-08-25 01:08:01 +00005942// Mapping from selectors to the methods that implement that selector, along
5943// with the "in original class" flag.
5944typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5945 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005946
5947/// \brief Find all of the methods that reside in the given container
5948/// (and its superclasses, protocols, etc.) that meet the given
5949/// criteria. Insert those methods into the map of known methods,
5950/// indexed by selector so they can be easily found.
5951static void FindImplementableMethods(ASTContext &Context,
5952 ObjCContainerDecl *Container,
5953 bool WantInstanceMethods,
5954 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005955 KnownMethodsMap &KnownMethods,
5956 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005957 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5958 // Recurse into protocols.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00005959 if (!IFace->hasDefinition())
5960 return;
5961
Douglas Gregore8f5a172010-04-07 00:21:17 +00005962 const ObjCList<ObjCProtocolDecl> &Protocols
5963 = IFace->getReferencedProtocols();
5964 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005965 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005966 I != E; ++I)
5967 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005968 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005969
Douglas Gregorea766182010-10-18 18:21:28 +00005970 // Add methods from any class extensions and categories.
5971 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5972 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005973 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5974 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005975 KnownMethods, false);
5976
5977 // Visit the superclass.
5978 if (IFace->getSuperClass())
5979 FindImplementableMethods(Context, IFace->getSuperClass(),
5980 WantInstanceMethods, ReturnType,
5981 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005982 }
5983
5984 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5985 // Recurse into protocols.
5986 const ObjCList<ObjCProtocolDecl> &Protocols
5987 = Category->getReferencedProtocols();
5988 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005989 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005990 I != E; ++I)
5991 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005992 KnownMethods, InOriginalClass);
5993
5994 // If this category is the original class, jump to the interface.
5995 if (InOriginalClass && Category->getClassInterface())
5996 FindImplementableMethods(Context, Category->getClassInterface(),
5997 WantInstanceMethods, ReturnType, KnownMethods,
5998 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005999 }
6000
6001 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00006002 if (Protocol->hasDefinition()) {
6003 // Recurse into protocols.
6004 const ObjCList<ObjCProtocolDecl> &Protocols
6005 = Protocol->getReferencedProtocols();
6006 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6007 E = Protocols.end();
6008 I != E; ++I)
6009 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6010 KnownMethods, false);
6011 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006012 }
6013
6014 // Add methods in this container. This operation occurs last because
6015 // we want the methods from this container to override any methods
6016 // we've previously seen with the same selector.
6017 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6018 MEnd = Container->meth_end();
6019 M != MEnd; ++M) {
6020 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
6021 if (!ReturnType.isNull() &&
6022 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
6023 continue;
6024
Douglas Gregor408be5a2010-08-25 01:08:01 +00006025 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006026 }
6027 }
6028}
6029
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006030/// \brief Add the parenthesized return or parameter type chunk to a code
6031/// completion string.
6032static void AddObjCPassingTypeChunk(QualType Type,
6033 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006034 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006035 CodeCompletionBuilder &Builder) {
6036 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor8987b232011-09-27 23:30:47 +00006037 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006038 Builder.getAllocator()));
6039 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6040}
6041
6042/// \brief Determine whether the given class is or inherits from a class by
6043/// the given name.
6044static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006045 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006046 if (!Class)
6047 return false;
6048
6049 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6050 return true;
6051
6052 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6053}
6054
6055/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6056/// Key-Value Observing (KVO).
6057static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6058 bool IsInstanceMethod,
6059 QualType ReturnType,
6060 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006061 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006062 ResultBuilder &Results) {
6063 IdentifierInfo *PropName = Property->getIdentifier();
6064 if (!PropName || PropName->getLength() == 0)
6065 return;
6066
Douglas Gregor8987b232011-09-27 23:30:47 +00006067 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6068
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006069 // Builder that will create each code completion.
6070 typedef CodeCompletionResult Result;
6071 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006072 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006073
6074 // The selector table.
6075 SelectorTable &Selectors = Context.Selectors;
6076
6077 // The property name, copied into the code completion allocation region
6078 // on demand.
6079 struct KeyHolder {
6080 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006081 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006082 const char *CopiedKey;
6083
Chris Lattner5f9e2722011-07-23 10:55:15 +00006084 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006085 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6086
6087 operator const char *() {
6088 if (CopiedKey)
6089 return CopiedKey;
6090
6091 return CopiedKey = Allocator.CopyString(Key);
6092 }
6093 } Key(Allocator, PropName->getName());
6094
6095 // The uppercased name of the property name.
6096 std::string UpperKey = PropName->getName();
6097 if (!UpperKey.empty())
6098 UpperKey[0] = toupper(UpperKey[0]);
6099
6100 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6101 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6102 Property->getType());
6103 bool ReturnTypeMatchesVoid
6104 = ReturnType.isNull() || ReturnType->isVoidType();
6105
6106 // Add the normal accessor -(type)key.
6107 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006108 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006109 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6110 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006111 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006112
6113 Builder.AddTypedTextChunk(Key);
6114 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6115 CXCursor_ObjCInstanceMethodDecl));
6116 }
6117
6118 // If we have an integral or boolean property (or the user has provided
6119 // an integral or boolean return type), add the accessor -(type)isKey.
6120 if (IsInstanceMethod &&
6121 ((!ReturnType.isNull() &&
6122 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6123 (ReturnType.isNull() &&
6124 (Property->getType()->isIntegerType() ||
6125 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006126 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006127 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006128 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006129 if (ReturnType.isNull()) {
6130 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6131 Builder.AddTextChunk("BOOL");
6132 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6133 }
6134
6135 Builder.AddTypedTextChunk(
6136 Allocator.CopyString(SelectorId->getName()));
6137 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6138 CXCursor_ObjCInstanceMethodDecl));
6139 }
6140 }
6141
6142 // Add the normal mutator.
6143 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6144 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006145 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006146 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006147 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006148 if (ReturnType.isNull()) {
6149 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6150 Builder.AddTextChunk("void");
6151 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6152 }
6153
6154 Builder.AddTypedTextChunk(
6155 Allocator.CopyString(SelectorId->getName()));
6156 Builder.AddTypedTextChunk(":");
Douglas Gregor8987b232011-09-27 23:30:47 +00006157 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006158 Builder.AddTextChunk(Key);
6159 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6160 CXCursor_ObjCInstanceMethodDecl));
6161 }
6162 }
6163
6164 // Indexed and unordered accessors
6165 unsigned IndexedGetterPriority = CCP_CodePattern;
6166 unsigned IndexedSetterPriority = CCP_CodePattern;
6167 unsigned UnorderedGetterPriority = CCP_CodePattern;
6168 unsigned UnorderedSetterPriority = CCP_CodePattern;
6169 if (const ObjCObjectPointerType *ObjCPointer
6170 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6171 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6172 // If this interface type is not provably derived from a known
6173 // collection, penalize the corresponding completions.
6174 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6175 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6176 if (!InheritsFromClassNamed(IFace, "NSArray"))
6177 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6178 }
6179
6180 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6181 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6182 if (!InheritsFromClassNamed(IFace, "NSSet"))
6183 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6184 }
6185 }
6186 } else {
6187 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6188 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6189 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6190 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6191 }
6192
6193 // Add -(NSUInteger)countOf<key>
6194 if (IsInstanceMethod &&
6195 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006196 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006197 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006198 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006199 if (ReturnType.isNull()) {
6200 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6201 Builder.AddTextChunk("NSUInteger");
6202 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6203 }
6204
6205 Builder.AddTypedTextChunk(
6206 Allocator.CopyString(SelectorId->getName()));
6207 Results.AddResult(Result(Builder.TakeString(),
6208 std::min(IndexedGetterPriority,
6209 UnorderedGetterPriority),
6210 CXCursor_ObjCInstanceMethodDecl));
6211 }
6212 }
6213
6214 // Indexed getters
6215 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6216 if (IsInstanceMethod &&
6217 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006218 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006219 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006220 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006221 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006222 if (ReturnType.isNull()) {
6223 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6224 Builder.AddTextChunk("id");
6225 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6226 }
6227
6228 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6229 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6230 Builder.AddTextChunk("NSUInteger");
6231 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6232 Builder.AddTextChunk("index");
6233 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6234 CXCursor_ObjCInstanceMethodDecl));
6235 }
6236 }
6237
6238 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6239 if (IsInstanceMethod &&
6240 (ReturnType.isNull() ||
6241 (ReturnType->isObjCObjectPointerType() &&
6242 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6243 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6244 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006245 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006246 = (Twine(Property->getName()) + "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("NSArray *");
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(), IndexedGetterPriority,
6261 CXCursor_ObjCInstanceMethodDecl));
6262 }
6263 }
6264
6265 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6266 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006267 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006268 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006269 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006270 &Context.Idents.get("range")
6271 };
6272
Douglas Gregore74c25c2011-05-04 23:50:46 +00006273 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006274 if (ReturnType.isNull()) {
6275 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6276 Builder.AddTextChunk("void");
6277 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6278 }
6279
6280 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6281 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6282 Builder.AddPlaceholderChunk("object-type");
6283 Builder.AddTextChunk(" **");
6284 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6285 Builder.AddTextChunk("buffer");
6286 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6287 Builder.AddTypedTextChunk("range:");
6288 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6289 Builder.AddTextChunk("NSRange");
6290 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6291 Builder.AddTextChunk("inRange");
6292 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6293 CXCursor_ObjCInstanceMethodDecl));
6294 }
6295 }
6296
6297 // Mutable indexed accessors
6298
6299 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6300 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006301 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006302 IdentifierInfo *SelectorIds[2] = {
6303 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006304 &Context.Idents.get(SelectorName)
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("insertObject:");
6315 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6316 Builder.AddPlaceholderChunk("object-type");
6317 Builder.AddTextChunk(" *");
6318 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6319 Builder.AddTextChunk("object");
6320 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6321 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6322 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6323 Builder.AddPlaceholderChunk("NSUInteger");
6324 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6325 Builder.AddTextChunk("index");
6326 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6327 CXCursor_ObjCInstanceMethodDecl));
6328 }
6329 }
6330
6331 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6332 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006333 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006334 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006335 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006336 &Context.Idents.get("atIndexes")
6337 };
6338
Douglas Gregore74c25c2011-05-04 23:50:46 +00006339 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006340 if (ReturnType.isNull()) {
6341 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6342 Builder.AddTextChunk("void");
6343 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6344 }
6345
6346 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6347 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6348 Builder.AddTextChunk("NSArray *");
6349 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6350 Builder.AddTextChunk("array");
6351 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6352 Builder.AddTypedTextChunk("atIndexes:");
6353 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6354 Builder.AddPlaceholderChunk("NSIndexSet *");
6355 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6356 Builder.AddTextChunk("indexes");
6357 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6358 CXCursor_ObjCInstanceMethodDecl));
6359 }
6360 }
6361
6362 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6363 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006364 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006365 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006366 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006367 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006368 if (ReturnType.isNull()) {
6369 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6370 Builder.AddTextChunk("void");
6371 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6372 }
6373
6374 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6375 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6376 Builder.AddTextChunk("NSUInteger");
6377 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6378 Builder.AddTextChunk("index");
6379 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6380 CXCursor_ObjCInstanceMethodDecl));
6381 }
6382 }
6383
6384 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6385 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006386 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006387 = (Twine("remove") + UpperKey + "AtIndexes").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.AddTextChunk("NSIndexSet *");
6399 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6400 Builder.AddTextChunk("indexes");
6401 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6402 CXCursor_ObjCInstanceMethodDecl));
6403 }
6404 }
6405
6406 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6407 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006408 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006409 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006410 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006411 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006412 &Context.Idents.get("withObject")
6413 };
6414
Douglas Gregore74c25c2011-05-04 23:50:46 +00006415 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006416 if (ReturnType.isNull()) {
6417 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6418 Builder.AddTextChunk("void");
6419 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6420 }
6421
6422 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6423 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6424 Builder.AddPlaceholderChunk("NSUInteger");
6425 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6426 Builder.AddTextChunk("index");
6427 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6428 Builder.AddTypedTextChunk("withObject:");
6429 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6430 Builder.AddTextChunk("id");
6431 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6432 Builder.AddTextChunk("object");
6433 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6434 CXCursor_ObjCInstanceMethodDecl));
6435 }
6436 }
6437
6438 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6439 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006440 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006441 = (Twine("replace") + UpperKey + "AtIndexes").str();
6442 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006443 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006444 &Context.Idents.get(SelectorName1),
6445 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006446 };
6447
Douglas Gregore74c25c2011-05-04 23:50:46 +00006448 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006449 if (ReturnType.isNull()) {
6450 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6451 Builder.AddTextChunk("void");
6452 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6453 }
6454
6455 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6456 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6457 Builder.AddPlaceholderChunk("NSIndexSet *");
6458 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6459 Builder.AddTextChunk("indexes");
6460 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6461 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6462 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6463 Builder.AddTextChunk("NSArray *");
6464 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6465 Builder.AddTextChunk("array");
6466 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6467 CXCursor_ObjCInstanceMethodDecl));
6468 }
6469 }
6470
6471 // Unordered getters
6472 // - (NSEnumerator *)enumeratorOfKey
6473 if (IsInstanceMethod &&
6474 (ReturnType.isNull() ||
6475 (ReturnType->isObjCObjectPointerType() &&
6476 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6477 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6478 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006479 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006480 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006481 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006482 if (ReturnType.isNull()) {
6483 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6484 Builder.AddTextChunk("NSEnumerator *");
6485 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6486 }
6487
6488 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6489 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6490 CXCursor_ObjCInstanceMethodDecl));
6491 }
6492 }
6493
6494 // - (type *)memberOfKey:(type *)object
6495 if (IsInstanceMethod &&
6496 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006497 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006498 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006499 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006500 if (ReturnType.isNull()) {
6501 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6502 Builder.AddPlaceholderChunk("object-type");
6503 Builder.AddTextChunk(" *");
6504 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6505 }
6506
6507 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6508 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6509 if (ReturnType.isNull()) {
6510 Builder.AddPlaceholderChunk("object-type");
6511 Builder.AddTextChunk(" *");
6512 } else {
6513 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006514 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006515 Builder.getAllocator()));
6516 }
6517 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6518 Builder.AddTextChunk("object");
6519 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6520 CXCursor_ObjCInstanceMethodDecl));
6521 }
6522 }
6523
6524 // Mutable unordered accessors
6525 // - (void)addKeyObject:(type *)object
6526 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006527 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006528 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006529 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006530 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006531 if (ReturnType.isNull()) {
6532 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6533 Builder.AddTextChunk("void");
6534 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6535 }
6536
6537 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6538 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6539 Builder.AddPlaceholderChunk("object-type");
6540 Builder.AddTextChunk(" *");
6541 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6542 Builder.AddTextChunk("object");
6543 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6544 CXCursor_ObjCInstanceMethodDecl));
6545 }
6546 }
6547
6548 // - (void)addKey:(NSSet *)objects
6549 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006550 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006551 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006552 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006553 if (ReturnType.isNull()) {
6554 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6555 Builder.AddTextChunk("void");
6556 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6557 }
6558
6559 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6560 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6561 Builder.AddTextChunk("NSSet *");
6562 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6563 Builder.AddTextChunk("objects");
6564 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6565 CXCursor_ObjCInstanceMethodDecl));
6566 }
6567 }
6568
6569 // - (void)removeKeyObject:(type *)object
6570 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006571 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006572 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006573 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006574 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006575 if (ReturnType.isNull()) {
6576 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6577 Builder.AddTextChunk("void");
6578 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6579 }
6580
6581 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6582 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6583 Builder.AddPlaceholderChunk("object-type");
6584 Builder.AddTextChunk(" *");
6585 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6586 Builder.AddTextChunk("object");
6587 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6588 CXCursor_ObjCInstanceMethodDecl));
6589 }
6590 }
6591
6592 // - (void)removeKey:(NSSet *)objects
6593 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006594 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006595 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006596 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006597 if (ReturnType.isNull()) {
6598 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6599 Builder.AddTextChunk("void");
6600 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6601 }
6602
6603 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6604 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6605 Builder.AddTextChunk("NSSet *");
6606 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6607 Builder.AddTextChunk("objects");
6608 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6609 CXCursor_ObjCInstanceMethodDecl));
6610 }
6611 }
6612
6613 // - (void)intersectKey:(NSSet *)objects
6614 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006615 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006616 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006617 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006618 if (ReturnType.isNull()) {
6619 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6620 Builder.AddTextChunk("void");
6621 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6622 }
6623
6624 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6625 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6626 Builder.AddTextChunk("NSSet *");
6627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6628 Builder.AddTextChunk("objects");
6629 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6630 CXCursor_ObjCInstanceMethodDecl));
6631 }
6632 }
6633
6634 // Key-Value Observing
6635 // + (NSSet *)keyPathsForValuesAffectingKey
6636 if (!IsInstanceMethod &&
6637 (ReturnType.isNull() ||
6638 (ReturnType->isObjCObjectPointerType() &&
6639 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6640 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6641 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006642 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006643 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006644 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006645 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006646 if (ReturnType.isNull()) {
6647 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6648 Builder.AddTextChunk("NSSet *");
6649 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6650 }
6651
6652 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6653 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006654 CXCursor_ObjCClassMethodDecl));
6655 }
6656 }
6657
6658 // + (BOOL)automaticallyNotifiesObserversForKey
6659 if (!IsInstanceMethod &&
6660 (ReturnType.isNull() ||
6661 ReturnType->isIntegerType() ||
6662 ReturnType->isBooleanType())) {
6663 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006664 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006665 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6666 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6667 if (ReturnType.isNull()) {
6668 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6669 Builder.AddTextChunk("BOOL");
6670 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6671 }
6672
6673 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6674 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6675 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006676 }
6677 }
6678}
6679
Douglas Gregore8f5a172010-04-07 00:21:17 +00006680void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6681 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006682 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006683 // Determine the return type of the method we're declaring, if
6684 // provided.
6685 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006686 Decl *IDecl = 0;
6687 if (CurContext->isObjCContainer()) {
6688 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6689 IDecl = cast<Decl>(OCD);
6690 }
Douglas Gregorea766182010-10-18 18:21:28 +00006691 // Determine where we should start searching for methods.
6692 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006693 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006694 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006695 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6696 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006697 IsInImplementation = true;
6698 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006699 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006700 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006701 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006702 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006703 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006704 }
6705
6706 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006707 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006708 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006709 }
6710
Douglas Gregorea766182010-10-18 18:21:28 +00006711 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006712 HandleCodeCompleteResults(this, CodeCompleter,
6713 CodeCompletionContext::CCC_Other,
6714 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006715 return;
6716 }
6717
6718 // Find all of the methods that we could declare/implement here.
6719 KnownMethodsMap KnownMethods;
6720 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006721 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006722
Douglas Gregore8f5a172010-04-07 00:21:17 +00006723 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006724 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006725 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006726 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006727 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006728 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006729 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006730 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6731 MEnd = KnownMethods.end();
6732 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006733 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006734 CodeCompletionBuilder Builder(Results.getAllocator(),
6735 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006736
6737 // If the result type was not already provided, add it to the
6738 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006739 if (ReturnType.isNull())
Douglas Gregor8987b232011-09-27 23:30:47 +00006740 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6741 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006742
6743 Selector Sel = Method->getSelector();
6744
6745 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006746 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006747 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006748
6749 // Add parameters to the pattern.
6750 unsigned I = 0;
6751 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6752 PEnd = Method->param_end();
6753 P != PEnd; (void)++P, ++I) {
6754 // Add the part of the selector name.
6755 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006756 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006757 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006758 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6759 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006760 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006761 } else
6762 break;
6763
6764 // Add the parameter type.
Douglas Gregor8987b232011-09-27 23:30:47 +00006765 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6766 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006767
6768 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006769 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006770 }
6771
6772 if (Method->isVariadic()) {
6773 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006774 Builder.AddChunk(CodeCompletionString::CK_Comma);
6775 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006776 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006777
Douglas Gregor447107d2010-05-28 00:57:46 +00006778 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006779 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006780 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6781 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6782 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006783 if (!Method->getResultType()->isVoidType()) {
6784 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006785 Builder.AddTextChunk("return");
6786 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6787 Builder.AddPlaceholderChunk("expression");
6788 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006789 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006790 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006791
Douglas Gregor218937c2011-02-01 19:23:04 +00006792 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6793 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006794 }
6795
Douglas Gregor408be5a2010-08-25 01:08:01 +00006796 unsigned Priority = CCP_CodePattern;
6797 if (!M->second.second)
6798 Priority += CCD_InBaseClass;
6799
Douglas Gregorba103062012-03-27 23:34:16 +00006800 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006801 }
6802
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006803 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6804 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006805 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006806 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006807 Containers.push_back(SearchDecl);
6808
Douglas Gregore74c25c2011-05-04 23:50:46 +00006809 VisitedSelectorSet KnownSelectors;
6810 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6811 MEnd = KnownMethods.end();
6812 M != MEnd; ++M)
6813 KnownSelectors.insert(M->first);
6814
6815
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006816 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6817 if (!IFace)
6818 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6819 IFace = Category->getClassInterface();
6820
6821 if (IFace) {
6822 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6823 Category = Category->getNextClassCategory())
6824 Containers.push_back(Category);
6825 }
6826
6827 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6828 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6829 PEnd = Containers[I]->prop_end();
6830 P != PEnd; ++P) {
6831 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006832 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006833 }
6834 }
6835 }
6836
Douglas Gregore8f5a172010-04-07 00:21:17 +00006837 Results.ExitScope();
6838
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006839 HandleCodeCompleteResults(this, CodeCompleter,
6840 CodeCompletionContext::CCC_Other,
6841 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006842}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006843
6844void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6845 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006846 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006847 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006848 IdentifierInfo **SelIdents,
6849 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006850 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006851 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006852 if (ExternalSource) {
6853 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6854 I != N; ++I) {
6855 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006856 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006857 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006858
6859 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006860 }
6861 }
6862
6863 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006864 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006865 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006866 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006867 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006868
6869 if (ReturnTy)
6870 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006871
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006872 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006873 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6874 MEnd = MethodPool.end();
6875 M != MEnd; ++M) {
6876 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6877 &M->second.second;
6878 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006879 MethList = MethList->Next) {
6880 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6881 NumSelIdents))
6882 continue;
6883
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006884 if (AtParameterName) {
6885 // Suggest parameter names we've seen before.
6886 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6887 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6888 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006889 CodeCompletionBuilder Builder(Results.getAllocator(),
6890 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00006891 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006892 Param->getIdentifier()->getName()));
6893 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006894 }
6895 }
6896
6897 continue;
6898 }
6899
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006900 Result R(MethList->Method, 0);
6901 R.StartParameter = NumSelIdents;
6902 R.AllParametersAreInformative = false;
6903 R.DeclaringEntity = true;
6904 Results.MaybeAddResult(R, CurContext);
6905 }
6906 }
6907
6908 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006909 HandleCodeCompleteResults(this, CodeCompleter,
6910 CodeCompletionContext::CCC_Other,
6911 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006912}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006913
Douglas Gregorf29c5232010-08-24 22:20:20 +00006914void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006915 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006916 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006917 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006918 Results.EnterNewScope();
6919
6920 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006921 CodeCompletionBuilder Builder(Results.getAllocator(),
6922 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00006923 Builder.AddTypedTextChunk("if");
6924 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6925 Builder.AddPlaceholderChunk("condition");
6926 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006927
6928 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006929 Builder.AddTypedTextChunk("ifdef");
6930 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6931 Builder.AddPlaceholderChunk("macro");
6932 Results.AddResult(Builder.TakeString());
6933
Douglas Gregorf44e8542010-08-24 19:08:16 +00006934 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006935 Builder.AddTypedTextChunk("ifndef");
6936 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6937 Builder.AddPlaceholderChunk("macro");
6938 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006939
6940 if (InConditional) {
6941 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00006942 Builder.AddTypedTextChunk("elif");
6943 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6944 Builder.AddPlaceholderChunk("condition");
6945 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006946
6947 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00006948 Builder.AddTypedTextChunk("else");
6949 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006950
6951 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00006952 Builder.AddTypedTextChunk("endif");
6953 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006954 }
6955
6956 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00006957 Builder.AddTypedTextChunk("include");
6958 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6959 Builder.AddTextChunk("\"");
6960 Builder.AddPlaceholderChunk("header");
6961 Builder.AddTextChunk("\"");
6962 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006963
6964 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00006965 Builder.AddTypedTextChunk("include");
6966 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6967 Builder.AddTextChunk("<");
6968 Builder.AddPlaceholderChunk("header");
6969 Builder.AddTextChunk(">");
6970 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006971
6972 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006973 Builder.AddTypedTextChunk("define");
6974 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6975 Builder.AddPlaceholderChunk("macro");
6976 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006977
6978 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00006979 Builder.AddTypedTextChunk("define");
6980 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6981 Builder.AddPlaceholderChunk("macro");
6982 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6983 Builder.AddPlaceholderChunk("args");
6984 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6985 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006986
6987 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00006988 Builder.AddTypedTextChunk("undef");
6989 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6990 Builder.AddPlaceholderChunk("macro");
6991 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006992
6993 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00006994 Builder.AddTypedTextChunk("line");
6995 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6996 Builder.AddPlaceholderChunk("number");
6997 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00006998
6999 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007000 Builder.AddTypedTextChunk("line");
7001 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7002 Builder.AddPlaceholderChunk("number");
7003 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7004 Builder.AddTextChunk("\"");
7005 Builder.AddPlaceholderChunk("filename");
7006 Builder.AddTextChunk("\"");
7007 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007008
7009 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007010 Builder.AddTypedTextChunk("error");
7011 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7012 Builder.AddPlaceholderChunk("message");
7013 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007014
7015 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007016 Builder.AddTypedTextChunk("pragma");
7017 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7018 Builder.AddPlaceholderChunk("arguments");
7019 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007020
David Blaikie4e4d0842012-03-11 07:00:24 +00007021 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007022 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007023 Builder.AddTypedTextChunk("import");
7024 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7025 Builder.AddTextChunk("\"");
7026 Builder.AddPlaceholderChunk("header");
7027 Builder.AddTextChunk("\"");
7028 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007029
7030 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007031 Builder.AddTypedTextChunk("import");
7032 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7033 Builder.AddTextChunk("<");
7034 Builder.AddPlaceholderChunk("header");
7035 Builder.AddTextChunk(">");
7036 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007037 }
7038
7039 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007040 Builder.AddTypedTextChunk("include_next");
7041 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7042 Builder.AddTextChunk("\"");
7043 Builder.AddPlaceholderChunk("header");
7044 Builder.AddTextChunk("\"");
7045 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007046
7047 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007048 Builder.AddTypedTextChunk("include_next");
7049 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7050 Builder.AddTextChunk("<");
7051 Builder.AddPlaceholderChunk("header");
7052 Builder.AddTextChunk(">");
7053 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007054
7055 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007056 Builder.AddTypedTextChunk("warning");
7057 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7058 Builder.AddPlaceholderChunk("message");
7059 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007060
7061 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7062 // completions for them. And __include_macros is a Clang-internal extension
7063 // that we don't want to encourage anyone to use.
7064
7065 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7066 Results.ExitScope();
7067
Douglas Gregorf44e8542010-08-24 19:08:16 +00007068 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007069 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007070 Results.data(), Results.size());
7071}
7072
7073void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007074 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007075 S->getFnParent()? Sema::PCC_RecoveryInFunction
7076 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007077}
7078
Douglas Gregorf29c5232010-08-24 22:20:20 +00007079void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007080 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007081 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007082 IsDefinition? CodeCompletionContext::CCC_MacroName
7083 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007084 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7085 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007086 CodeCompletionBuilder Builder(Results.getAllocator(),
7087 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007088 Results.EnterNewScope();
7089 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7090 MEnd = PP.macro_end();
7091 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007092 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007093 M->first->getName()));
7094 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007095 }
7096 Results.ExitScope();
7097 } else if (IsDefinition) {
7098 // FIXME: Can we detect when the user just wrote an include guard above?
7099 }
7100
Douglas Gregor52779fb2010-09-23 23:01:17 +00007101 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007102 Results.data(), Results.size());
7103}
7104
Douglas Gregorf29c5232010-08-24 22:20:20 +00007105void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007106 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007107 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007108 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007109
7110 if (!CodeCompleter || CodeCompleter->includeMacros())
7111 AddMacroResults(PP, Results);
7112
7113 // defined (<macro>)
7114 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007115 CodeCompletionBuilder Builder(Results.getAllocator(),
7116 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007117 Builder.AddTypedTextChunk("defined");
7118 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7119 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7120 Builder.AddPlaceholderChunk("macro");
7121 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7122 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007123 Results.ExitScope();
7124
7125 HandleCodeCompleteResults(this, CodeCompleter,
7126 CodeCompletionContext::CCC_PreprocessorExpression,
7127 Results.data(), Results.size());
7128}
7129
7130void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7131 IdentifierInfo *Macro,
7132 MacroInfo *MacroInfo,
7133 unsigned Argument) {
7134 // FIXME: In the future, we could provide "overload" results, much like we
7135 // do for function calls.
7136
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007137 // Now just ignore this. There will be another code-completion callback
7138 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007139}
7140
Douglas Gregor55817af2010-08-25 17:04:25 +00007141void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007142 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007143 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007144 0, 0);
7145}
7146
Douglas Gregordae68752011-02-01 22:57:45 +00007147void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007148 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007149 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007150 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7151 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007152 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7153 CodeCompletionDeclConsumer Consumer(Builder,
7154 Context.getTranslationUnitDecl());
7155 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7156 Consumer);
7157 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007158
7159 if (!CodeCompleter || CodeCompleter->includeMacros())
7160 AddMacroResults(PP, Builder);
7161
7162 Results.clear();
7163 Results.insert(Results.end(),
7164 Builder.data(), Builder.data() + Builder.size());
7165}