blob: b1904942f4e8e2587c8247d5ab9ee5f129cd0ab8 [file] [log] [blame]
Douglas Gregor2436e712009-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 McCall83024632010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.h"
Douglas Gregorc3a6ade2010-08-12 20:07:10 +000014#include "clang/Sema/Lookup.h"
John McCall5c32be02010-08-24 20:38:10 +000015#include "clang/Sema/Overload.h"
Douglas Gregor2436e712009-09-17 21:32:03 +000016#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregord720daf2010-04-06 17:30:22 +000017#include "clang/Sema/ExternalSemaSource.h"
John McCallcc14d1f2010-08-24 08:50:51 +000018#include "clang/Sema/Scope.h"
John McCallaab3e412010-08-25 08:40:02 +000019#include "clang/Sema/ScopeInfo.h"
John McCallde6836a2010-08-24 07:21:54 +000020#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000021#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000022#include "clang/AST/ExprObjC.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000024#include "clang/Lex/MacroInfo.h"
25#include "clang/Lex/Preprocessor.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000026#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000027#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000028#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000029#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000030#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000031#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000032#include "llvm/ADT/Twine.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000033#include <list>
34#include <map>
35#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000036
37using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000038using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000039
Douglas Gregor3545ff42009-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 McCall276321a2010-08-25 06:19:51 +000050 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-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 Gregor05e7ca32009-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 Lattner0e62c1c2011-07-23 10:55:15 +000067 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-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 Gregor3545ff42009-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 Gregor05e7ca32009-12-06 20:23:50 +0000118 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000119
120 /// \brief The semantic analysis object for which results are being
121 /// produced.
122 Sema &SemaRef;
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000123
124 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000125 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000126
127 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor3545ff42009-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 Gregor6ae4c522010-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 Gregor7aa6b222010-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 Gregor3545ff42009-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 Gregor9be0ed42010-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 Gregorc2cb2e22010-08-27 15:29:55 +0000155 /// \brief The selector that we prefer.
156 Selector PreferredSelector;
157
Douglas Gregor05fcf842010-11-02 20:36:02 +0000158 /// \brief The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000159 CodeCompletionContext CompletionContext;
160
James Dennett596e4752012-06-14 03:11:41 +0000161 /// \brief If we are in an instance method definition, the \@implementation
Douglas Gregor05fcf842010-11-02 20:36:02 +0000162 /// object.
163 ObjCImplementationDecl *ObjCImplementation;
164
Douglas Gregor50832e02010-09-20 22:39:41 +0000165 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000166
Douglas Gregor0212fd72010-09-21 16:06:22 +0000167 void MaybeAddConstructorResults(Result R);
168
Douglas Gregor3545ff42009-09-21 16:56:56 +0000169 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000170 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000171 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000172 const CodeCompletionContext &CompletionContext,
173 LookupFilter Filter = 0)
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000174 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
175 Filter(Filter),
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000176 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-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 Gregor3545ff42009-09-21 16:56:56 +0000198
Douglas Gregorf64acca2010-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 Gregorac322ec2010-08-27 21:18:54 +0000203 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000204 }
205
Douglas Gregor3545ff42009-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 Gregor3545ff42009-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 Gregor7aa6b222010-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 Gregor9be0ed42010-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 Gregorc2cb2e22010-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 Gregor05fcf842010-11-02 20:36:02 +0000240
Douglas Gregor50832e02010-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 Gregor6ae4c522010-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 Gregor74661272010-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 Gregorb278aaf2011-02-01 19:23:04 +0000256 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000257 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +0000258
259 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000260
Douglas Gregor7c208612010-01-14 00:20:49 +0000261 /// \brief Determine whether the given declaration is at all interesting
262 /// as a code-completion result.
Douglas Gregor6ae4c522010-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 Gregore0717ab2010-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 Gregor3545ff42009-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 Gregor2af2f672009-09-21 20:12:40 +0000282 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000283 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000284 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000285 /// \param CurContext the context in which this result will be named.
Douglas Gregor2af2f672009-09-21 20:12:40 +0000286 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000287
Douglas Gregorc580c522010-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 Gregor09bbc652010-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 Gregorc580c522010-01-14 01:09:38 +0000301
Douglas Gregor78a21012010-01-14 16:01:26 +0000302 /// \brief Add a new non-declaration result to this result set.
303 void AddResult(Result R);
304
Douglas Gregor3545ff42009-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 Gregorbaf69612009-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 Gregor3545ff42009-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 Gregor9d64c5e2009-09-21 20:51:25 +0000320 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor70febae2010-05-28 00:49:12 +0000321 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregor85b50632010-07-28 21:50:18 +0000322 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor504a6ae2010-01-10 23:08:15 +0000323 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor3545ff42009-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 Gregore412a5a2009-09-23 22:26:46 +0000331 bool IsMember(NamedDecl *ND) const;
Douglas Gregor2b8162b2010-01-14 16:08:12 +0000332 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregora817a192010-05-27 23:06:34 +0000333 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregord8c61782012-02-15 15:34:24 +0000334 bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
Douglas Gregor68762e72010-08-23 21:17:50 +0000335 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor0ac41382010-09-23 23:01:17 +0000336 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000337 //@}
338 };
339}
340
Douglas Gregor05e7ca32009-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 Lattner9795b392010-09-04 18:12:20 +0000383 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000384 iterator tmp(*this);
385 ++(*this);
386 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000387 }*/
Douglas Gregor05e7ca32009-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 Gregor94bb5e82009-12-06 21:27:58 +0000393 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-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 Gregor94bb5e82009-12-06 21:27:58 +0000401 return X.DeclOrIterator.getOpaqueValue()
402 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000403 X.SingleDeclIndex == Y.SingleDeclIndex;
404 }
405
406 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000407 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000408 }
409};
410
Douglas Gregor05e7ca32009-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 Gregor2af2f672009-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 Lattner0e62c1c2011-07-23 10:55:15 +0000447 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor2af2f672009-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 Gregor68762e72010-08-23 21:17:50 +0000464 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
465 if (!Namespace->getIdentifier())
466 continue;
467
Douglas Gregor2af2f672009-09-21 20:12:40 +0000468 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000469 }
Douglas Gregor2af2f672009-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 Gregor9eb77012009-11-07 00:00:49 +0000474 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000475 return Result;
476}
477
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000478bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
479 bool &AsNestedNameSpecifier) const {
480 AsNestedNameSpecifier = false;
481
Douglas Gregor7c208612010-01-14 00:20:49 +0000482 ND = ND->getUnderlyingDecl();
483 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregor58acf322009-10-09 22:16:47 +0000484
485 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000486 if (!ND->getDeclName())
487 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000488
489 // Friend declarations and declarations introduced due to friends are never
490 // added as results.
John McCallbbbbe4e2010-03-11 07:50:04 +0000491 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregor7c208612010-01-14 00:20:49 +0000492 return false;
493
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000494 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000495 if (isa<ClassTemplateSpecializationDecl>(ND) ||
496 isa<ClassTemplatePartialSpecializationDecl>(ND))
497 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000498
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000499 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-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 Gregor3545ff42009-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 Gregor7c208612010-01-14 00:20:49 +0000507 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000508
Douglas Gregor58acf322009-10-09 22:16:47 +0000509 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor9f1570d2010-07-14 17:44:04 +0000510 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbar2c422dc92009-10-18 20:26:12 +0000511 //
512 // FIXME: Add predicate for this.
Douglas Gregor58acf322009-10-09 22:16:47 +0000513 if (Id->getLength() >= 2) {
Daniel Dunbar2c422dc92009-10-18 20:26:12 +0000514 const char *Name = Id->getNameStart();
Douglas Gregor58acf322009-10-09 22:16:47 +0000515 if (Name[0] == '_' &&
Douglas Gregor9f1570d2010-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 Gregor7c208612010-01-14 00:20:49 +0000520 return false;
Douglas Gregor58acf322009-10-09 22:16:47 +0000521 }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000522 }
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000523
Douglas Gregor59cab552010-08-16 23:05:20 +0000524 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
525 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
526 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000527 Filter != &ResultBuilder::IsNamespaceOrAlias &&
528 Filter != 0))
Douglas Gregor59cab552010-08-16 23:05:20 +0000529 AsNestedNameSpecifier = true;
530
Douglas Gregor3545ff42009-09-21 16:56:56 +0000531 // Filter out any unwanted results.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000532 if (Filter && !(this->*Filter)(ND)) {
533 // Check whether it is interesting as a nested-name-specifier.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000534 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-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 Gregor7c208612010-01-14 00:20:49 +0000543 return false;
Douglas Gregor59cab552010-08-16 23:05:20 +0000544 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000545 // ... then it must be interesting!
546 return true;
547}
548
Douglas Gregore0717ab2010-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 Blaikiebbafb8a2012-03-11 07:00:24 +0000554 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000555 return true;
556
Sebastian Redl50c68252010-08-31 00:36:30 +0000557 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregore0717ab2010-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 Redl50c68252010-08-31 00:36:30 +0000563 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-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 Gregor95887f92010-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 Gregor6e240332010-08-16 16:18:59 +0000579SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-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 Gregor95887f92010-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 Blaikie8a40f702012-01-17 06:56:22 +0000601
Douglas Gregor95887f92010-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 Gregor6e240332010-08-16 16:18:59 +0000648QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor95887f92010-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 Gregor603d81b2010-07-13 08:18:22 +0000658 T = Function->getCallResultType();
Douglas Gregor95887f92010-07-08 23:20:03 +0000659 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000660 T = Method->getSendResultType();
Douglas Gregor95887f92010-07-08 23:20:03 +0000661 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000662 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor95887f92010-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 Gregoraf670a82011-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 Gregor95887f92010-07-08 23:20:03 +0000704}
705
Douglas Gregor50832e02010-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 Gregor5fb901d2010-09-20 23:11:55 +0000713
Douglas Gregor50832e02010-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 Gregor95887f92010-07-08 23:20:03 +0000725 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000726 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
727 R.Priority /= CCF_SimilarTypeMatch;
728 }
729 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000730}
731
Douglas Gregor0212fd72010-09-21 16:06:22 +0000732void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000733 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-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 Gregor7c208612010-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 Gregor6ae4c522010-01-14 03:21:49 +0000786 bool AsNestedNameSpecifier = false;
787 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000788 return;
789
Douglas Gregor0212fd72010-09-21 16:06:22 +0000790 // C++ constructors are never found by name lookup.
791 if (isa<CXXConstructorDecl>(R.Declaration))
792 return;
793
Douglas Gregor3545ff42009-09-21 16:56:56 +0000794 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-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 Gregor3545ff42009-09-21 16:56:56 +0000805 if (ND->getCanonicalDecl() == CanonDecl) {
806 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000807 Results[Index].Declaration = R.Declaration;
808
Douglas Gregor3545ff42009-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 Gregor05e7ca32009-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 Gregor3545ff42009-09-21 16:56:56 +0000827 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000828 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor3545ff42009-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 Gregor05e7ca32009-12-06 20:23:50 +0000834 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000835 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000836 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000837 continue;
838
839 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000840 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000841 return;
Douglas Gregor3545ff42009-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 Gregorc2cb2e22010-08-27 15:29:55 +0000850
Douglas Gregore412a5a2009-09-23 22:26:46 +0000851 // If the filter is for nested-name-specifiers, then this result starts a
852 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000853 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000854 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000855 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregor50832e02010-09-20 22:39:41 +0000856 } else
857 AdjustResultPriorityForDecl(R);
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000858
Douglas Gregor5bf52692009-09-22 23:15:58 +0000859 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000860 if (R.QualifierIsInformative && !R.Qualifier &&
861 !R.StartsNestedNameSpecifier) {
Douglas Gregor5bf52692009-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 Gregore412a5a2009-09-23 22:26:46 +0000871
Douglas Gregor3545ff42009-09-21 16:56:56 +0000872 // Insert this result into the set of results and into the current shadow
873 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000874 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000875 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +0000876
877 if (!AsNestedNameSpecifier)
878 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000879}
880
Douglas Gregorc580c522010-01-14 01:09:38 +0000881void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000882 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-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 Gregorc580c522010-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 Gregor6ae4c522010-01-14 03:21:49 +0000895 bool AsNestedNameSpecifier = false;
896 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000897 return;
898
Douglas Gregor0212fd72010-09-21 16:06:22 +0000899 // C++ constructors are never found by name lookup.
900 if (isa<CXXConstructorDecl>(R.Declaration))
901 return;
902
Douglas Gregorc580c522010-01-14 01:09:38 +0000903 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
904 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +0000905
Douglas Gregorc580c522010-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 Gregora2db7932010-05-26 22:00:08 +0000912 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +0000913 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000914 R.Priority = CCP_NestedNameSpecifier;
915 }
Douglas Gregor09bbc652010-01-14 15:47:35 +0000916 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
917 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl50c68252010-08-31 00:36:30 +0000918 ->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +0000919 R.QualifierIsInformative = true;
920
Douglas Gregorc580c522010-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 Gregor6ae4c522010-01-14 03:21:49 +0000929 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +0000930 else
931 R.QualifierIsInformative = false;
932 }
933
Douglas Gregora2db7932010-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 Gregor50832e02010-09-20 22:39:41 +0000938 AdjustResultPriorityForDecl(R);
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000939
Douglas Gregor9be0ed42010-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 Gregorc580c522010-01-14 01:09:38 +0000954 // Insert this result into the set of results.
955 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +0000956
957 if (!AsNestedNameSpecifier)
958 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +0000959}
960
Douglas Gregor78a21012010-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 Gregor3545ff42009-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 Gregor05e7ca32009-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 Gregor3545ff42009-09-21 16:56:56 +0000980 ShadowMaps.pop_back();
981}
982
Douglas Gregor9d64c5e2009-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 Gregor70febae2010-05-28 00:49:12 +0000986 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
987
Douglas Gregor9d64c5e2009-09-21 20:51:25 +0000988 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikiebbafb8a2012-03-11 07:00:24 +0000989 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +0000990 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +0000991 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +0000992 if (isa<ObjCIvarDecl>(ND))
993 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +0000994 }
995
Douglas Gregor9d64c5e2009-09-21 20:51:25 +0000996 return ND->getIdentifierNamespace() & IDNS;
997}
998
Douglas Gregor504a6ae2010-01-10 23:08:15 +0000999/// \brief Determines whether this given declaration will be found by
Douglas Gregor70febae2010-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 Blaikiebbafb8a2012-03-11 07:00:24 +00001007 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001008 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001009 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001010 if (isa<ObjCIvarDecl>(ND))
1011 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001012 }
1013
Douglas Gregor70febae2010-05-28 00:49:12 +00001014 return ND->getIdentifierNamespace() & IDNS;
1015}
1016
Douglas Gregor85b50632010-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 Gregor70febae2010-05-28 00:49:12 +00001028/// \brief Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001029/// ordinary name lookup.
1030bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001031 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1032
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001033 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001034 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001035 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001036
1037 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001038 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1039 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001040}
1041
Douglas Gregor3545ff42009-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 Bagnara6150c882010-05-11 21:36:43 +00001064 return RD->getTagKind() == TTK_Class ||
1065 RD->getTagKind() == TTK_Struct;
Douglas Gregor3545ff42009-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 Bagnara6150c882010-05-11 21:36:43 +00001077 return RD->getTagKind() == TTK_Union;
Douglas Gregor3545ff42009-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 Gregor99fe2ad2009-12-11 17:31:05 +00001093/// \brief Determines whether the given declaration is a type.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001094bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregor99fa2642010-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 Gregor3545ff42009-09-21 16:56:56 +00001099}
1100
Douglas Gregor99fe2ad2009-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 Gregore412a5a2009-09-23 22:26:46 +00001104bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001105 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1106 ND = Using->getTargetDecl();
1107
Douglas Gregor70788392009-12-11 18:14:22 +00001108 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1109 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001110}
1111
Douglas Gregora817a192010-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 Blaikiebbafb8a2012-03-11 07:00:24 +00001136 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-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 Gregord8c61782012-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 Gregor68762e72010-08-23 21:17:50 +00001165bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001166 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1167 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-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 Blaikiebbafb8a2012-03-11 07:00:24 +00001177 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001178}
Douglas Gregora817a192010-05-27 23:06:34 +00001179
Douglas Gregor0ac41382010-09-23 23:01:17 +00001180bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1181 return false;
1182}
1183
Douglas Gregor2b8162b2010-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 Gregorc580c522010-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 Verbruggen2e657ff2011-10-06 07:27:49 +00001201 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1202 bool InBaseClass) {
1203 bool Accessible = true;
Douglas Gregor03ba1882011-11-03 16:51:37 +00001204 if (Ctx)
1205 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1206
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001207 ResultBuilder::Result Result(ND, 0, false, Accessible);
1208 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001209 }
1210 };
1211}
1212
Douglas Gregor3545ff42009-09-21 16:56:56 +00001213/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001214static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001215 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001216 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-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 Gregor504a6ae2010-01-10 23:08:15 +00001231
Douglas Gregor3545ff42009-09-21 16:56:56 +00001232 if (LangOpts.C99) {
1233 // C99-specific
Douglas Gregora2db7932010-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 Gregor3545ff42009-09-21 16:56:56 +00001238 }
1239
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001240 CodeCompletionBuilder Builder(Results.getAllocator(),
1241 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001242 if (LangOpts.CPlusPlus) {
1243 // C++-specific
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001244 Results.AddResult(Result("bool", CCP_Type +
1245 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001246 Results.AddResult(Result("class", CCP_Type));
1247 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001248
Douglas Gregorf4c33342010-05-28 00:22:41 +00001249 // typename qualified-id
Douglas Gregorb278aaf2011-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 Gregorf64acca2010-05-25 21:41:55 +00001256
Douglas Gregor3545ff42009-09-21 16:56:56 +00001257 if (LangOpts.CPlusPlus0x) {
Douglas Gregora2db7932010-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 Gregorf4c33342010-05-28 00:22:41 +00001261
Douglas Gregorb278aaf2011-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 Gregor3545ff42009-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 Gregor78a21012010-01-14 16:01:26 +00001273 // Results.AddResult(Result("_Decimal32"));
1274 // Results.AddResult(Result("_Decimal64"));
1275 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001276
Douglas Gregorb278aaf2011-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 Gregorf4c33342010-05-28 00:22:41 +00001281
Douglas Gregorb278aaf2011-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 Gregor3545ff42009-09-21 16:56:56 +00001287 }
1288}
1289
John McCallfaf5fb42010-08-26 23:41:50 +00001290static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001291 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001292 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001293 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-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 Gregor78a21012010-01-14 16:01:26 +00001297 Results.AddResult(Result("extern"));
1298 Results.AddResult(Result("static"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001299}
1300
John McCallfaf5fb42010-08-26 23:41:50 +00001301static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001302 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001303 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001304 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001305 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001306 case Sema::PCC_Class:
1307 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001308 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-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 Gregor504a6ae2010-01-10 23:08:15 +00001313 }
1314 // Fall through
1315
John McCallfaf5fb42010-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 Gregor504a6ae2010-01-10 23:08:15 +00001320 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001321 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001322 break;
1323
John McCallfaf5fb42010-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 Gregor5e35d592010-09-14 23:59:36 +00001331 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001332 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001333 break;
1334 }
1335}
1336
Douglas Gregorf98e6a22010-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 Gregor48d46252010-01-13 21:54:15 +00001340 ResultBuilder &Results,
1341 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001342static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001343 ResultBuilder &Results,
1344 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001345static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001346 ResultBuilder &Results,
1347 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001348static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001349
Douglas Gregorf4c33342010-05-28 00:22:41 +00001350static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001351 CodeCompletionBuilder Builder(Results.getAllocator(),
1352 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-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 Gregorf4c33342010-05-28 00:22:41 +00001359}
1360
John McCallfaf5fb42010-08-26 23:41:50 +00001361static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001362 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001363 switch (CCC) {
John McCallfaf5fb42010-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 Gregor5e35d592010-09-14 23:59:36 +00001372 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001373 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001374 return true;
1375
John McCallfaf5fb42010-08-26 23:41:50 +00001376 case Sema::PCC_Expression:
1377 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001378 return LangOpts.CPlusPlus;
1379
1380 case Sema::PCC_ObjCInterface:
1381 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001382 return false;
1383
John McCallfaf5fb42010-08-26 23:41:50 +00001384 case Sema::PCC_ForInit:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001385 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001386 }
David Blaikie8a40f702012-01-17 06:56:22 +00001387
1388 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001389}
1390
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001391static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1392 const Preprocessor &PP) {
1393 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001394 Policy.AnonymousTagLocations = false;
1395 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001396 Policy.SuppressUnwrittenScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001397 return Policy;
1398}
1399
Argyrios Kyrtzidis8d05ca72012-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 Gregore5c79d52011-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))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001417 return BT->getNameAsCString(Policy);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001418
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 Gregord8c61782012-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 Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001445 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-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 Gregor504a6ae2010-01-10 23:08:15 +00001455/// \brief Add language constructs that show up for "ordinary" names.
John McCallfaf5fb42010-08-26 23:41:50 +00001456static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001457 Scope *S,
1458 Sema &SemaRef,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001459 ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001460 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001461 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregore5c79d52011-10-18 21:20:17 +00001462 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001463
John McCall276321a2010-08-25 06:19:51 +00001464 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001465 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001466 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001467 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001468 if (Results.includeCodePatterns()) {
1469 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-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 Gregorf4c33342010-05-28 00:22:41 +00001478 }
1479
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001480 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-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 Gregor504a6ae2010-01-10 23:08:15 +00001487
1488 // Using directives
Douglas Gregorb278aaf2011-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 Gregor504a6ae2010-01-10 23:08:15 +00001495
1496 // asm(string-literal)
Douglas Gregorb278aaf2011-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 Gregor504a6ae2010-01-10 23:08:15 +00001502
Douglas Gregorf4c33342010-05-28 00:22:41 +00001503 if (Results.includeCodePatterns()) {
1504 // Explicit template instantiation
Douglas Gregorb278aaf2011-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 Gregorf4c33342010-05-28 00:22:41 +00001509 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001510 }
Douglas Gregorf1934162010-01-13 21:24:21 +00001511
David Blaikiebbafb8a2012-03-11 07:00:24 +00001512 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001513 AddObjCTopLevelResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001514
Douglas Gregorf4c33342010-05-28 00:22:41 +00001515 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001516 // Fall through
1517
John McCallfaf5fb42010-08-26 23:41:50 +00001518 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001519 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001520 // Using declaration
Douglas Gregorb278aaf2011-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 Gregor504a6ae2010-01-10 23:08:15 +00001527
Douglas Gregorf4c33342010-05-28 00:22:41 +00001528 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001529 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-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 Gregor504a6ae2010-01-10 23:08:15 +00001538 }
1539
John McCallfaf5fb42010-08-26 23:41:50 +00001540 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001541 AddTypedefResult(Results);
1542
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001543 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001544 Builder.AddTypedTextChunk("public");
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001545 if (Results.includeCodePatterns())
1546 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001547 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001548
1549 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001550 Builder.AddTypedTextChunk("protected");
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001551 if (Results.includeCodePatterns())
1552 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001553 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001554
1555 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001556 Builder.AddTypedTextChunk("private");
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001557 if (Results.includeCodePatterns())
1558 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001559 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001560 }
1561 }
1562 // Fall through
1563
John McCallfaf5fb42010-08-26 23:41:50 +00001564 case Sema::PCC_Template:
1565 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001566 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001567 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001568 Builder.AddTypedTextChunk("template");
1569 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1570 Builder.AddPlaceholderChunk("parameters");
1571 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1572 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001573 }
1574
David Blaikiebbafb8a2012-03-11 07:00:24 +00001575 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1576 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001577 break;
1578
John McCallfaf5fb42010-08-26 23:41:50 +00001579 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001580 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1581 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1582 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001583 break;
1584
John McCallfaf5fb42010-08-26 23:41:50 +00001585 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001586 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1587 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1588 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001589 break;
1590
John McCallfaf5fb42010-08-26 23:41:50 +00001591 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001592 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001593 break;
1594
John McCallfaf5fb42010-08-26 23:41:50 +00001595 case Sema::PCC_RecoveryInFunction:
1596 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001597 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001598
David Blaikiebbafb8a2012-03-11 07:00:24 +00001599 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1600 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001601 Builder.AddTypedTextChunk("try");
1602 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1603 Builder.AddPlaceholderChunk("statements");
1604 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1605 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1606 Builder.AddTextChunk("catch");
1607 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1608 Builder.AddPlaceholderChunk("declaration");
1609 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1610 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1611 Builder.AddPlaceholderChunk("statements");
1612 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1613 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1614 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001615 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001616 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001617 AddObjCStatementResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001618
Douglas Gregorf64acca2010-05-25 21:41:55 +00001619 if (Results.includeCodePatterns()) {
1620 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001621 Builder.AddTypedTextChunk("if");
1622 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001623 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001624 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001625 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001626 Builder.AddPlaceholderChunk("expression");
1627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1628 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1629 Builder.AddPlaceholderChunk("statements");
1630 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1631 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1632 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001633
Douglas Gregorf64acca2010-05-25 21:41:55 +00001634 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001635 Builder.AddTypedTextChunk("switch");
1636 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001637 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001638 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001639 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001640 Builder.AddPlaceholderChunk("expression");
1641 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1642 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1643 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1644 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1645 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001646 }
1647
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001648 // Switch-specific statements.
John McCallaab3e412010-08-25 08:40:02 +00001649 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001650 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001651 Builder.AddTypedTextChunk("case");
1652 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1653 Builder.AddPlaceholderChunk("expression");
1654 Builder.AddChunk(CodeCompletionString::CK_Colon);
1655 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001656
1657 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001658 Builder.AddTypedTextChunk("default");
1659 Builder.AddChunk(CodeCompletionString::CK_Colon);
1660 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001661 }
1662
Douglas Gregorf64acca2010-05-25 21:41:55 +00001663 if (Results.includeCodePatterns()) {
1664 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001665 Builder.AddTypedTextChunk("while");
1666 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001667 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001668 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001669 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001670 Builder.AddPlaceholderChunk("expression");
1671 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1672 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1673 Builder.AddPlaceholderChunk("statements");
1674 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1675 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1676 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001677
1678 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001679 Builder.AddTypedTextChunk("do");
1680 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1681 Builder.AddPlaceholderChunk("statements");
1682 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1683 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1684 Builder.AddTextChunk("while");
1685 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1686 Builder.AddPlaceholderChunk("expression");
1687 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1688 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001689
Douglas Gregorf64acca2010-05-25 21:41:55 +00001690 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001691 Builder.AddTypedTextChunk("for");
1692 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001693 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001694 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001695 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001696 Builder.AddPlaceholderChunk("init-expression");
1697 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1698 Builder.AddPlaceholderChunk("condition");
1699 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1700 Builder.AddPlaceholderChunk("inc-expression");
1701 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1702 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1703 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1704 Builder.AddPlaceholderChunk("statements");
1705 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1706 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1707 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001708 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001709
1710 if (S->getContinueParent()) {
1711 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001712 Builder.AddTypedTextChunk("continue");
1713 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001714 }
1715
1716 if (S->getBreakParent()) {
1717 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001718 Builder.AddTypedTextChunk("break");
1719 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001720 }
1721
1722 // "return expression ;" or "return ;", depending on whether we
1723 // know the function is void or not.
1724 bool isVoid = false;
1725 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1726 isVoid = Function->getResultType()->isVoidType();
1727 else if (ObjCMethodDecl *Method
1728 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1729 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9a28e842010-03-01 23:15:13 +00001730 else if (SemaRef.getCurBlock() &&
1731 !SemaRef.getCurBlock()->ReturnType.isNull())
1732 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001733 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001734 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001735 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1736 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001737 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001738 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001739
Douglas Gregorf4c33342010-05-28 00:22:41 +00001740 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001741 Builder.AddTypedTextChunk("goto");
1742 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1743 Builder.AddPlaceholderChunk("label");
1744 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001745
Douglas Gregorf4c33342010-05-28 00:22:41 +00001746 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001747 Builder.AddTypedTextChunk("using");
1748 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1749 Builder.AddTextChunk("namespace");
1750 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1751 Builder.AddPlaceholderChunk("identifier");
1752 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001753 }
1754
1755 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001756 case Sema::PCC_ForInit:
1757 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001758 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001759 // Fall through: conditions and statements can have expressions.
1760
Douglas Gregor5e35d592010-09-14 23:59:36 +00001761 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001762 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00001763 CCC == Sema::PCC_ParenthesizedExpression) {
1764 // (__bridge <type>)<expression>
1765 Builder.AddTypedTextChunk("__bridge");
1766 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1767 Builder.AddPlaceholderChunk("type");
1768 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1769 Builder.AddPlaceholderChunk("expression");
1770 Results.AddResult(Result(Builder.TakeString()));
1771
1772 // (__bridge_transfer <Objective-C type>)<expression>
1773 Builder.AddTypedTextChunk("__bridge_transfer");
1774 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1775 Builder.AddPlaceholderChunk("Objective-C type");
1776 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1777 Builder.AddPlaceholderChunk("expression");
1778 Results.AddResult(Result(Builder.TakeString()));
1779
1780 // (__bridge_retained <CF type>)<expression>
1781 Builder.AddTypedTextChunk("__bridge_retained");
1782 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1783 Builder.AddPlaceholderChunk("CF type");
1784 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1785 Builder.AddPlaceholderChunk("expression");
1786 Results.AddResult(Result(Builder.TakeString()));
1787 }
1788 // Fall through
1789
John McCallfaf5fb42010-08-26 23:41:50 +00001790 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001791 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001792 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001793 addThisCompletion(SemaRef, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001794
Douglas Gregore5c79d52011-10-18 21:20:17 +00001795 // true
1796 Builder.AddResultTypeChunk("bool");
1797 Builder.AddTypedTextChunk("true");
1798 Results.AddResult(Result(Builder.TakeString()));
1799
1800 // false
1801 Builder.AddResultTypeChunk("bool");
1802 Builder.AddTypedTextChunk("false");
1803 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001804
David Blaikiebbafb8a2012-03-11 07:00:24 +00001805 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001806 // dynamic_cast < type-id > ( expression )
1807 Builder.AddTypedTextChunk("dynamic_cast");
1808 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1809 Builder.AddPlaceholderChunk("type");
1810 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1811 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1812 Builder.AddPlaceholderChunk("expression");
1813 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1814 Results.AddResult(Result(Builder.TakeString()));
1815 }
Douglas Gregorf4c33342010-05-28 00:22:41 +00001816
1817 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001818 Builder.AddTypedTextChunk("static_cast");
1819 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1820 Builder.AddPlaceholderChunk("type");
1821 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1822 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1823 Builder.AddPlaceholderChunk("expression");
1824 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1825 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001826
Douglas Gregorf4c33342010-05-28 00:22:41 +00001827 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001828 Builder.AddTypedTextChunk("reinterpret_cast");
1829 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1830 Builder.AddPlaceholderChunk("type");
1831 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1832 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1833 Builder.AddPlaceholderChunk("expression");
1834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1835 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001836
Douglas Gregorf4c33342010-05-28 00:22:41 +00001837 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001838 Builder.AddTypedTextChunk("const_cast");
1839 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1840 Builder.AddPlaceholderChunk("type");
1841 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1842 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1843 Builder.AddPlaceholderChunk("expression");
1844 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1845 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001846
David Blaikiebbafb8a2012-03-11 07:00:24 +00001847 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001848 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00001849 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00001850 Builder.AddTypedTextChunk("typeid");
1851 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1852 Builder.AddPlaceholderChunk("expression-or-type");
1853 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1854 Results.AddResult(Result(Builder.TakeString()));
1855 }
1856
Douglas Gregorf4c33342010-05-28 00:22:41 +00001857 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001858 Builder.AddTypedTextChunk("new");
1859 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1860 Builder.AddPlaceholderChunk("type");
1861 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1862 Builder.AddPlaceholderChunk("expressions");
1863 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1864 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001865
Douglas Gregorf4c33342010-05-28 00:22:41 +00001866 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001867 Builder.AddTypedTextChunk("new");
1868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1869 Builder.AddPlaceholderChunk("type");
1870 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1871 Builder.AddPlaceholderChunk("size");
1872 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1873 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1874 Builder.AddPlaceholderChunk("expressions");
1875 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1876 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001877
Douglas Gregorf4c33342010-05-28 00:22:41 +00001878 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001879 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001880 Builder.AddTypedTextChunk("delete");
1881 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1882 Builder.AddPlaceholderChunk("expression");
1883 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001884
Douglas Gregorf4c33342010-05-28 00:22:41 +00001885 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001886 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001887 Builder.AddTypedTextChunk("delete");
1888 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1889 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1890 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1891 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1892 Builder.AddPlaceholderChunk("expression");
1893 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001894
David Blaikiebbafb8a2012-03-11 07:00:24 +00001895 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001896 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001897 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00001898 Builder.AddTypedTextChunk("throw");
1899 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1900 Builder.AddPlaceholderChunk("expression");
1901 Results.AddResult(Result(Builder.TakeString()));
1902 }
Douglas Gregor4205fef2011-10-18 16:29:03 +00001903
Douglas Gregora2db7932010-05-26 22:00:08 +00001904 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00001905
David Blaikiebbafb8a2012-03-11 07:00:24 +00001906 if (SemaRef.getLangOpts().CPlusPlus0x) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00001907 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00001908 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001909 Builder.AddTypedTextChunk("nullptr");
1910 Results.AddResult(Result(Builder.TakeString()));
1911
1912 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00001913 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001914 Builder.AddTypedTextChunk("alignof");
1915 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1916 Builder.AddPlaceholderChunk("type");
1917 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1918 Results.AddResult(Result(Builder.TakeString()));
1919
1920 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00001921 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001922 Builder.AddTypedTextChunk("noexcept");
1923 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1924 Builder.AddPlaceholderChunk("expression");
1925 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1926 Results.AddResult(Result(Builder.TakeString()));
1927
1928 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001929 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001930 Builder.AddTypedTextChunk("sizeof...");
1931 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1932 Builder.AddPlaceholderChunk("parameter-pack");
1933 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1934 Results.AddResult(Result(Builder.TakeString()));
1935 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001936 }
1937
David Blaikiebbafb8a2012-03-11 07:00:24 +00001938 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001939 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00001940 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1941 // The interface can be NULL.
1942 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00001943 if (ID->getSuperClass()) {
1944 std::string SuperType;
1945 SuperType = ID->getSuperClass()->getNameAsString();
1946 if (Method->isInstanceMethod())
1947 SuperType += " *";
1948
1949 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1950 Builder.AddTypedTextChunk("super");
1951 Results.AddResult(Result(Builder.TakeString()));
1952 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00001953 }
1954
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001955 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001956 }
1957
Douglas Gregorf4c33342010-05-28 00:22:41 +00001958 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001959 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001960 Builder.AddTypedTextChunk("sizeof");
1961 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1962 Builder.AddPlaceholderChunk("expression-or-type");
1963 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1964 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001965 break;
1966 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00001967
John McCallfaf5fb42010-08-26 23:41:50 +00001968 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00001969 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00001970 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001971 }
1972
David Blaikiebbafb8a2012-03-11 07:00:24 +00001973 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1974 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001975
David Blaikiebbafb8a2012-03-11 07:00:24 +00001976 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00001977 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001978}
1979
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001980/// \brief If the given declaration has an associated type, add it as a result
1981/// type chunk.
1982static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00001983 const PrintingPolicy &Policy,
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001984 NamedDecl *ND,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001985 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001986 if (!ND)
1987 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00001988
1989 // Skip constructors and conversion functions, which have their return types
1990 // built into their names.
1991 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1992 return;
1993
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001994 // Determine the type of the declaration (if it has a type).
Douglas Gregor0212fd72010-09-21 16:06:22 +00001995 QualType T;
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001996 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1997 T = Function->getResultType();
1998 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1999 T = Method->getResultType();
2000 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
2001 T = FunTmpl->getTemplatedDecl()->getResultType();
2002 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
2003 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2004 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2005 /* Do nothing: ignore unresolved using declarations*/
John McCall31168b02011-06-15 23:02:42 +00002006 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002007 T = Value->getType();
John McCall31168b02011-06-15 23:02:42 +00002008 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002009 T = Property->getType();
2010
2011 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2012 return;
2013
Douglas Gregor75acd922011-09-27 23:30:47 +00002014 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002015 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002016}
2017
Douglas Gregordbb71db2010-08-23 23:51:41 +00002018static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002019 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002020 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2021 if (Sentinel->getSentinel() == 0) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002022 if (Context.getLangOpts().ObjC1 &&
Douglas Gregordbb71db2010-08-23 23:51:41 +00002023 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002024 Result.AddTextChunk(", nil");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002025 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002026 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002027 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002028 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002029 }
2030}
2031
Douglas Gregor8f08d742011-07-30 07:55:26 +00002032static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2033 std::string Result;
2034 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002035 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002036 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002037 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002038 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002039 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002040 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002041 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002042 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002043 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002044 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002045 Result += "oneway ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002046 return Result;
2047}
2048
Douglas Gregore90dd002010-08-24 16:15:59 +00002049static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002050 const PrintingPolicy &Policy,
Douglas Gregor981a0c42010-08-29 19:47:46 +00002051 ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002052 bool SuppressName = false,
2053 bool SuppressBlock = false) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002054 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2055 if (Param->getType()->isDependentType() ||
2056 !Param->getType()->isBlockPointerType()) {
2057 // The argument for a dependent or non-block parameter is a placeholder
2058 // containing that parameter's type.
2059 std::string Result;
2060
Douglas Gregor981a0c42010-08-29 19:47:46 +00002061 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002062 Result = Param->getIdentifier()->getName();
2063
John McCall31168b02011-06-15 23:02:42 +00002064 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002065
2066 if (ObjCMethodParam) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002067 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2068 + Result + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002069 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002070 Result += Param->getIdentifier()->getName();
2071 }
2072 return Result;
2073 }
2074
2075 // The argument for a block pointer parameter is a block literal with
2076 // the appropriate type.
Douglas Gregor24bbc462011-02-15 22:37:09 +00002077 FunctionTypeLoc *Block = 0;
2078 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregore90dd002010-08-24 16:15:59 +00002079 TypeLoc TL;
2080 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2081 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2082 while (true) {
2083 // Look through typedefs.
Douglas Gregord793e7c2011-10-18 04:23:19 +00002084 if (!SuppressBlock) {
2085 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2086 if (TypeSourceInfo *InnerTSInfo
2087 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2088 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2089 continue;
2090 }
2091 }
2092
2093 // Look through qualified types
2094 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2095 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregore90dd002010-08-24 16:15:59 +00002096 continue;
2097 }
2098 }
2099
Douglas Gregore90dd002010-08-24 16:15:59 +00002100 // Try to get the function prototype behind the block pointer type,
2101 // then we're done.
2102 if (BlockPointerTypeLoc *BlockPtr
2103 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara6d810632010-12-14 22:11:44 +00002104 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor24bbc462011-02-15 22:37:09 +00002105 Block = dyn_cast<FunctionTypeLoc>(&TL);
2106 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregore90dd002010-08-24 16:15:59 +00002107 }
2108 break;
2109 }
2110 }
2111
2112 if (!Block) {
2113 // We were unable to find a FunctionProtoTypeLoc with parameter names
2114 // for the block; just use the parameter type as a placeholder.
2115 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002116 if (!ObjCMethodParam && Param->getIdentifier())
2117 Result = Param->getIdentifier()->getName();
2118
John McCall31168b02011-06-15 23:02:42 +00002119 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002120
2121 if (ObjCMethodParam) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002122 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2123 + Result + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002124 if (Param->getIdentifier())
2125 Result += Param->getIdentifier()->getName();
2126 }
2127
2128 return Result;
2129 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002130
Douglas Gregore90dd002010-08-24 16:15:59 +00002131 // We have the function prototype behind the block pointer type, as it was
2132 // written in the source.
Douglas Gregor67da50e2010-09-08 22:47:51 +00002133 std::string Result;
2134 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002135 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002136 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002137
2138 // Format the parameter list.
2139 std::string Params;
Douglas Gregor24bbc462011-02-15 22:37:09 +00002140 if (!BlockProto || Block->getNumArgs() == 0) {
2141 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002142 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002143 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002144 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002145 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002146 Params += "(";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002147 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2148 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002149 Params += ", ";
2150 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2151 /*SuppressName=*/false,
2152 /*SuppressBlock=*/true);
Douglas Gregor67da50e2010-09-08 22:47:51 +00002153
Douglas Gregor24bbc462011-02-15 22:37:09 +00002154 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002155 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002156 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002157 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002158 }
Douglas Gregor67da50e2010-09-08 22:47:51 +00002159
Douglas Gregord793e7c2011-10-18 04:23:19 +00002160 if (SuppressBlock) {
2161 // Format as a parameter.
2162 Result = Result + " (^";
2163 if (Param->getIdentifier())
2164 Result += Param->getIdentifier()->getName();
2165 Result += ")";
2166 Result += Params;
2167 } else {
2168 // Format as a block literal argument.
2169 Result = '^' + Result;
2170 Result += Params;
2171
2172 if (Param->getIdentifier())
2173 Result += Param->getIdentifier()->getName();
2174 }
2175
Douglas Gregore90dd002010-08-24 16:15:59 +00002176 return Result;
2177}
2178
Douglas Gregor3545ff42009-09-21 16:56:56 +00002179/// \brief Add function parameter chunks to the given code completion string.
2180static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002181 const PrintingPolicy &Policy,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002182 FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002183 CodeCompletionBuilder &Result,
2184 unsigned Start = 0,
2185 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002186 bool FirstParameter = true;
Douglas Gregor9eb77012009-11-07 00:00:49 +00002187
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002188 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002189 ParmVarDecl *Param = Function->getParamDecl(P);
2190
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002191 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002192 // When we see an optional default argument, put that argument and
2193 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002194 CodeCompletionBuilder Opt(Result.getAllocator(),
2195 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002196 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002197 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002198 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002199 Result.AddOptionalChunk(Opt.TakeString());
2200 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002201 }
2202
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002203 if (FirstParameter)
2204 FirstParameter = false;
2205 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002206 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002207
2208 InOptional = false;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002209
2210 // Format the placeholder string.
Douglas Gregor75acd922011-09-27 23:30:47 +00002211 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2212 Param);
Douglas Gregore90dd002010-08-24 16:15:59 +00002213
Douglas Gregor400f5972010-08-31 05:13:43 +00002214 if (Function->isVariadic() && P == N - 1)
2215 PlaceholderStr += ", ...";
2216
Douglas Gregor3545ff42009-09-21 16:56:56 +00002217 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002218 Result.AddPlaceholderChunk(
2219 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002220 }
Douglas Gregorba449032009-09-22 21:42:17 +00002221
2222 if (const FunctionProtoType *Proto
2223 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002224 if (Proto->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00002225 if (Proto->getNumArgs() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002226 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002227
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002228 MaybeAddSentinel(Context, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002229 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002230}
2231
2232/// \brief Add template parameter chunks to the given code completion string.
2233static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002234 const PrintingPolicy &Policy,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002235 TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002236 CodeCompletionBuilder &Result,
2237 unsigned MaxParameters = 0,
2238 unsigned Start = 0,
2239 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002240 bool FirstParameter = true;
2241
2242 TemplateParameterList *Params = Template->getTemplateParameters();
2243 TemplateParameterList::iterator PEnd = Params->end();
2244 if (MaxParameters)
2245 PEnd = Params->begin() + MaxParameters;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002246 for (TemplateParameterList::iterator P = Params->begin() + Start;
2247 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002248 bool HasDefaultArg = false;
2249 std::string PlaceholderStr;
2250 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2251 if (TTP->wasDeclaredWithTypename())
2252 PlaceholderStr = "typename";
2253 else
2254 PlaceholderStr = "class";
2255
2256 if (TTP->getIdentifier()) {
2257 PlaceholderStr += ' ';
2258 PlaceholderStr += TTP->getIdentifier()->getName();
2259 }
2260
2261 HasDefaultArg = TTP->hasDefaultArgument();
2262 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002263 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002264 if (NTTP->getIdentifier())
2265 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002266 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002267 HasDefaultArg = NTTP->hasDefaultArgument();
2268 } else {
2269 assert(isa<TemplateTemplateParmDecl>(*P));
2270 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2271
2272 // Since putting the template argument list into the placeholder would
2273 // be very, very long, we just use an abbreviation.
2274 PlaceholderStr = "template<...> class";
2275 if (TTP->getIdentifier()) {
2276 PlaceholderStr += ' ';
2277 PlaceholderStr += TTP->getIdentifier()->getName();
2278 }
2279
2280 HasDefaultArg = TTP->hasDefaultArgument();
2281 }
2282
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002283 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002284 // When we see an optional default argument, put that argument and
2285 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002286 CodeCompletionBuilder Opt(Result.getAllocator(),
2287 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002288 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002289 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002290 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002291 P - Params->begin(), true);
2292 Result.AddOptionalChunk(Opt.TakeString());
2293 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002294 }
2295
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002296 InDefaultArg = false;
2297
Douglas Gregor3545ff42009-09-21 16:56:56 +00002298 if (FirstParameter)
2299 FirstParameter = false;
2300 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002301 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002302
2303 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002304 Result.AddPlaceholderChunk(
2305 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002306 }
2307}
2308
Douglas Gregorf2510672009-09-21 19:57:38 +00002309/// \brief Add a qualifier to the given code-completion string, if the
2310/// provided nested-name-specifier is non-NULL.
Douglas Gregor0f622362009-12-11 18:44:16 +00002311static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002312AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregor0f622362009-12-11 18:44:16 +00002313 NestedNameSpecifier *Qualifier,
2314 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002315 ASTContext &Context,
2316 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002317 if (!Qualifier)
2318 return;
2319
2320 std::string PrintedNNS;
2321 {
2322 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002323 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002324 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002325 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002326 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002327 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002328 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002329}
2330
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002331static void
2332AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2333 FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002334 const FunctionProtoType *Proto
2335 = Function->getType()->getAs<FunctionProtoType>();
2336 if (!Proto || !Proto->getTypeQuals())
2337 return;
2338
Douglas Gregor304f9b02011-02-01 21:15:40 +00002339 // FIXME: Add ref-qualifier!
2340
2341 // Handle single qualifiers without copying
2342 if (Proto->getTypeQuals() == Qualifiers::Const) {
2343 Result.AddInformativeChunk(" const");
2344 return;
2345 }
2346
2347 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2348 Result.AddInformativeChunk(" volatile");
2349 return;
2350 }
2351
2352 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2353 Result.AddInformativeChunk(" restrict");
2354 return;
2355 }
2356
2357 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002358 std::string QualsStr;
2359 if (Proto->getTypeQuals() & Qualifiers::Const)
2360 QualsStr += " const";
2361 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2362 QualsStr += " volatile";
2363 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2364 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002365 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002366}
2367
Douglas Gregor0212fd72010-09-21 16:06:22 +00002368/// \brief Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002369static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2370 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002371 DeclarationName Name = ND->getDeclName();
2372 if (!Name)
2373 return;
2374
2375 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002376 case DeclarationName::CXXOperatorName: {
2377 const char *OperatorName = 0;
2378 switch (Name.getCXXOverloadedOperator()) {
2379 case OO_None:
2380 case OO_Conditional:
2381 case NUM_OVERLOADED_OPERATORS:
2382 OperatorName = "operator";
2383 break;
2384
2385#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2386 case OO_##Name: OperatorName = "operator" Spelling; break;
2387#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2388#include "clang/Basic/OperatorKinds.def"
2389
2390 case OO_New: OperatorName = "operator new"; break;
2391 case OO_Delete: OperatorName = "operator delete"; break;
2392 case OO_Array_New: OperatorName = "operator new[]"; break;
2393 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2394 case OO_Call: OperatorName = "operator()"; break;
2395 case OO_Subscript: OperatorName = "operator[]"; break;
2396 }
2397 Result.AddTypedTextChunk(OperatorName);
2398 break;
2399 }
2400
Douglas Gregor0212fd72010-09-21 16:06:22 +00002401 case DeclarationName::Identifier:
2402 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002403 case DeclarationName::CXXDestructorName:
2404 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002405 Result.AddTypedTextChunk(
2406 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002407 break;
2408
2409 case DeclarationName::CXXUsingDirective:
2410 case DeclarationName::ObjCZeroArgSelector:
2411 case DeclarationName::ObjCOneArgSelector:
2412 case DeclarationName::ObjCMultiArgSelector:
2413 break;
2414
2415 case DeclarationName::CXXConstructorName: {
2416 CXXRecordDecl *Record = 0;
2417 QualType Ty = Name.getCXXNameType();
2418 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2419 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2420 else if (const InjectedClassNameType *InjectedTy
2421 = Ty->getAs<InjectedClassNameType>())
2422 Record = InjectedTy->getDecl();
2423 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002424 Result.AddTypedTextChunk(
2425 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002426 break;
2427 }
2428
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002429 Result.AddTypedTextChunk(
2430 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002431 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002432 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002433 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002434 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002435 }
2436 break;
2437 }
2438 }
2439}
2440
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002441CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002442 CodeCompletionAllocator &Allocator,
2443 CodeCompletionTUInfo &CCTUInfo) {
2444 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002445}
2446
Douglas Gregor3545ff42009-09-21 16:56:56 +00002447/// \brief If possible, create a new code completion string for the given
2448/// result.
2449///
2450/// \returns Either a new, heap-allocated code completion string describing
2451/// how to use this result, or NULL to indicate that the string or name of the
2452/// result is all that is needed.
2453CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002454CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2455 Preprocessor &PP,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002456 CodeCompletionAllocator &Allocator,
2457 CodeCompletionTUInfo &CCTUInfo) {
2458 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor9eb77012009-11-07 00:00:49 +00002459
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002460 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002461 if (Kind == RK_Pattern) {
2462 Pattern->Priority = Priority;
2463 Pattern->Availability = Availability;
Douglas Gregor78254c82012-03-27 23:34:16 +00002464
2465 if (Declaration) {
2466 Result.addParentContext(Declaration->getDeclContext());
2467 Pattern->ParentKind = Result.getParentKind();
2468 Pattern->ParentName = Result.getParentName();
2469 }
2470
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002471 return Pattern;
2472 }
Douglas Gregorf09935f2009-12-01 05:55:20 +00002473
Douglas Gregorf09935f2009-12-01 05:55:20 +00002474 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002475 Result.AddTypedTextChunk(Keyword);
2476 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002477 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002478
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002479 if (Kind == RK_Macro) {
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002480 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregorf09935f2009-12-01 05:55:20 +00002481 assert(MI && "Not a macro?");
2482
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002483 Result.AddTypedTextChunk(
2484 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregorf09935f2009-12-01 05:55:20 +00002485
2486 if (!MI->isFunctionLike())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002487 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002488
2489 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002490 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor0c505312011-07-30 08:17:44 +00002491 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002492
2493 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2494 if (MI->isC99Varargs()) {
2495 --AEnd;
2496
2497 if (A == AEnd) {
2498 Result.AddPlaceholderChunk("...");
2499 }
Douglas Gregor0c505312011-07-30 08:17:44 +00002500 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002501
Douglas Gregor0c505312011-07-30 08:17:44 +00002502 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002503 if (A != MI->arg_begin())
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002504 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3aa55262012-01-21 00:43:38 +00002505
2506 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002507 SmallString<32> Arg = (*A)->getName();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002508 if (MI->isC99Varargs())
2509 Arg += ", ...";
2510 else
2511 Arg += "...";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002512 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3aa55262012-01-21 00:43:38 +00002513 break;
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002514 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002515
2516 // Non-variadic macros are simple.
2517 Result.AddPlaceholderChunk(
2518 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor0c505312011-07-30 08:17:44 +00002519 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002520 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002521 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002522 }
2523
Douglas Gregorf64acca2010-05-25 21:41:55 +00002524 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor3545ff42009-09-21 16:56:56 +00002525 NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002526 Result.addParentContext(ND->getDeclContext());
2527
Douglas Gregor9eb77012009-11-07 00:00:49 +00002528 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002529 Result.AddTypedTextChunk(
2530 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002531 Result.AddTextChunk("::");
2532 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002533 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002534
2535 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2536 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2537 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2538 }
2539 }
Douglas Gregor9eb77012009-11-07 00:00:49 +00002540
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002541 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002542
Douglas Gregor3545ff42009-09-21 16:56:56 +00002543 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002544 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002545 Ctx, Policy);
2546 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002547 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002548 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002549 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002550 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002551 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002552 }
2553
2554 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002555 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002556 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002557 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002558 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002559
Douglas Gregor3545ff42009-09-21 16:56:56 +00002560 // Figure out which template parameters are deduced (or have default
2561 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002562 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002563 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002564 unsigned LastDeducibleArgument;
2565 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2566 --LastDeducibleArgument) {
2567 if (!Deduced[LastDeducibleArgument - 1]) {
2568 // C++0x: Figure out if the template argument has a default. If so,
2569 // the user doesn't need to type this argument.
2570 // FIXME: We need to abstract template parameters better!
2571 bool HasDefaultArg = false;
2572 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002573 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002574 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2575 HasDefaultArg = TTP->hasDefaultArgument();
2576 else if (NonTypeTemplateParmDecl *NTTP
2577 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2578 HasDefaultArg = NTTP->hasDefaultArgument();
2579 else {
2580 assert(isa<TemplateTemplateParmDecl>(Param));
2581 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002582 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002583 }
2584
2585 if (!HasDefaultArg)
2586 break;
2587 }
2588 }
2589
2590 if (LastDeducibleArgument) {
2591 // Some of the function template arguments cannot be deduced from a
2592 // function call, so we introduce an explicit template argument list
2593 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002594 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002595 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002596 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002597 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002598 }
2599
2600 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002601 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002602 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002603 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002604 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002605 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002606 }
2607
2608 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002609 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002610 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002611 Result.AddTypedTextChunk(
2612 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002613 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002614 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002615 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002616 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002617 }
2618
Douglas Gregord3c5d792009-11-17 16:44:22 +00002619 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002620 Selector Sel = Method->getSelector();
2621 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002622 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002623 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002624 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002625 }
2626
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002627 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002628 SelName += ':';
2629 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002630 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002631 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002632 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002633
2634 // If there is only one parameter, and we're past it, add an empty
2635 // typed-text chunk since there is nothing to type.
2636 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002637 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002638 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002639 unsigned Idx = 0;
2640 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2641 PEnd = Method->param_end();
2642 P != PEnd; (void)++P, ++Idx) {
2643 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002644 std::string Keyword;
2645 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002646 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002647 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002648 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002649 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002650 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002651 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002652 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002653 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002654 }
Douglas Gregor1b605f72009-11-19 01:08:35 +00002655
2656 // If we're before the starting parameter, skip the placeholder.
2657 if (Idx < StartParameter)
2658 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002659
2660 std::string Arg;
Douglas Gregore90dd002010-08-24 16:15:59 +00002661
2662 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002663 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregore90dd002010-08-24 16:15:59 +00002664 else {
John McCall31168b02011-06-15 23:02:42 +00002665 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor8f08d742011-07-30 07:55:26 +00002666 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2667 + Arg + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002668 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00002669 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00002670 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00002671 }
2672
Douglas Gregor400f5972010-08-31 05:13:43 +00002673 if (Method->isVariadic() && (P + 1) == PEnd)
2674 Arg += ", ...";
2675
Douglas Gregor95887f92010-07-08 23:20:03 +00002676 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002677 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00002678 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002679 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00002680 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002681 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002682 }
2683
Douglas Gregor04c5f972009-12-23 00:21:46 +00002684 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00002685 if (Method->param_size() == 0) {
2686 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002687 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002688 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002689 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002690 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002691 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002692 }
Douglas Gregordbb71db2010-08-23 23:51:41 +00002693
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002694 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00002695 }
2696
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002697 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002698 }
2699
Douglas Gregorf09935f2009-12-01 05:55:20 +00002700 if (Qualifier)
Douglas Gregor5bf52692009-09-22 23:15:58 +00002701 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002702 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00002703
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002704 Result.AddTypedTextChunk(
2705 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002706 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002707}
2708
Douglas Gregorf0f51982009-09-23 00:34:09 +00002709CodeCompletionString *
2710CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2711 unsigned CurrentArg,
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00002712 Sema &S,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002713 CodeCompletionAllocator &Allocator,
2714 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00002715 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00002716
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002717 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002718 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002719 FunctionDecl *FDecl = getFunction();
Douglas Gregor75acd922011-09-27 23:30:47 +00002720 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002721 const FunctionProtoType *Proto
2722 = dyn_cast<FunctionProtoType>(getFunctionType());
2723 if (!FDecl && !Proto) {
2724 // Function without a prototype. Just give the return type and a
2725 // highlighted ellipsis.
2726 const FunctionType *FT = getFunctionType();
Douglas Gregor304f9b02011-02-01 21:15:40 +00002727 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00002728 S.Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002729 Result.getAllocator()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002730 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2731 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2732 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002733 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00002734 }
2735
2736 if (FDecl)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002737 Result.AddTextChunk(
2738 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002739 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002740 Result.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002741 Result.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00002742 Proto->getResultType().getAsString(Policy)));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002743
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002744 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002745 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2746 for (unsigned I = 0; I != NumParams; ++I) {
2747 if (I)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002748 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002749
2750 std::string ArgString;
2751 QualType ArgType;
2752
2753 if (FDecl) {
2754 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2755 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2756 } else {
2757 ArgType = Proto->getArgType(I);
2758 }
2759
John McCall31168b02011-06-15 23:02:42 +00002760 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002761
2762 if (I == CurrentArg)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002763 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2764 Result.getAllocator().CopyString(ArgString));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002765 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002766 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002767 }
2768
2769 if (Proto && Proto->isVariadic()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002770 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002771 if (CurrentArg < NumParams)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002772 Result.AddTextChunk("...");
Douglas Gregorf0f51982009-09-23 00:34:09 +00002773 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002774 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregorf0f51982009-09-23 00:34:09 +00002775 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002776 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002777
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002778 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00002779}
2780
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002781unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002782 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00002783 bool PreferredTypeIsPointer) {
2784 unsigned Priority = CCP_Macro;
2785
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002786 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2787 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2788 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00002789 Priority = CCP_Constant;
2790 if (PreferredTypeIsPointer)
2791 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002792 }
2793 // Treat "YES", "NO", "true", and "false" as constants.
2794 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2795 MacroName.equals("true") || MacroName.equals("false"))
2796 Priority = CCP_Constant;
2797 // Treat "bool" as a type.
2798 else if (MacroName.equals("bool"))
2799 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2800
Douglas Gregor6e240332010-08-16 16:18:59 +00002801
2802 return Priority;
2803}
2804
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002805CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2806 if (!D)
2807 return CXCursor_UnexposedDecl;
2808
2809 switch (D->getKind()) {
2810 case Decl::Enum: return CXCursor_EnumDecl;
2811 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2812 case Decl::Field: return CXCursor_FieldDecl;
2813 case Decl::Function:
2814 return CXCursor_FunctionDecl;
2815 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2816 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002817 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00002818
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00002819 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002820 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2821 case Decl::ObjCMethod:
2822 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2823 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2824 case Decl::CXXMethod: return CXCursor_CXXMethod;
2825 case Decl::CXXConstructor: return CXCursor_Constructor;
2826 case Decl::CXXDestructor: return CXCursor_Destructor;
2827 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2828 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00002829 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002830 case Decl::ParmVar: return CXCursor_ParmDecl;
2831 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00002832 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002833 case Decl::Var: return CXCursor_VarDecl;
2834 case Decl::Namespace: return CXCursor_Namespace;
2835 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2836 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2837 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2838 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2839 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2840 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00002841 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002842 case Decl::ClassTemplatePartialSpecialization:
2843 return CXCursor_ClassTemplatePartialSpecialization;
2844 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor3e653b32012-04-30 23:41:16 +00002845 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002846
2847 case Decl::Using:
2848 case Decl::UnresolvedUsingValue:
2849 case Decl::UnresolvedUsingTypename:
2850 return CXCursor_UsingDeclaration;
2851
Douglas Gregor4cd65962011-06-03 23:08:58 +00002852 case Decl::ObjCPropertyImpl:
2853 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2854 case ObjCPropertyImplDecl::Dynamic:
2855 return CXCursor_ObjCDynamicDecl;
2856
2857 case ObjCPropertyImplDecl::Synthesize:
2858 return CXCursor_ObjCSynthesizeDecl;
2859 }
Douglas Gregor4cd65962011-06-03 23:08:58 +00002860
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002861 default:
2862 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2863 switch (TD->getTagKind()) {
2864 case TTK_Struct: return CXCursor_StructDecl;
2865 case TTK_Class: return CXCursor_ClassDecl;
2866 case TTK_Union: return CXCursor_UnionDecl;
2867 case TTK_Enum: return CXCursor_EnumDecl;
2868 }
2869 }
2870 }
2871
2872 return CXCursor_UnexposedDecl;
2873}
2874
Douglas Gregor55b037b2010-07-08 20:55:51 +00002875static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2876 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00002877 typedef CodeCompletionResult Result;
Douglas Gregor55b037b2010-07-08 20:55:51 +00002878
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002879 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002880
Douglas Gregor9eb77012009-11-07 00:00:49 +00002881 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2882 MEnd = PP.macro_end();
Douglas Gregor55b037b2010-07-08 20:55:51 +00002883 M != MEnd; ++M) {
Douglas Gregor6e240332010-08-16 16:18:59 +00002884 Results.AddResult(Result(M->first,
2885 getMacroUsagePriority(M->first->getName(),
David Blaikiebbafb8a2012-03-11 07:00:24 +00002886 PP.getLangOpts(),
Douglas Gregor6e240332010-08-16 16:18:59 +00002887 TargetTypeIsPointer)));
Douglas Gregor55b037b2010-07-08 20:55:51 +00002888 }
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002889
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002890 Results.ExitScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002891
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002892}
2893
Douglas Gregorce0e8562010-08-23 21:54:33 +00002894static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2895 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00002896 typedef CodeCompletionResult Result;
Douglas Gregorce0e8562010-08-23 21:54:33 +00002897
2898 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002899
Douglas Gregorce0e8562010-08-23 21:54:33 +00002900 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2901 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2902 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2903 Results.AddResult(Result("__func__", CCP_Constant));
2904 Results.ExitScope();
2905}
2906
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00002907static void HandleCodeCompleteResults(Sema *S,
2908 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002909 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00002910 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002911 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002912 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002913 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002914}
2915
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002916static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2917 Sema::ParserCompletionContext PCC) {
2918 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00002919 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002920 return CodeCompletionContext::CCC_TopLevel;
2921
John McCallfaf5fb42010-08-26 23:41:50 +00002922 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002923 return CodeCompletionContext::CCC_ClassStructUnion;
2924
John McCallfaf5fb42010-08-26 23:41:50 +00002925 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002926 return CodeCompletionContext::CCC_ObjCInterface;
2927
John McCallfaf5fb42010-08-26 23:41:50 +00002928 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002929 return CodeCompletionContext::CCC_ObjCImplementation;
2930
John McCallfaf5fb42010-08-26 23:41:50 +00002931 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002932 return CodeCompletionContext::CCC_ObjCIvarList;
2933
John McCallfaf5fb42010-08-26 23:41:50 +00002934 case Sema::PCC_Template:
2935 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00002936 if (S.CurContext->isFileContext())
2937 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00002938 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00002939 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00002940 return CodeCompletionContext::CCC_Other;
Douglas Gregor0ac41382010-09-23 23:01:17 +00002941
John McCallfaf5fb42010-08-26 23:41:50 +00002942 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00002943 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00002944
John McCallfaf5fb42010-08-26 23:41:50 +00002945 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002946 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2947 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00002948 return CodeCompletionContext::CCC_ParenthesizedExpression;
2949 else
2950 return CodeCompletionContext::CCC_Expression;
2951
2952 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00002953 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002954 return CodeCompletionContext::CCC_Expression;
2955
John McCallfaf5fb42010-08-26 23:41:50 +00002956 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002957 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00002958
John McCallfaf5fb42010-08-26 23:41:50 +00002959 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00002960 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00002961
2962 case Sema::PCC_ParenthesizedExpression:
2963 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor80039242011-02-15 20:33:25 +00002964
2965 case Sema::PCC_LocalDeclarationSpecifiers:
2966 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002967 }
David Blaikie8a40f702012-01-17 06:56:22 +00002968
2969 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002970}
2971
Douglas Gregorac322ec2010-08-27 21:18:54 +00002972/// \brief If we're in a C++ virtual member function, add completion results
2973/// that invoke the functions we override, since it's common to invoke the
2974/// overridden function as well as adding new functionality.
2975///
2976/// \param S The semantic analysis object for which we are generating results.
2977///
2978/// \param InContext This context in which the nested-name-specifier preceding
2979/// the code-completion point
2980static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2981 ResultBuilder &Results) {
2982 // Look through blocks.
2983 DeclContext *CurContext = S.CurContext;
2984 while (isa<BlockDecl>(CurContext))
2985 CurContext = CurContext->getParent();
2986
2987
2988 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2989 if (!Method || !Method->isVirtual())
2990 return;
2991
2992 // We need to have names for all of the parameters, if we're going to
2993 // generate a forwarding call.
2994 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2995 PEnd = Method->param_end();
2996 P != PEnd;
2997 ++P) {
2998 if (!(*P)->getDeclName())
2999 return;
3000 }
3001
Douglas Gregor75acd922011-09-27 23:30:47 +00003002 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003003 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3004 MEnd = Method->end_overridden_methods();
3005 M != MEnd; ++M) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003006 CodeCompletionBuilder Builder(Results.getAllocator(),
3007 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003008 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3009 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3010 continue;
3011
3012 // If we need a nested-name-specifier, add one now.
3013 if (!InContext) {
3014 NestedNameSpecifier *NNS
3015 = getRequiredQualification(S.Context, CurContext,
3016 Overridden->getDeclContext());
3017 if (NNS) {
3018 std::string Str;
3019 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003020 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003021 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003022 }
3023 } else if (!InContext->Equals(Overridden->getDeclContext()))
3024 continue;
3025
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003026 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003027 Overridden->getNameAsString()));
3028 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003029 bool FirstParam = true;
3030 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3031 PEnd = Method->param_end();
3032 P != PEnd; ++P) {
3033 if (FirstParam)
3034 FirstParam = false;
3035 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003036 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003037
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003038 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003039 (*P)->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003040 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003041 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3042 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003043 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003044 CXCursor_CXXMethod,
3045 CXAvailability_Available,
3046 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003047 Results.Ignore(Overridden);
3048 }
3049}
3050
Douglas Gregor07f43572012-01-29 18:15:03 +00003051void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3052 ModuleIdPath Path) {
3053 typedef CodeCompletionResult Result;
3054 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003055 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003056 CodeCompletionContext::CCC_Other);
3057 Results.EnterNewScope();
3058
3059 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003060 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003061 typedef CodeCompletionResult Result;
3062 if (Path.empty()) {
3063 // Enumerate all top-level modules.
3064 llvm::SmallVector<Module *, 8> Modules;
3065 PP.getHeaderSearchInfo().collectAllModules(Modules);
3066 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3067 Builder.AddTypedTextChunk(
3068 Builder.getAllocator().CopyString(Modules[I]->Name));
3069 Results.AddResult(Result(Builder.TakeString(),
3070 CCP_Declaration,
3071 CXCursor_NotImplemented,
3072 Modules[I]->isAvailable()
3073 ? CXAvailability_Available
3074 : CXAvailability_NotAvailable));
3075 }
3076 } else {
3077 // Load the named module.
3078 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3079 Module::AllVisible,
3080 /*IsInclusionDirective=*/false);
3081 // Enumerate submodules.
3082 if (Mod) {
3083 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3084 SubEnd = Mod->submodule_end();
3085 Sub != SubEnd; ++Sub) {
3086
3087 Builder.AddTypedTextChunk(
3088 Builder.getAllocator().CopyString((*Sub)->Name));
3089 Results.AddResult(Result(Builder.TakeString(),
3090 CCP_Declaration,
3091 CXCursor_NotImplemented,
3092 (*Sub)->isAvailable()
3093 ? CXAvailability_Available
3094 : CXAvailability_NotAvailable));
3095 }
3096 }
3097 }
3098 Results.ExitScope();
3099 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3100 Results.data(),Results.size());
3101}
3102
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003103void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003104 ParserCompletionContext CompletionContext) {
John McCall276321a2010-08-25 06:19:51 +00003105 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003106 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003107 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003108 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003109 Results.EnterNewScope();
Douglas Gregor50832e02010-09-20 22:39:41 +00003110
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003111 // Determine how to filter results, e.g., so that the names of
3112 // values (functions, enumerators, function templates, etc.) are
3113 // only allowed where we can have an expression.
3114 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003115 case PCC_Namespace:
3116 case PCC_Class:
3117 case PCC_ObjCInterface:
3118 case PCC_ObjCImplementation:
3119 case PCC_ObjCInstanceVariableList:
3120 case PCC_Template:
3121 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003122 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003123 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003124 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3125 break;
3126
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003127 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003128 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003129 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003130 case PCC_ForInit:
3131 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003132 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003133 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3134 else
3135 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003136
David Blaikiebbafb8a2012-03-11 07:00:24 +00003137 if (getLangOpts().CPlusPlus)
Douglas Gregorac322ec2010-08-27 21:18:54 +00003138 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003139 break;
Douglas Gregor6da3db42010-05-25 05:58:43 +00003140
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003141 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003142 // Unfiltered
3143 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003144 }
3145
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003146 // If we are in a C++ non-static member function, check the qualifiers on
3147 // the member function to filter/prioritize the results list.
3148 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3149 if (CurMethod->isInstance())
3150 Results.setObjectTypeQualifiers(
3151 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3152
Douglas Gregorc580c522010-01-14 01:09:38 +00003153 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003154 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3155 CodeCompleter->includeGlobals());
Douglas Gregor92253692009-12-07 09:54:55 +00003156
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003157 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003158 Results.ExitScope();
3159
Douglas Gregorce0e8562010-08-23 21:54:33 +00003160 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003161 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003162 case PCC_Expression:
3163 case PCC_Statement:
3164 case PCC_RecoveryInFunction:
3165 if (S->getFnParent())
David Blaikiebbafb8a2012-03-11 07:00:24 +00003166 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003167 break;
3168
3169 case PCC_Namespace:
3170 case PCC_Class:
3171 case PCC_ObjCInterface:
3172 case PCC_ObjCImplementation:
3173 case PCC_ObjCInstanceVariableList:
3174 case PCC_Template:
3175 case PCC_MemberTemplate:
3176 case PCC_ForInit:
3177 case PCC_Condition:
3178 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003179 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003180 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003181 }
3182
Douglas Gregor9eb77012009-11-07 00:00:49 +00003183 if (CodeCompleter->includeMacros())
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003184 AddMacroResults(PP, Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003185
Douglas Gregor50832e02010-09-20 22:39:41 +00003186 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003187 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003188}
3189
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003190static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3191 ParsedType Receiver,
3192 IdentifierInfo **SelIdents,
3193 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003194 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003195 bool IsSuper,
3196 ResultBuilder &Results);
3197
3198void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3199 bool AllowNonIdentifiers,
3200 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003201 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003202 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003203 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003204 AllowNestedNameSpecifiers
3205 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3206 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003207 Results.EnterNewScope();
3208
3209 // Type qualifiers can come after names.
3210 Results.AddResult(Result("const"));
3211 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003212 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003213 Results.AddResult(Result("restrict"));
3214
David Blaikiebbafb8a2012-03-11 07:00:24 +00003215 if (getLangOpts().CPlusPlus) {
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003216 if (AllowNonIdentifiers) {
3217 Results.AddResult(Result("operator"));
3218 }
3219
3220 // Add nested-name-specifiers.
3221 if (AllowNestedNameSpecifiers) {
3222 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003223 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003224 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3225 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3226 CodeCompleter->includeGlobals());
Douglas Gregor0ac41382010-09-23 23:01:17 +00003227 Results.setFilter(0);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003228 }
3229 }
3230 Results.ExitScope();
3231
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003232 // If we're in a context where we might have an expression (rather than a
3233 // declaration), and what we've seen so far is an Objective-C type that could
3234 // be a receiver of a class message, this may be a class message send with
3235 // the initial opening bracket '[' missing. Add appropriate completions.
3236 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3237 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3238 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3239 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3240 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3241 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3242 DS.getTypeQualifiers() == 0 &&
3243 S &&
3244 (S->getFlags() & Scope::DeclScope) != 0 &&
3245 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3246 Scope::FunctionPrototypeScope |
3247 Scope::AtCatchScope)) == 0) {
3248 ParsedType T = DS.getRepAsType();
3249 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003250 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003251 }
3252
Douglas Gregor56ccce02010-08-24 04:59:56 +00003253 // Note that we intentionally suppress macro results here, since we do not
3254 // encourage using macros to produce the names of entities.
3255
Douglas Gregor0ac41382010-09-23 23:01:17 +00003256 HandleCodeCompleteResults(this, CodeCompleter,
3257 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003258 Results.data(), Results.size());
3259}
3260
Douglas Gregor68762e72010-08-23 21:17:50 +00003261struct Sema::CodeCompleteExpressionData {
3262 CodeCompleteExpressionData(QualType PreferredType = QualType())
3263 : PreferredType(PreferredType), IntegralConstantExpression(false),
3264 ObjCCollection(false) { }
3265
3266 QualType PreferredType;
3267 bool IntegralConstantExpression;
3268 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003269 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003270};
3271
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003272/// \brief Perform code-completion in an expression context when we know what
3273/// type we're looking for.
Douglas Gregor85b50632010-07-28 21:50:18 +00003274///
3275/// \param IntegralConstantExpression Only permit integral constant
3276/// expressions.
Douglas Gregor68762e72010-08-23 21:17:50 +00003277void Sema::CodeCompleteExpression(Scope *S,
3278 const CodeCompleteExpressionData &Data) {
John McCall276321a2010-08-25 06:19:51 +00003279 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003280 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003281 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003282 CodeCompletionContext::CCC_Expression);
Douglas Gregor68762e72010-08-23 21:17:50 +00003283 if (Data.ObjCCollection)
3284 Results.setFilter(&ResultBuilder::IsObjCCollection);
3285 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003286 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003287 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003288 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3289 else
3290 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003291
3292 if (!Data.PreferredType.isNull())
3293 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3294
3295 // Ignore any declarations that we were told that we don't care about.
3296 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3297 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003298
3299 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003300 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3301 CodeCompleter->includeGlobals());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003302
3303 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003304 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003305 Results.ExitScope();
3306
Douglas Gregor55b037b2010-07-08 20:55:51 +00003307 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003308 if (!Data.PreferredType.isNull())
3309 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3310 || Data.PreferredType->isMemberPointerType()
3311 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003312
Douglas Gregorce0e8562010-08-23 21:54:33 +00003313 if (S->getFnParent() &&
3314 !Data.ObjCCollection &&
3315 !Data.IntegralConstantExpression)
David Blaikiebbafb8a2012-03-11 07:00:24 +00003316 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003317
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003318 if (CodeCompleter->includeMacros())
Douglas Gregor55b037b2010-07-08 20:55:51 +00003319 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003320 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor68762e72010-08-23 21:17:50 +00003321 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3322 Data.PreferredType),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003323 Results.data(),Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003324}
3325
Douglas Gregoreda7e542010-09-18 01:28:11 +00003326void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3327 if (E.isInvalid())
3328 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003329 else if (getLangOpts().ObjC1)
Douglas Gregoreda7e542010-09-18 01:28:11 +00003330 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003331}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003332
Douglas Gregorb888acf2010-12-09 23:01:55 +00003333/// \brief The set of properties that have already been added, referenced by
3334/// property name.
3335typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3336
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003337/// \brief Retrieve the container definition, if any?
3338static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3339 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3340 if (Interface->hasDefinition())
3341 return Interface->getDefinition();
3342
3343 return Interface;
3344 }
3345
3346 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3347 if (Protocol->hasDefinition())
3348 return Protocol->getDefinition();
3349
3350 return Protocol;
3351 }
3352 return Container;
3353}
3354
3355static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor5d649882009-11-18 22:32:06 +00003356 bool AllowCategories,
Douglas Gregor95147142011-05-05 15:50:42 +00003357 bool AllowNullaryMethods,
Douglas Gregor9291bad2009-11-18 01:29:26 +00003358 DeclContext *CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003359 AddedPropertiesSet &AddedProperties,
Douglas Gregor9291bad2009-11-18 01:29:26 +00003360 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003361 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003362
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003363 // Retrieve the definition.
3364 Container = getContainerDef(Container);
3365
Douglas Gregor9291bad2009-11-18 01:29:26 +00003366 // Add properties in this container.
3367 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3368 PEnd = Container->prop_end();
3369 P != PEnd;
Douglas Gregorb888acf2010-12-09 23:01:55 +00003370 ++P) {
3371 if (AddedProperties.insert(P->getIdentifier()))
David Blaikie40ed2972012-06-06 20:45:41 +00003372 Results.MaybeAddResult(Result(*P, 0), CurContext);
Douglas Gregorb888acf2010-12-09 23:01:55 +00003373 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003374
Douglas Gregor95147142011-05-05 15:50:42 +00003375 // Add nullary methods
3376 if (AllowNullaryMethods) {
3377 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003378 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor95147142011-05-05 15:50:42 +00003379 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3380 MEnd = Container->meth_end();
3381 M != MEnd; ++M) {
3382 if (M->getSelector().isUnarySelector())
3383 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3384 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003385 CodeCompletionBuilder Builder(Results.getAllocator(),
3386 Results.getCodeCompletionTUInfo());
David Blaikie40ed2972012-06-06 20:45:41 +00003387 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor95147142011-05-05 15:50:42 +00003388 Builder.AddTypedTextChunk(
3389 Results.getAllocator().CopyString(Name->getName()));
3390
David Blaikie40ed2972012-06-06 20:45:41 +00003391 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregor78254c82012-03-27 23:34:16 +00003392 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor95147142011-05-05 15:50:42 +00003393 CurContext);
3394 }
3395 }
3396 }
3397
3398
Douglas Gregor9291bad2009-11-18 01:29:26 +00003399 // Add properties in referenced protocols.
3400 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3401 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3402 PEnd = Protocol->protocol_end();
3403 P != PEnd; ++P)
Douglas Gregor95147142011-05-05 15:50:42 +00003404 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3405 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003406 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003407 if (AllowCategories) {
3408 // Look through categories.
3409 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3410 Category; Category = Category->getNextClassCategory())
Douglas Gregor95147142011-05-05 15:50:42 +00003411 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3412 CurContext, AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00003413 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003414
3415 // Look through protocols.
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003416 for (ObjCInterfaceDecl::all_protocol_iterator
3417 I = IFace->all_referenced_protocol_begin(),
3418 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor95147142011-05-05 15:50:42 +00003419 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3420 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003421
3422 // Look in the superclass.
3423 if (IFace->getSuperClass())
Douglas Gregor95147142011-05-05 15:50:42 +00003424 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3425 AllowNullaryMethods, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003426 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003427 } else if (const ObjCCategoryDecl *Category
3428 = dyn_cast<ObjCCategoryDecl>(Container)) {
3429 // Look through protocols.
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003430 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3431 PEnd = Category->protocol_end();
Douglas Gregor9291bad2009-11-18 01:29:26 +00003432 P != PEnd; ++P)
Douglas Gregor95147142011-05-05 15:50:42 +00003433 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3434 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003435 }
3436}
3437
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003438void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor2436e712009-09-17 21:32:03 +00003439 SourceLocation OpLoc,
3440 bool IsArrow) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003441 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00003442 return;
3443
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003444 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3445 if (ConvertedBase.isInvalid())
3446 return;
3447 Base = ConvertedBase.get();
3448
John McCall276321a2010-08-25 06:19:51 +00003449 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003450
Douglas Gregor2436e712009-09-17 21:32:03 +00003451 QualType BaseType = Base->getType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003452
3453 if (IsArrow) {
3454 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3455 BaseType = Ptr->getPointeeType();
3456 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003457 /*Do nothing*/ ;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003458 else
3459 return;
3460 }
3461
Douglas Gregor21325842011-07-07 16:03:39 +00003462 enum CodeCompletionContext::Kind contextKind;
3463
3464 if (IsArrow) {
3465 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3466 }
3467 else {
3468 if (BaseType->isObjCObjectPointerType() ||
3469 BaseType->isObjCObjectOrInterfaceType()) {
3470 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3471 }
3472 else {
3473 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3474 }
3475 }
3476
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003477 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003478 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00003479 CodeCompletionContext(contextKind,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003480 BaseType),
3481 &ResultBuilder::IsMember);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003482 Results.EnterNewScope();
3483 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003484 // Indicate that we are performing a member access, and the cv-qualifiers
3485 // for the base object type.
3486 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3487
Douglas Gregor9291bad2009-11-18 01:29:26 +00003488 // Access to a C/C++ class, struct, or union.
Douglas Gregor6ae4c522010-01-14 03:21:49 +00003489 Results.allowNestedNameSpecifiers();
Douglas Gregor09bbc652010-01-14 15:47:35 +00003490 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003491 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3492 CodeCompleter->includeGlobals());
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003493
David Blaikiebbafb8a2012-03-11 07:00:24 +00003494 if (getLangOpts().CPlusPlus) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003495 if (!Results.empty()) {
3496 // The "template" keyword can follow "->" or "." in the grammar.
3497 // However, we only want to suggest the template keyword if something
3498 // is dependent.
3499 bool IsDependent = BaseType->isDependentType();
3500 if (!IsDependent) {
3501 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3502 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3503 IsDependent = Ctx->isDependentContext();
3504 break;
3505 }
3506 }
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003507
Douglas Gregor9291bad2009-11-18 01:29:26 +00003508 if (IsDependent)
Douglas Gregor78a21012010-01-14 16:01:26 +00003509 Results.AddResult(Result("template"));
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003510 }
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003511 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003512 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3513 // Objective-C property reference.
Douglas Gregorb888acf2010-12-09 23:01:55 +00003514 AddedPropertiesSet AddedProperties;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003515
3516 // Add property results based on our interface.
3517 const ObjCObjectPointerType *ObjCPtr
3518 = BaseType->getAsObjCInterfacePointerType();
3519 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor95147142011-05-05 15:50:42 +00003520 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3521 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003522 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003523
3524 // Add properties from the protocols in a qualified interface.
3525 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3526 E = ObjCPtr->qual_end();
3527 I != E; ++I)
Douglas Gregor95147142011-05-05 15:50:42 +00003528 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3529 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003530 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCall8b07ec22010-05-15 11:32:37 +00003531 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003532 // Objective-C instance variable access.
3533 ObjCInterfaceDecl *Class = 0;
3534 if (const ObjCObjectPointerType *ObjCPtr
3535 = BaseType->getAs<ObjCObjectPointerType>())
3536 Class = ObjCPtr->getInterfaceDecl();
3537 else
John McCall8b07ec22010-05-15 11:32:37 +00003538 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor9291bad2009-11-18 01:29:26 +00003539
3540 // Add all ivars from this class and its superclasses.
Douglas Gregor2b8162b2010-01-14 16:08:12 +00003541 if (Class) {
3542 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3543 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor39982192010-08-15 06:18:01 +00003544 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3545 CodeCompleter->includeGlobals());
Douglas Gregor9291bad2009-11-18 01:29:26 +00003546 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003547 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003548
3549 // FIXME: How do we cope with isa?
3550
3551 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003552
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003553 // Hand off the results found for code completion.
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003554 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003555 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003556 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00003557}
3558
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003559void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3560 if (!CodeCompleter)
3561 return;
3562
John McCall276321a2010-08-25 06:19:51 +00003563 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003564 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003565 enum CodeCompletionContext::Kind ContextKind
3566 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003567 switch ((DeclSpec::TST)TagSpec) {
3568 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003569 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003570 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003571 break;
3572
3573 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003574 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003575 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003576 break;
3577
3578 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003579 case DeclSpec::TST_class:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003580 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003581 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003582 break;
3583
3584 default:
David Blaikie83d382b2011-09-23 05:06:16 +00003585 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003586 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003587
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003588 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3589 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00003590 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00003591
3592 // First pass: look for tags.
3593 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00003594 LookupVisibleDecls(S, LookupTagName, Consumer,
3595 CodeCompleter->includeGlobals());
John McCalle87beb22010-04-23 18:46:30 +00003596
Douglas Gregor39982192010-08-15 06:18:01 +00003597 if (CodeCompleter->includeGlobals()) {
3598 // Second pass: look for nested name specifiers.
3599 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3600 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3601 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003602
Douglas Gregor0ac41382010-09-23 23:01:17 +00003603 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003604 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003605}
3606
Douglas Gregor28c78432010-08-27 17:35:51 +00003607void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003608 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003609 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003610 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00003611 Results.EnterNewScope();
3612 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3613 Results.AddResult("const");
3614 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3615 Results.AddResult("volatile");
David Blaikiebbafb8a2012-03-11 07:00:24 +00003616 if (getLangOpts().C99 &&
Douglas Gregor28c78432010-08-27 17:35:51 +00003617 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3618 Results.AddResult("restrict");
3619 Results.ExitScope();
3620 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003621 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00003622 Results.data(), Results.size());
3623}
3624
Douglas Gregord328d572009-09-21 18:10:23 +00003625void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00003626 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00003627 return;
John McCall5939b162011-08-06 07:30:58 +00003628
John McCallaab3e412010-08-25 08:40:02 +00003629 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00003630 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3631 if (!type->isEnumeralType()) {
3632 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00003633 Data.IntegralConstantExpression = true;
3634 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00003635 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00003636 }
Douglas Gregord328d572009-09-21 18:10:23 +00003637
3638 // Code-complete the cases of a switch statement over an enumeration type
3639 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00003640 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003641 if (EnumDecl *Def = Enum->getDefinition())
3642 Enum = Def;
Douglas Gregord328d572009-09-21 18:10:23 +00003643
3644 // Determine which enumerators we have already seen in the switch statement.
3645 // FIXME: Ideally, we would also be able to look *past* the code-completion
3646 // token, in case we are code-completing in the middle of the switch and not
3647 // at the end. However, we aren't able to do so at the moment.
3648 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorf2510672009-09-21 19:57:38 +00003649 NestedNameSpecifier *Qualifier = 0;
Douglas Gregord328d572009-09-21 18:10:23 +00003650 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3651 SC = SC->getNextSwitchCase()) {
3652 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3653 if (!Case)
3654 continue;
3655
3656 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3657 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3658 if (EnumConstantDecl *Enumerator
3659 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3660 // We look into the AST of the case statement to determine which
3661 // enumerator was named. Alternatively, we could compute the value of
3662 // the integral constant expression, then compare it against the
3663 // values of each enumerator. However, value-based approach would not
3664 // work as well with C++ templates where enumerators declared within a
3665 // template are type- and value-dependent.
3666 EnumeratorsSeen.insert(Enumerator);
3667
Douglas Gregorf2510672009-09-21 19:57:38 +00003668 // If this is a qualified-id, keep track of the nested-name-specifier
3669 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00003670 //
3671 // switch (TagD.getKind()) {
3672 // case TagDecl::TK_enum:
3673 // break;
3674 // case XXX
3675 //
Douglas Gregorf2510672009-09-21 19:57:38 +00003676 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00003677 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3678 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00003679 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00003680 }
3681 }
3682
David Blaikiebbafb8a2012-03-11 07:00:24 +00003683 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorf2510672009-09-21 19:57:38 +00003684 // If there are no prior enumerators in C++, check whether we have to
3685 // qualify the names of the enumerators that we suggest, because they
3686 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00003687 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00003688 }
3689
Douglas Gregord328d572009-09-21 18:10:23 +00003690 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003691 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003692 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003693 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00003694 Results.EnterNewScope();
3695 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3696 EEnd = Enum->enumerator_end();
3697 E != EEnd; ++E) {
David Blaikie40ed2972012-06-06 20:45:41 +00003698 if (EnumeratorsSeen.count(*E))
Douglas Gregord328d572009-09-21 18:10:23 +00003699 continue;
3700
David Blaikie40ed2972012-06-06 20:45:41 +00003701 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor3a69eaf2011-02-18 23:30:37 +00003702 R.Priority = CCP_EnumInCase;
3703 Results.AddResult(R, CurContext, 0, false);
Douglas Gregord328d572009-09-21 18:10:23 +00003704 }
3705 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00003706
Douglas Gregor21325842011-07-07 16:03:39 +00003707 //We need to make sure we're setting the right context,
3708 //so only say we include macros if the code completer says we do
3709 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3710 if (CodeCompleter->includeMacros()) {
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003711 AddMacroResults(PP, Results);
Douglas Gregor21325842011-07-07 16:03:39 +00003712 kind = CodeCompletionContext::CCC_OtherWithMacros;
3713 }
3714
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003715 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00003716 kind,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003717 Results.data(),Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00003718}
3719
Douglas Gregorcabea402009-09-22 15:41:20 +00003720namespace {
3721 struct IsBetterOverloadCandidate {
3722 Sema &S;
John McCallbc077cf2010-02-08 23:07:23 +00003723 SourceLocation Loc;
Douglas Gregorcabea402009-09-22 15:41:20 +00003724
3725 public:
John McCallbc077cf2010-02-08 23:07:23 +00003726 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3727 : S(S), Loc(Loc) { }
Douglas Gregorcabea402009-09-22 15:41:20 +00003728
3729 bool
3730 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall5c32be02010-08-24 20:38:10 +00003731 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregorcabea402009-09-22 15:41:20 +00003732 }
3733 };
3734}
3735
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003736static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3737 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003738 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003739
3740 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003741 if (!Args[I])
3742 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003743
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003744 return false;
3745}
3746
Richard Trieu2bd04012011-09-09 02:00:50 +00003747void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003748 llvm::ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00003749 if (!CodeCompleter)
3750 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003751
3752 // When we're code-completing for a call, we fall back to ordinary
3753 // name code-completion whenever we can't produce specific
3754 // results. We may want to revisit this strategy in the future,
3755 // e.g., by merging the two kinds of results.
3756
Douglas Gregorcabea402009-09-22 15:41:20 +00003757 Expr *Fn = (Expr *)FnIn;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003758
Douglas Gregorcabea402009-09-22 15:41:20 +00003759 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003760 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3761 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003762 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00003763 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003764 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003765
John McCall57500772009-12-16 12:17:52 +00003766 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00003767 SourceLocation Loc = Fn->getExprLoc();
3768 OverloadCandidateSet CandidateSet(Loc);
John McCall57500772009-12-16 12:17:52 +00003769
Douglas Gregorcabea402009-09-22 15:41:20 +00003770 // FIXME: What if we're calling something that isn't a function declaration?
3771 // FIXME: What if we're calling a pseudo-destructor?
3772 // FIXME: What if we're calling a member function?
3773
Douglas Gregorff59f672010-01-21 15:46:19 +00003774 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003775 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00003776
John McCall57500772009-12-16 12:17:52 +00003777 Expr *NakedFn = Fn->IgnoreParenCasts();
3778 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003779 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall57500772009-12-16 12:17:52 +00003780 /*PartialOverloading=*/ true);
3781 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3782 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorff59f672010-01-21 15:46:19 +00003783 if (FDecl) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00003784 if (!getLangOpts().CPlusPlus ||
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003785 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorff59f672010-01-21 15:46:19 +00003786 Results.push_back(ResultCandidate(FDecl));
3787 else
John McCallb89836b2010-01-26 01:37:31 +00003788 // FIXME: access?
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003789 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3790 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorff59f672010-01-21 15:46:19 +00003791 }
John McCall57500772009-12-16 12:17:52 +00003792 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003793
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003794 QualType ParamType;
3795
Douglas Gregorff59f672010-01-21 15:46:19 +00003796 if (!CandidateSet.empty()) {
3797 // Sort the overload candidate set by placing the best overloads first.
3798 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCallbc077cf2010-02-08 23:07:23 +00003799 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregorcabea402009-09-22 15:41:20 +00003800
Douglas Gregorff59f672010-01-21 15:46:19 +00003801 // Add the remaining viable overload candidates as code-completion reslults.
3802 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3803 CandEnd = CandidateSet.end();
3804 Cand != CandEnd; ++Cand) {
3805 if (Cand->Viable)
3806 Results.push_back(ResultCandidate(Cand->Function));
3807 }
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003808
3809 // From the viable candidates, try to determine the type of this parameter.
3810 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3811 if (const FunctionType *FType = Results[I].getFunctionType())
3812 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003813 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003814 if (ParamType.isNull())
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003815 ParamType = Proto->getArgType(Args.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003816 else if (!Context.hasSameUnqualifiedType(
3817 ParamType.getNonReferenceType(),
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003818 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003819 ParamType = QualType();
3820 break;
3821 }
3822 }
3823 }
3824 } else {
3825 // Try to determine the parameter type from the type of the expression
3826 // being called.
3827 QualType FunctionType = Fn->getType();
3828 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3829 FunctionType = Ptr->getPointeeType();
3830 else if (const BlockPointerType *BlockPtr
3831 = FunctionType->getAs<BlockPointerType>())
3832 FunctionType = BlockPtr->getPointeeType();
3833 else if (const MemberPointerType *MemPtr
3834 = FunctionType->getAs<MemberPointerType>())
3835 FunctionType = MemPtr->getPointeeType();
3836
3837 if (const FunctionProtoType *Proto
3838 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003839 if (Args.size() < Proto->getNumArgs())
3840 ParamType = Proto->getArgType(Args.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003841 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003842 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00003843
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003844 if (ParamType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003845 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003846 else
3847 CodeCompleteExpression(S, ParamType);
3848
Douglas Gregorc01890e2010-04-06 20:19:47 +00003849 if (!Results.empty())
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003850 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregor3ef59522009-12-11 19:06:04 +00003851 Results.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00003852}
3853
John McCall48871652010-08-21 09:40:31 +00003854void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3855 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003856 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003857 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003858 return;
3859 }
3860
3861 CodeCompleteExpression(S, VD->getType());
3862}
3863
3864void Sema::CodeCompleteReturn(Scope *S) {
3865 QualType ResultType;
3866 if (isa<BlockDecl>(CurContext)) {
3867 if (BlockScopeInfo *BSI = getCurBlock())
3868 ResultType = BSI->ReturnType;
3869 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3870 ResultType = Function->getResultType();
3871 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3872 ResultType = Method->getResultType();
3873
3874 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003875 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003876 else
3877 CodeCompleteExpression(S, ResultType);
3878}
3879
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003880void Sema::CodeCompleteAfterIf(Scope *S) {
3881 typedef CodeCompletionResult Result;
3882 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003883 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003884 mapCodeCompletionContext(*this, PCC_Statement));
3885 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3886 Results.EnterNewScope();
3887
3888 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3889 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3890 CodeCompleter->includeGlobals());
3891
3892 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3893
3894 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003895 CodeCompletionBuilder Builder(Results.getAllocator(),
3896 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003897 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00003898 if (Results.includeCodePatterns()) {
3899 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3900 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3901 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3902 Builder.AddPlaceholderChunk("statements");
3903 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3904 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3905 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003906 Results.AddResult(Builder.TakeString());
3907
3908 // "else if" block
3909 Builder.AddTypedTextChunk("else");
3910 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3911 Builder.AddTextChunk("if");
3912 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3913 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003914 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003915 Builder.AddPlaceholderChunk("condition");
3916 else
3917 Builder.AddPlaceholderChunk("expression");
3918 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00003919 if (Results.includeCodePatterns()) {
3920 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3921 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3922 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3923 Builder.AddPlaceholderChunk("statements");
3924 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3925 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3926 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003927 Results.AddResult(Builder.TakeString());
3928
3929 Results.ExitScope();
3930
3931 if (S->getFnParent())
David Blaikiebbafb8a2012-03-11 07:00:24 +00003932 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003933
3934 if (CodeCompleter->includeMacros())
3935 AddMacroResults(PP, Results);
3936
3937 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3938 Results.data(),Results.size());
3939}
3940
Richard Trieu2bd04012011-09-09 02:00:50 +00003941void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003942 if (LHS)
3943 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3944 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003945 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003946}
3947
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00003948void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00003949 bool EnteringContext) {
3950 if (!SS.getScopeRep() || !CodeCompleter)
3951 return;
3952
Douglas Gregor3545ff42009-09-21 16:56:56 +00003953 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3954 if (!Ctx)
3955 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00003956
3957 // Try to instantiate any non-dependent declaration contexts before
3958 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00003959 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00003960 return;
3961
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003962 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003963 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003964 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003965 Results.EnterNewScope();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003966
Douglas Gregor3545ff42009-09-21 16:56:56 +00003967 // The "template" keyword can follow "::" in the grammar, but only
3968 // put it into the grammar if the nested-name-specifier is dependent.
3969 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3970 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00003971 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00003972
3973 // Add calls to overridden virtual functions, if there are any.
3974 //
3975 // FIXME: This isn't wonderful, because we don't know whether we're actually
3976 // in a context that permits expressions. This is a general issue with
3977 // qualified-id completions.
3978 if (!EnteringContext)
3979 MaybeAddOverrideCalls(*this, Ctx, Results);
3980 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003981
Douglas Gregorac322ec2010-08-27 21:18:54 +00003982 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3983 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3984
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003985 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorc1679ec2011-07-25 17:48:11 +00003986 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003987 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00003988}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00003989
3990void Sema::CodeCompleteUsing(Scope *S) {
3991 if (!CodeCompleter)
3992 return;
3993
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003994 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003995 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003996 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3997 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00003998 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003999
4000 // If we aren't in class scope, we could see the "namespace" keyword.
4001 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004002 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004003
4004 // After "using", we can see anything that would start a
4005 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004006 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004007 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4008 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004009 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004010
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004011 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004012 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004013 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004014}
4015
4016void Sema::CodeCompleteUsingDirective(Scope *S) {
4017 if (!CodeCompleter)
4018 return;
4019
Douglas Gregor3545ff42009-09-21 16:56:56 +00004020 // After "using namespace", we expect to see a namespace name or namespace
4021 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004022 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004023 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004024 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004025 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004026 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004027 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004028 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4029 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004030 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004031 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004032 CodeCompletionContext::CCC_Namespace,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004033 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004034}
4035
4036void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4037 if (!CodeCompleter)
4038 return;
4039
Douglas Gregor3545ff42009-09-21 16:56:56 +00004040 DeclContext *Ctx = (DeclContext *)S->getEntity();
4041 if (!S->getParent())
4042 Ctx = Context.getTranslationUnitDecl();
4043
Douglas Gregor0ac41382010-09-23 23:01:17 +00004044 bool SuppressedGlobalResults
4045 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4046
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004047 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004048 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004049 SuppressedGlobalResults
4050 ? CodeCompletionContext::CCC_Namespace
4051 : CodeCompletionContext::CCC_Other,
4052 &ResultBuilder::IsNamespace);
4053
4054 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004055 // We only want to see those namespaces that have already been defined
4056 // within this scope, because its likely that the user is creating an
4057 // extended namespace declaration. Keep track of the most recent
4058 // definition of each namespace.
4059 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4060 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4061 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4062 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00004063 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004064
4065 // Add the most recent definition (or extended definition) of each
4066 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004067 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004068 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004069 NS = OrigToLatest.begin(),
4070 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004071 NS != NSEnd; ++NS)
John McCall276321a2010-08-25 06:19:51 +00004072 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregorfc59ce12010-01-14 16:14:35 +00004073 CurContext, 0, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004074 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004075 }
4076
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004077 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004078 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004079 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004080}
4081
4082void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4083 if (!CodeCompleter)
4084 return;
4085
Douglas Gregor3545ff42009-09-21 16:56:56 +00004086 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004087 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004088 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004089 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004090 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004091 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004092 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4093 CodeCompleter->includeGlobals());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004094 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004095 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004096 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004097}
4098
Douglas Gregorc811ede2009-09-18 20:05:18 +00004099void Sema::CodeCompleteOperatorName(Scope *S) {
4100 if (!CodeCompleter)
4101 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004102
John McCall276321a2010-08-25 06:19:51 +00004103 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004104 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004105 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004106 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004107 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004108 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004109
Douglas Gregor3545ff42009-09-21 16:56:56 +00004110 // Add the names of overloadable operators.
4111#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4112 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004113 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004114#include "clang/Basic/OperatorKinds.def"
4115
4116 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004117 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004118 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004119 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4120 CodeCompleter->includeGlobals());
Douglas Gregor3545ff42009-09-21 16:56:56 +00004121
4122 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004123 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004124 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004125
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004126 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004127 CodeCompletionContext::CCC_Type,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004128 Results.data(),Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004129}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004130
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004131void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Alexis Hunt1d792652011-01-08 20:30:50 +00004132 CXXCtorInitializer** Initializers,
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004133 unsigned NumInitializers) {
Douglas Gregor75acd922011-09-27 23:30:47 +00004134 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004135 CXXConstructorDecl *Constructor
4136 = static_cast<CXXConstructorDecl *>(ConstructorD);
4137 if (!Constructor)
4138 return;
4139
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004140 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004141 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004142 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004143 Results.EnterNewScope();
4144
4145 // Fill in any already-initialized fields or base classes.
4146 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4147 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4148 for (unsigned I = 0; I != NumInitializers; ++I) {
4149 if (Initializers[I]->isBaseInitializer())
4150 InitializedBases.insert(
4151 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4152 else
Francois Pichetd583da02010-12-04 09:14:42 +00004153 InitializedFields.insert(cast<FieldDecl>(
4154 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004155 }
4156
4157 // Add completions for base classes.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004158 CodeCompletionBuilder Builder(Results.getAllocator(),
4159 Results.getCodeCompletionTUInfo());
Douglas Gregor99129ef2010-08-29 19:27:27 +00004160 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004161 CXXRecordDecl *ClassDecl = Constructor->getParent();
4162 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4163 BaseEnd = ClassDecl->bases_end();
4164 Base != BaseEnd; ++Base) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004165 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4166 SawLastInitializer
4167 = NumInitializers > 0 &&
4168 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4169 Context.hasSameUnqualifiedType(Base->getType(),
4170 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004171 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004172 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004173
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004174 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004175 Results.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00004176 Base->getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004177 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4178 Builder.AddPlaceholderChunk("args");
4179 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4180 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004181 SawLastInitializer? CCP_NextInitializer
4182 : CCP_MemberDeclaration));
4183 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004184 }
4185
4186 // Add completions for virtual base classes.
4187 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4188 BaseEnd = ClassDecl->vbases_end();
4189 Base != BaseEnd; ++Base) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004190 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4191 SawLastInitializer
4192 = NumInitializers > 0 &&
4193 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4194 Context.hasSameUnqualifiedType(Base->getType(),
4195 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004196 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004197 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004198
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004199 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004200 Builder.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00004201 Base->getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004202 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4203 Builder.AddPlaceholderChunk("args");
4204 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4205 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004206 SawLastInitializer? CCP_NextInitializer
4207 : CCP_MemberDeclaration));
4208 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004209 }
4210
4211 // Add completions for members.
4212 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4213 FieldEnd = ClassDecl->field_end();
4214 Field != FieldEnd; ++Field) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004215 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4216 SawLastInitializer
4217 = NumInitializers > 0 &&
Francois Pichetd583da02010-12-04 09:14:42 +00004218 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie40ed2972012-06-06 20:45:41 +00004219 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004220 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004221 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004222
4223 if (!Field->getDeclName())
4224 continue;
4225
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004226 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004227 Field->getIdentifier()->getName()));
4228 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4229 Builder.AddPlaceholderChunk("args");
4230 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4231 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004232 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00004233 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00004234 CXCursor_MemberRef,
4235 CXAvailability_Available,
David Blaikie40ed2972012-06-06 20:45:41 +00004236 *Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00004237 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004238 }
4239 Results.ExitScope();
4240
Douglas Gregor0ac41382010-09-23 23:01:17 +00004241 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004242 Results.data(), Results.size());
4243}
4244
Douglas Gregord8c61782012-02-15 15:34:24 +00004245/// \brief Determine whether this scope denotes a namespace.
4246static bool isNamespaceScope(Scope *S) {
4247 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4248 if (!DC)
4249 return false;
4250
4251 return DC->isFileContext();
4252}
4253
4254void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4255 bool AfterAmpersand) {
4256 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004257 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00004258 CodeCompletionContext::CCC_Other);
4259 Results.EnterNewScope();
4260
4261 // Note what has already been captured.
4262 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4263 bool IncludedThis = false;
4264 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4265 CEnd = Intro.Captures.end();
4266 C != CEnd; ++C) {
4267 if (C->Kind == LCK_This) {
4268 IncludedThis = true;
4269 continue;
4270 }
4271
4272 Known.insert(C->Id);
4273 }
4274
4275 // Look for other capturable variables.
4276 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4277 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4278 D != DEnd; ++D) {
4279 VarDecl *Var = dyn_cast<VarDecl>(*D);
4280 if (!Var ||
4281 !Var->hasLocalStorage() ||
4282 Var->hasAttr<BlocksAttr>())
4283 continue;
4284
4285 if (Known.insert(Var->getIdentifier()))
4286 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4287 }
4288 }
4289
4290 // Add 'this', if it would be valid.
4291 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4292 addThisCompletion(*this, Results);
4293
4294 Results.ExitScope();
4295
4296 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4297 Results.data(), Results.size());
4298}
4299
James Dennett596e4752012-06-14 03:11:41 +00004300/// Macro that optionally prepends an "@" to the string literal passed in via
4301/// Keyword, depending on whether NeedAt is true or false.
4302#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4303
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004304static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004305 ResultBuilder &Results,
4306 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004307 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004308 // Since we have an implementation, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00004309 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004310
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004311 CodeCompletionBuilder Builder(Results.getAllocator(),
4312 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004313 if (LangOpts.ObjC2) {
4314 // @dynamic
James Dennett596e4752012-06-14 03:11:41 +00004315 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004316 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4317 Builder.AddPlaceholderChunk("property");
4318 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004319
4320 // @synthesize
James Dennett596e4752012-06-14 03:11:41 +00004321 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004322 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4323 Builder.AddPlaceholderChunk("property");
4324 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004325 }
4326}
4327
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004328static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004329 ResultBuilder &Results,
4330 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004331 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004332
4333 // Since we have an interface or protocol, we can end it.
James Dennett596e4752012-06-14 03:11:41 +00004334 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004335
4336 if (LangOpts.ObjC2) {
4337 // @property
James Dennett596e4752012-06-14 03:11:41 +00004338 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004339
4340 // @required
James Dennett596e4752012-06-14 03:11:41 +00004341 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004342
4343 // @optional
James Dennett596e4752012-06-14 03:11:41 +00004344 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00004345 }
4346}
4347
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004348static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004349 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004350 CodeCompletionBuilder Builder(Results.getAllocator(),
4351 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004352
4353 // @class name ;
James Dennett596e4752012-06-14 03:11:41 +00004354 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004355 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4356 Builder.AddPlaceholderChunk("name");
4357 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004358
Douglas Gregorf4c33342010-05-28 00:22:41 +00004359 if (Results.includeCodePatterns()) {
4360 // @interface name
4361 // FIXME: Could introduce the whole pattern, including superclasses and
4362 // such.
James Dennett596e4752012-06-14 03:11:41 +00004363 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004364 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4365 Builder.AddPlaceholderChunk("class");
4366 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004367
Douglas Gregorf4c33342010-05-28 00:22:41 +00004368 // @protocol name
James Dennett596e4752012-06-14 03:11:41 +00004369 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004370 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4371 Builder.AddPlaceholderChunk("protocol");
4372 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004373
4374 // @implementation name
James Dennett596e4752012-06-14 03:11:41 +00004375 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004376 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4377 Builder.AddPlaceholderChunk("class");
4378 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004379 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004380
4381 // @compatibility_alias name
James Dennett596e4752012-06-14 03:11:41 +00004382 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004383 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4384 Builder.AddPlaceholderChunk("alias");
4385 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4386 Builder.AddPlaceholderChunk("class");
4387 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004388}
4389
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004390void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00004391 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004392 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004393 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004394 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00004395 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004396 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00004397 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004398 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00004399 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00004400 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004401 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00004402 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004403 HandleCodeCompleteResults(this, CodeCompleter,
4404 CodeCompletionContext::CCC_Other,
4405 Results.data(),Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00004406}
4407
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004408static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004409 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004410 CodeCompletionBuilder Builder(Results.getAllocator(),
4411 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004412
4413 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004414 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00004415 if (Results.getSema().getLangOpts().CPlusPlus ||
4416 Results.getSema().getLangOpts().ConstStrings)
Douglas Gregore5c79d52011-10-18 21:20:17 +00004417 EncodeType = " const char[]";
4418 Builder.AddResultTypeChunk(EncodeType);
James Dennett596e4752012-06-14 03:11:41 +00004419 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004420 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4421 Builder.AddPlaceholderChunk("type-name");
4422 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4423 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004424
4425 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004426 Builder.AddResultTypeChunk("Protocol *");
James Dennett596e4752012-06-14 03:11:41 +00004427 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004428 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4429 Builder.AddPlaceholderChunk("protocol-name");
4430 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4431 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004432
4433 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004434 Builder.AddResultTypeChunk("SEL");
James Dennett596e4752012-06-14 03:11:41 +00004435 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004436 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4437 Builder.AddPlaceholderChunk("selector");
4438 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4439 Results.AddResult(Result(Builder.TakeString()));
Ted Kremeneke65b0862012-03-06 20:05:56 +00004440
4441 // @[ objects, ... ]
James Dennett596e4752012-06-14 03:11:41 +00004442 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00004443 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4444 Builder.AddPlaceholderChunk("objects, ...");
4445 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4446 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4447 Results.AddResult(Result(Builder.TakeString()));
4448
4449 // @{ key : object, ... }
James Dennett596e4752012-06-14 03:11:41 +00004450 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00004451 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4452 Builder.AddPlaceholderChunk("key");
4453 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4454 Builder.AddChunk(CodeCompletionString::CK_Colon);
4455 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4456 Builder.AddPlaceholderChunk("object, ...");
4457 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4458 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4459 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004460}
4461
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004462static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004463 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004464 CodeCompletionBuilder Builder(Results.getAllocator(),
4465 Results.getCodeCompletionTUInfo());
Douglas Gregorf1934162010-01-13 21:24:21 +00004466
Douglas Gregorf4c33342010-05-28 00:22:41 +00004467 if (Results.includeCodePatterns()) {
4468 // @try { statements } @catch ( declaration ) { statements } @finally
4469 // { statements }
James Dennett596e4752012-06-14 03:11:41 +00004470 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004471 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4472 Builder.AddPlaceholderChunk("statements");
4473 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4474 Builder.AddTextChunk("@catch");
4475 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4476 Builder.AddPlaceholderChunk("parameter");
4477 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4478 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4479 Builder.AddPlaceholderChunk("statements");
4480 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4481 Builder.AddTextChunk("@finally");
4482 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4483 Builder.AddPlaceholderChunk("statements");
4484 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4485 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004486 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004487
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004488 // @throw
James Dennett596e4752012-06-14 03:11:41 +00004489 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004490 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4491 Builder.AddPlaceholderChunk("expression");
4492 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004493
Douglas Gregorf4c33342010-05-28 00:22:41 +00004494 if (Results.includeCodePatterns()) {
4495 // @synchronized ( expression ) { statements }
James Dennett596e4752012-06-14 03:11:41 +00004496 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004497 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4498 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4499 Builder.AddPlaceholderChunk("expression");
4500 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4501 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4502 Builder.AddPlaceholderChunk("statements");
4503 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4504 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004505 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004506}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004507
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004508static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00004509 ResultBuilder &Results,
4510 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004511 typedef CodeCompletionResult Result;
James Dennett596e4752012-06-14 03:11:41 +00004512 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4513 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4514 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregor48d46252010-01-13 21:54:15 +00004515 if (LangOpts.ObjC2)
James Dennett596e4752012-06-14 03:11:41 +00004516 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00004517}
4518
4519void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004520 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004521 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004522 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00004523 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00004524 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00004525 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004526 HandleCodeCompleteResults(this, CodeCompleter,
4527 CodeCompletionContext::CCC_Other,
4528 Results.data(),Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00004529}
4530
4531void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004532 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004533 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004534 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00004535 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004536 AddObjCStatementResults(Results, false);
4537 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004538 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004539 HandleCodeCompleteResults(this, CodeCompleter,
4540 CodeCompletionContext::CCC_Other,
4541 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004542}
4543
4544void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004545 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004546 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004547 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004548 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004549 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004550 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004551 HandleCodeCompleteResults(this, CodeCompleter,
4552 CodeCompletionContext::CCC_Other,
4553 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004554}
4555
Douglas Gregore6078da2009-11-19 00:14:45 +00004556/// \brief Determine whether the addition of the given flag to an Objective-C
4557/// property's attributes will cause a conflict.
4558static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4559 // Check if we've already added this flag.
4560 if (Attributes & NewFlag)
4561 return true;
4562
4563 Attributes |= NewFlag;
4564
4565 // Check for collisions with "readonly".
4566 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4567 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4568 ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00004569 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00004570 ObjCDeclSpec::DQ_PR_copy |
John McCall31168b02011-06-15 23:02:42 +00004571 ObjCDeclSpec::DQ_PR_retain |
4572 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregore6078da2009-11-19 00:14:45 +00004573 return true;
4574
John McCall31168b02011-06-15 23:02:42 +00004575 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregore6078da2009-11-19 00:14:45 +00004576 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00004577 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00004578 ObjCDeclSpec::DQ_PR_copy |
John McCall31168b02011-06-15 23:02:42 +00004579 ObjCDeclSpec::DQ_PR_retain|
4580 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregore6078da2009-11-19 00:14:45 +00004581 if (AssignCopyRetMask &&
4582 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00004583 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00004584 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00004585 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4586 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregore6078da2009-11-19 00:14:45 +00004587 return true;
4588
4589 return false;
4590}
4591
Douglas Gregor36029f42009-11-18 23:08:07 +00004592void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00004593 if (!CodeCompleter)
4594 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00004595
Steve Naroff936354c2009-10-08 21:55:05 +00004596 unsigned Attributes = ODS.getPropertyAttributes();
4597
John McCall276321a2010-08-25 06:19:51 +00004598 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004599 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004600 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004601 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00004602 Results.EnterNewScope();
Douglas Gregore6078da2009-11-19 00:14:45 +00004603 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00004604 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004605 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00004606 Results.AddResult(CodeCompletionResult("assign"));
John McCall31168b02011-06-15 23:02:42 +00004607 if (!ObjCPropertyFlagConflicts(Attributes,
4608 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4609 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004610 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00004611 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004612 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00004613 Results.AddResult(CodeCompletionResult("retain"));
John McCall31168b02011-06-15 23:02:42 +00004614 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4615 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004616 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00004617 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004618 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00004619 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00004620 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4621 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004622 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004623 CodeCompletionBuilder Setter(Results.getAllocator(),
4624 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004625 Setter.AddTypedTextChunk("setter");
4626 Setter.AddTextChunk(" = ");
4627 Setter.AddPlaceholderChunk("method");
4628 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00004629 }
Douglas Gregore6078da2009-11-19 00:14:45 +00004630 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004631 CodeCompletionBuilder Getter(Results.getAllocator(),
4632 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004633 Getter.AddTypedTextChunk("getter");
4634 Getter.AddTextChunk(" = ");
4635 Getter.AddPlaceholderChunk("method");
4636 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00004637 }
Steve Naroff936354c2009-10-08 21:55:05 +00004638 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004639 HandleCodeCompleteResults(this, CodeCompleter,
4640 CodeCompletionContext::CCC_Other,
4641 Results.data(),Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00004642}
Steve Naroffeae65032009-11-07 02:08:14 +00004643
Douglas Gregorc8537c52009-11-19 07:41:15 +00004644/// \brief Descripts the kind of Objective-C method that we want to find
4645/// via code completion.
4646enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00004647 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4648 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4649 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00004650};
4651
Douglas Gregor67c692c2010-08-26 15:07:07 +00004652static bool isAcceptableObjCSelector(Selector Sel,
4653 ObjCMethodKind WantKind,
4654 IdentifierInfo **SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004655 unsigned NumSelIdents,
4656 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00004657 if (NumSelIdents > Sel.getNumArgs())
4658 return false;
4659
4660 switch (WantKind) {
4661 case MK_Any: break;
4662 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4663 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4664 }
4665
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004666 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4667 return false;
4668
Douglas Gregor67c692c2010-08-26 15:07:07 +00004669 for (unsigned I = 0; I != NumSelIdents; ++I)
4670 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4671 return false;
4672
4673 return true;
4674}
4675
Douglas Gregorc8537c52009-11-19 07:41:15 +00004676static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4677 ObjCMethodKind WantKind,
4678 IdentifierInfo **SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004679 unsigned NumSelIdents,
4680 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00004681 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004682 NumSelIdents, AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004683}
Douglas Gregor1154e272010-09-16 16:06:31 +00004684
4685namespace {
4686 /// \brief A set of selectors, which is used to avoid introducing multiple
4687 /// completions with the same selector into the result set.
4688 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4689}
4690
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004691/// \brief Add all of the Objective-C methods in the given Objective-C
4692/// container to the set of results.
4693///
4694/// The container will be a class, protocol, category, or implementation of
4695/// any of the above. This mether will recurse to include methods from
4696/// the superclasses of classes along with their categories, protocols, and
4697/// implementations.
4698///
4699/// \param Container the container in which we'll look to find methods.
4700///
James Dennett596e4752012-06-14 03:11:41 +00004701/// \param WantInstanceMethods Whether to add instance methods (only); if
4702/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004703///
4704/// \param CurContext the context in which we're performing the lookup that
4705/// finds methods.
4706///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004707/// \param AllowSameLength Whether we allow a method to be added to the list
4708/// when it has the same number of parameters as we have selector identifiers.
4709///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004710/// \param Results the structure into which we'll add results.
4711static void AddObjCMethods(ObjCContainerDecl *Container,
4712 bool WantInstanceMethods,
Douglas Gregorc8537c52009-11-19 07:41:15 +00004713 ObjCMethodKind WantKind,
Douglas Gregor1b605f72009-11-19 01:08:35 +00004714 IdentifierInfo **SelIdents,
4715 unsigned NumSelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004716 DeclContext *CurContext,
Douglas Gregor1154e272010-09-16 16:06:31 +00004717 VisitedSelectorSet &Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004718 bool AllowSameLength,
Douglas Gregor416b5752010-08-25 01:08:01 +00004719 ResultBuilder &Results,
4720 bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004721 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004722 Container = getContainerDef(Container);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004723 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4724 MEnd = Container->meth_end();
4725 M != MEnd; ++M) {
David Blaikie2d7c57e2012-04-30 02:36:29 +00004726 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00004727 // Check whether the selector identifiers we've been given are a
4728 // subset of the identifiers for this particular method.
David Blaikie40ed2972012-06-06 20:45:41 +00004729 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004730 AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00004731 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004732
David Blaikie2d7c57e2012-04-30 02:36:29 +00004733 if (!Selectors.insert(M->getSelector()))
Douglas Gregor1154e272010-09-16 16:06:31 +00004734 continue;
4735
David Blaikie40ed2972012-06-06 20:45:41 +00004736 Result R = Result(*M, 0);
Douglas Gregor1b605f72009-11-19 01:08:35 +00004737 R.StartParameter = NumSelIdents;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004738 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00004739 if (!InOriginalClass)
4740 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00004741 Results.MaybeAddResult(R, CurContext);
4742 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004743 }
4744
Douglas Gregorf37c9492010-09-16 15:34:59 +00004745 // Visit the protocols of protocols.
4746 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00004747 if (Protocol->hasDefinition()) {
4748 const ObjCList<ObjCProtocolDecl> &Protocols
4749 = Protocol->getReferencedProtocols();
4750 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4751 E = Protocols.end();
4752 I != E; ++I)
4753 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4754 NumSelIdents, CurContext, Selectors, AllowSameLength,
4755 Results, false);
4756 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00004757 }
4758
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004759 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00004760 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004761 return;
4762
4763 // Add methods in protocols.
Argyrios Kyrtzidise7f3ef32012-03-13 01:09:41 +00004764 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4765 E = IFace->protocol_end();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004766 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00004767 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004768 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004769
4770 // Add methods in categories.
4771 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4772 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00004773 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004774 NumSelIdents, CurContext, Selectors, AllowSameLength,
4775 Results, InOriginalClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004776
4777 // Add a categories protocol methods.
4778 const ObjCList<ObjCProtocolDecl> &Protocols
4779 = CatDecl->getReferencedProtocols();
4780 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4781 E = Protocols.end();
4782 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00004783 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004784 NumSelIdents, CurContext, Selectors, AllowSameLength,
4785 Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004786
4787 // Add methods in category implementations.
4788 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004789 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004790 NumSelIdents, CurContext, Selectors, AllowSameLength,
4791 Results, InOriginalClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004792 }
4793
4794 // Add methods in superclass.
4795 if (IFace->getSuperClass())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004796 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004797 SelIdents, NumSelIdents, CurContext, Selectors,
4798 AllowSameLength, Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004799
4800 // Add methods in our implementation, if any.
4801 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004802 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004803 NumSelIdents, CurContext, Selectors, AllowSameLength,
4804 Results, InOriginalClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004805}
4806
4807
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004808void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00004809 typedef CodeCompletionResult Result;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004810
4811 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004812 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004813 if (!Class) {
4814 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004815 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00004816 Class = Category->getClassInterface();
4817
4818 if (!Class)
4819 return;
4820 }
4821
4822 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004823 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004824 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004825 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004826 Results.EnterNewScope();
4827
Douglas Gregor1154e272010-09-16 16:06:31 +00004828 VisitedSelectorSet Selectors;
4829 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004830 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004831 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004832 HandleCodeCompleteResults(this, CodeCompleter,
4833 CodeCompletionContext::CCC_Other,
4834 Results.data(),Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00004835}
4836
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004837void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00004838 typedef CodeCompletionResult Result;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004839
4840 // Try to find the interface where setters might live.
4841 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004842 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004843 if (!Class) {
4844 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004845 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00004846 Class = Category->getClassInterface();
4847
4848 if (!Class)
4849 return;
4850 }
4851
4852 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004853 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004854 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004855 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004856 Results.EnterNewScope();
4857
Douglas Gregor1154e272010-09-16 16:06:31 +00004858 VisitedSelectorSet Selectors;
4859 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004860 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004861
4862 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004863 HandleCodeCompleteResults(this, CodeCompleter,
4864 CodeCompletionContext::CCC_Other,
4865 Results.data(),Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004866}
4867
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004868void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4869 bool IsParameter) {
John McCall276321a2010-08-25 06:19:51 +00004870 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004871 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004872 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004873 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00004874 Results.EnterNewScope();
4875
4876 // Add context-sensitive, Objective-C parameter-passing keywords.
4877 bool AddedInOut = false;
4878 if ((DS.getObjCDeclQualifier() &
4879 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4880 Results.AddResult("in");
4881 Results.AddResult("inout");
4882 AddedInOut = true;
4883 }
4884 if ((DS.getObjCDeclQualifier() &
4885 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4886 Results.AddResult("out");
4887 if (!AddedInOut)
4888 Results.AddResult("inout");
4889 }
4890 if ((DS.getObjCDeclQualifier() &
4891 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4892 ObjCDeclSpec::DQ_Oneway)) == 0) {
4893 Results.AddResult("bycopy");
4894 Results.AddResult("byref");
4895 Results.AddResult("oneway");
4896 }
4897
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004898 // If we're completing the return type of an Objective-C method and the
4899 // identifier IBAction refers to a macro, provide a completion item for
4900 // an action, e.g.,
4901 // IBAction)<#selector#>:(id)sender
4902 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4903 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004904 CodeCompletionBuilder Builder(Results.getAllocator(),
4905 Results.getCodeCompletionTUInfo(),
4906 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004907 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00004908 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004909 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00004910 Builder.AddChunk(CodeCompletionString::CK_Colon);
4911 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004912 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00004913 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004914 Builder.AddTextChunk("sender");
4915 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4916 }
4917
Douglas Gregor99fa2642010-08-24 01:06:58 +00004918 // Add various builtin type names and specifiers.
4919 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4920 Results.ExitScope();
4921
4922 // Add the various type names
4923 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4924 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4925 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4926 CodeCompleter->includeGlobals());
4927
4928 if (CodeCompleter->includeMacros())
4929 AddMacroResults(PP, Results);
4930
4931 HandleCodeCompleteResults(this, CodeCompleter,
4932 CodeCompletionContext::CCC_Type,
4933 Results.data(), Results.size());
4934}
4935
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004936/// \brief When we have an expression with type "id", we may assume
4937/// that it has some more-specific class type based on knowledge of
4938/// common uses of Objective-C. This routine returns that class type,
4939/// or NULL if no better result could be determined.
4940static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00004941 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004942 if (!Msg)
4943 return 0;
4944
4945 Selector Sel = Msg->getSelector();
4946 if (Sel.isNull())
4947 return 0;
4948
4949 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4950 if (!Id)
4951 return 0;
4952
4953 ObjCMethodDecl *Method = Msg->getMethodDecl();
4954 if (!Method)
4955 return 0;
4956
4957 // Determine the class that we're sending the message to.
Douglas Gregor9a129192010-04-21 00:45:42 +00004958 ObjCInterfaceDecl *IFace = 0;
4959 switch (Msg->getReceiverKind()) {
4960 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00004961 if (const ObjCObjectType *ObjType
4962 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4963 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00004964 break;
4965
4966 case ObjCMessageExpr::Instance: {
4967 QualType T = Msg->getInstanceReceiver()->getType();
4968 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4969 IFace = Ptr->getInterfaceDecl();
4970 break;
4971 }
4972
4973 case ObjCMessageExpr::SuperInstance:
4974 case ObjCMessageExpr::SuperClass:
4975 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004976 }
4977
4978 if (!IFace)
4979 return 0;
4980
4981 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4982 if (Method->isInstanceMethod())
4983 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4984 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00004985 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004986 .Case("autorelease", IFace)
4987 .Case("copy", IFace)
4988 .Case("copyWithZone", IFace)
4989 .Case("mutableCopy", IFace)
4990 .Case("mutableCopyWithZone", IFace)
4991 .Case("awakeFromCoder", IFace)
4992 .Case("replacementObjectFromCoder", IFace)
4993 .Case("class", IFace)
4994 .Case("classForCoder", IFace)
4995 .Case("superclass", Super)
4996 .Default(0);
4997
4998 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4999 .Case("new", IFace)
5000 .Case("alloc", IFace)
5001 .Case("allocWithZone", IFace)
5002 .Case("class", IFace)
5003 .Case("superclass", Super)
5004 .Default(0);
5005}
5006
Douglas Gregor6fc04132010-08-27 15:10:57 +00005007// Add a special completion for a message send to "super", which fills in the
5008// most likely case of forwarding all of our arguments to the superclass
5009// function.
5010///
5011/// \param S The semantic analysis object.
5012///
5013/// \param S NeedSuperKeyword Whether we need to prefix this completion with
5014/// the "super" keyword. Otherwise, we just need to provide the arguments.
5015///
5016/// \param SelIdents The identifiers in the selector that have already been
5017/// provided as arguments for a send to "super".
5018///
5019/// \param NumSelIdents The number of identifiers in \p SelIdents.
5020///
5021/// \param Results The set of results to augment.
5022///
5023/// \returns the Objective-C method declaration that would be invoked by
5024/// this "super" completion. If NULL, no completion was added.
5025static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5026 IdentifierInfo **SelIdents,
5027 unsigned NumSelIdents,
5028 ResultBuilder &Results) {
5029 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5030 if (!CurMethod)
5031 return 0;
5032
5033 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5034 if (!Class)
5035 return 0;
5036
5037 // Try to find a superclass method with the same selector.
5038 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005039 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5040 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00005041 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5042 CurMethod->isInstanceMethod());
5043
Douglas Gregorb5f1e462011-02-16 00:51:18 +00005044 // Check in categories or class extensions.
5045 if (!SuperMethod) {
5046 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5047 Category = Category->getNextClassCategory())
5048 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
5049 CurMethod->isInstanceMethod())))
5050 break;
5051 }
5052 }
5053
Douglas Gregor6fc04132010-08-27 15:10:57 +00005054 if (!SuperMethod)
5055 return 0;
5056
5057 // Check whether the superclass method has the same signature.
5058 if (CurMethod->param_size() != SuperMethod->param_size() ||
5059 CurMethod->isVariadic() != SuperMethod->isVariadic())
5060 return 0;
5061
5062 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5063 CurPEnd = CurMethod->param_end(),
5064 SuperP = SuperMethod->param_begin();
5065 CurP != CurPEnd; ++CurP, ++SuperP) {
5066 // Make sure the parameter types are compatible.
5067 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5068 (*SuperP)->getType()))
5069 return 0;
5070
5071 // Make sure we have a parameter name to forward!
5072 if (!(*CurP)->getIdentifier())
5073 return 0;
5074 }
5075
5076 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005077 CodeCompletionBuilder Builder(Results.getAllocator(),
5078 Results.getCodeCompletionTUInfo());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005079
5080 // Give this completion a return type.
Douglas Gregor75acd922011-09-27 23:30:47 +00005081 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5082 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005083
5084 // If we need the "super" keyword, add it (plus some spacing).
5085 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005086 Builder.AddTypedTextChunk("super");
5087 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005088 }
5089
5090 Selector Sel = CurMethod->getSelector();
5091 if (Sel.isUnarySelector()) {
5092 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005093 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005094 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005095 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005096 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005097 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005098 } else {
5099 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5100 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5101 if (I > NumSelIdents)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005102 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005103
5104 if (I < NumSelIdents)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005105 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005106 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005107 Sel.getNameForSlot(I) + ":"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005108 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005109 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005110 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005111 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005112 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005113 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005114 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005115 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005116 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005117 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005118 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005119 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005120 }
5121 }
5122 }
5123
Douglas Gregor78254c82012-03-27 23:34:16 +00005124 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5125 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005126 return SuperMethod;
5127}
5128
Douglas Gregora817a192010-05-27 23:06:34 +00005129void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005130 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005131 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005132 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005133 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikiebbafb8a2012-03-11 07:00:24 +00005134 getLangOpts().CPlusPlus0x
Douglas Gregord8c61782012-02-15 15:34:24 +00005135 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5136 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005137
Douglas Gregora817a192010-05-27 23:06:34 +00005138 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5139 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005140 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5141 CodeCompleter->includeGlobals());
Douglas Gregora817a192010-05-27 23:06:34 +00005142
5143 // If we are in an Objective-C method inside a class that has a superclass,
5144 // add "super" as an option.
5145 if (ObjCMethodDecl *Method = getCurMethodDecl())
5146 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005147 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005148 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005149
5150 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5151 }
Douglas Gregora817a192010-05-27 23:06:34 +00005152
David Blaikiebbafb8a2012-03-11 07:00:24 +00005153 if (getLangOpts().CPlusPlus0x)
Douglas Gregord8c61782012-02-15 15:34:24 +00005154 addThisCompletion(*this, Results);
5155
Douglas Gregora817a192010-05-27 23:06:34 +00005156 Results.ExitScope();
5157
5158 if (CodeCompleter->includeMacros())
5159 AddMacroResults(PP, Results);
Douglas Gregor50832e02010-09-20 22:39:41 +00005160 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005161 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005162
5163}
5164
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005165void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5166 IdentifierInfo **SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005167 unsigned NumSelIdents,
5168 bool AtArgumentExpression) {
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005169 ObjCInterfaceDecl *CDecl = 0;
5170 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5171 // Figure out which interface we're in.
5172 CDecl = CurMethod->getClassInterface();
5173 if (!CDecl)
5174 return;
5175
5176 // Find the superclass of this class.
5177 CDecl = CDecl->getSuperClass();
5178 if (!CDecl)
5179 return;
5180
5181 if (CurMethod->isInstanceMethod()) {
5182 // We are inside an instance method, which means that the message
5183 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005184 // current object.
5185 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor6fc04132010-08-27 15:10:57 +00005186 SelIdents, NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005187 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005188 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005189 }
5190
5191 // Fall through to send to the superclass in CDecl.
5192 } else {
5193 // "super" may be the name of a type or variable. Figure out which
5194 // it is.
5195 IdentifierInfo *Super = &Context.Idents.get("super");
5196 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5197 LookupOrdinaryName);
5198 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5199 // "super" names an interface. Use it.
5200 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005201 if (const ObjCObjectType *Iface
5202 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5203 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005204 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5205 // "super" names an unresolved type; we can't be more specific.
5206 } else {
5207 // Assume that "super" names some kind of value and parse that way.
5208 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005209 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005210 UnqualifiedId id;
5211 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005212 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5213 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005214 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005215 SelIdents, NumSelIdents,
5216 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005217 }
5218
5219 // Fall through
5220 }
5221
John McCallba7bf592010-08-24 05:47:05 +00005222 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005223 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00005224 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005225 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005226 NumSelIdents, AtArgumentExpression,
5227 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005228}
5229
Douglas Gregor74661272010-09-21 00:03:25 +00005230/// \brief Given a set of code-completion results for the argument of a message
5231/// send, determine the preferred type (if any) for that argument expression.
5232static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5233 unsigned NumSelIdents) {
5234 typedef CodeCompletionResult Result;
5235 ASTContext &Context = Results.getSema().Context;
5236
5237 QualType PreferredType;
5238 unsigned BestPriority = CCP_Unlikely * 2;
5239 Result *ResultsData = Results.data();
5240 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5241 Result &R = ResultsData[I];
5242 if (R.Kind == Result::RK_Declaration &&
5243 isa<ObjCMethodDecl>(R.Declaration)) {
5244 if (R.Priority <= BestPriority) {
5245 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5246 if (NumSelIdents <= Method->param_size()) {
5247 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5248 ->getType();
5249 if (R.Priority < BestPriority || PreferredType.isNull()) {
5250 BestPriority = R.Priority;
5251 PreferredType = MyPreferredType;
5252 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5253 MyPreferredType)) {
5254 PreferredType = QualType();
5255 }
5256 }
5257 }
5258 }
5259 }
5260
5261 return PreferredType;
5262}
5263
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005264static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5265 ParsedType Receiver,
5266 IdentifierInfo **SelIdents,
5267 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005268 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005269 bool IsSuper,
5270 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005271 typedef CodeCompletionResult Result;
Douglas Gregor8ce33212009-11-17 17:59:40 +00005272 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005273
Douglas Gregor8ce33212009-11-17 17:59:40 +00005274 // If the given name refers to an interface type, retrieve the
5275 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005276 if (Receiver) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005277 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005278 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00005279 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5280 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00005281 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005282
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005283 // Add all of the factory methods in this Objective-C class, its protocols,
5284 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00005285 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005286
Douglas Gregor6fc04132010-08-27 15:10:57 +00005287 // If this is a send-to-super, try to add the special "super" send
5288 // completion.
5289 if (IsSuper) {
5290 if (ObjCMethodDecl *SuperMethod
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005291 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5292 Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00005293 Results.Ignore(SuperMethod);
5294 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005295
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005296 // If we're inside an Objective-C method definition, prefer its selector to
5297 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005298 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005299 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005300
Douglas Gregor1154e272010-09-16 16:06:31 +00005301 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00005302 if (CDecl)
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005303 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005304 SemaRef.CurContext, Selectors, AtArgumentExpression,
5305 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005306 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00005307 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005308
Douglas Gregord720daf2010-04-06 17:30:22 +00005309 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005310 // pool from the AST file.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005311 if (SemaRef.ExternalSource) {
5312 for (uint32_t I = 0,
5313 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00005314 I != N; ++I) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005315 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5316 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005317 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005318
5319 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00005320 }
5321 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005322
5323 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5324 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00005325 M != MEnd; ++M) {
5326 for (ObjCMethodList *MethList = &M->second.second;
5327 MethList && MethList->Method;
Douglas Gregor6285f752010-04-06 16:40:00 +00005328 MethList = MethList->Next) {
5329 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5330 NumSelIdents))
5331 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005332
Douglas Gregor6285f752010-04-06 16:40:00 +00005333 Result R(MethList->Method, 0);
5334 R.StartParameter = NumSelIdents;
5335 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005336 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00005337 }
5338 }
5339 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005340
5341 Results.ExitScope();
5342}
Douglas Gregor6285f752010-04-06 16:40:00 +00005343
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005344void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5345 IdentifierInfo **SelIdents,
5346 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005347 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005348 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00005349
5350 QualType T = this->GetTypeFromParser(Receiver);
5351
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005352 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005353 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00005354 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregorea777402011-07-26 15:24:30 +00005355 T, SelIdents, NumSelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00005356
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005357 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5358 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00005359
5360 // If we're actually at the argument expression (rather than prior to the
5361 // selector), we're actually performing code completion for an expression.
5362 // Determine whether we have a single, best method. If so, we can
5363 // code-complete the expression using the corresponding parameter type as
5364 // our preferred type, improving completion results.
5365 if (AtArgumentExpression) {
5366 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregor63745d52011-07-21 01:05:26 +00005367 NumSelIdents);
Douglas Gregor74661272010-09-21 00:03:25 +00005368 if (PreferredType.isNull())
5369 CodeCompleteOrdinaryName(S, PCC_Expression);
5370 else
5371 CodeCompleteExpression(S, PreferredType);
5372 return;
5373 }
5374
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005375 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00005376 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005377 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00005378}
5379
Richard Trieu2bd04012011-09-09 02:00:50 +00005380void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregor1b605f72009-11-19 01:08:35 +00005381 IdentifierInfo **SelIdents,
Douglas Gregor6fc04132010-08-27 15:10:57 +00005382 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005383 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005384 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00005385 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00005386
5387 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00005388
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005389 // If necessary, apply function/array conversion to the receiver.
5390 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00005391 if (RecExpr) {
5392 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5393 if (Conv.isInvalid()) // conversion failed. bail.
5394 return;
5395 RecExpr = Conv.take();
5396 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00005397 QualType ReceiverType = RecExpr? RecExpr->getType()
5398 : Super? Context.getObjCObjectPointerType(
5399 Context.getObjCInterfaceType(Super))
5400 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00005401
Douglas Gregordc520b02010-11-08 21:12:30 +00005402 // If we're messaging an expression with type "id" or "Class", check
5403 // whether we know something special about the receiver that allows
5404 // us to assume a more-specific receiver type.
5405 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5406 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5407 if (ReceiverType->isObjCClassType())
5408 return CodeCompleteObjCClassMessage(S,
5409 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5410 SelIdents, NumSelIdents,
5411 AtArgumentExpression, Super);
5412
5413 ReceiverType = Context.getObjCObjectPointerType(
5414 Context.getObjCInterfaceType(IFace));
5415 }
5416
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005417 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005418 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005419 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor63745d52011-07-21 01:05:26 +00005420 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregorea777402011-07-26 15:24:30 +00005421 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00005422
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005423 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005424
Douglas Gregor6fc04132010-08-27 15:10:57 +00005425 // If this is a send-to-super, try to add the special "super" send
5426 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00005427 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005428 if (ObjCMethodDecl *SuperMethod
5429 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5430 Results))
5431 Results.Ignore(SuperMethod);
5432 }
5433
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005434 // If we're inside an Objective-C method definition, prefer its selector to
5435 // others.
5436 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5437 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005438
Douglas Gregor1154e272010-09-16 16:06:31 +00005439 // Keep track of the selectors we've already added.
5440 VisitedSelectorSet Selectors;
5441
Douglas Gregora3329fa2009-11-18 00:06:18 +00005442 // Handle messages to Class. This really isn't a message to an instance
5443 // method, so we treat it the same way we would treat a message send to a
5444 // class method.
5445 if (ReceiverType->isObjCClassType() ||
5446 ReceiverType->isObjCQualifiedClassType()) {
5447 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5448 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregorc8537c52009-11-19 07:41:15 +00005449 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005450 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005451 }
5452 }
5453 // Handle messages to a qualified ID ("id<foo>").
5454 else if (const ObjCObjectPointerType *QualID
5455 = ReceiverType->getAsObjCQualifiedIdType()) {
5456 // Search protocols for instance methods.
5457 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5458 E = QualID->qual_end();
5459 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00005460 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005461 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005462 }
5463 // Handle messages to a pointer to interface type.
5464 else if (const ObjCObjectPointerType *IFacePtr
5465 = ReceiverType->getAsObjCInterfacePointerType()) {
5466 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005467 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005468 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5469 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005470
5471 // Search protocols for instance methods.
5472 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5473 E = IFacePtr->qual_end();
5474 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00005475 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005476 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005477 }
Douglas Gregor6285f752010-04-06 16:40:00 +00005478 // Handle messages to "id".
5479 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00005480 // We're messaging "id", so provide all instance methods we know
5481 // about as code-completion results.
5482
5483 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005484 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00005485 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00005486 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5487 I != N; ++I) {
5488 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00005489 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005490 continue;
5491
Sebastian Redl75d8a322010-08-02 23:18:59 +00005492 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00005493 }
5494 }
5495
Sebastian Redl75d8a322010-08-02 23:18:59 +00005496 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5497 MEnd = MethodPool.end();
5498 M != MEnd; ++M) {
5499 for (ObjCMethodList *MethList = &M->second.first;
5500 MethList && MethList->Method;
Douglas Gregor6285f752010-04-06 16:40:00 +00005501 MethList = MethList->Next) {
5502 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5503 NumSelIdents))
5504 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00005505
5506 if (!Selectors.insert(MethList->Method->getSelector()))
5507 continue;
5508
Douglas Gregor6285f752010-04-06 16:40:00 +00005509 Result R(MethList->Method, 0);
5510 R.StartParameter = NumSelIdents;
5511 R.AllParametersAreInformative = false;
5512 Results.MaybeAddResult(R, CurContext);
5513 }
5514 }
5515 }
Steve Naroffeae65032009-11-07 02:08:14 +00005516 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00005517
5518
5519 // If we're actually at the argument expression (rather than prior to the
5520 // selector), we're actually performing code completion for an expression.
5521 // Determine whether we have a single, best method. If so, we can
5522 // code-complete the expression using the corresponding parameter type as
5523 // our preferred type, improving completion results.
5524 if (AtArgumentExpression) {
5525 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5526 NumSelIdents);
5527 if (PreferredType.isNull())
5528 CodeCompleteOrdinaryName(S, PCC_Expression);
5529 else
5530 CodeCompleteExpression(S, PreferredType);
5531 return;
5532 }
5533
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005534 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00005535 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005536 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00005537}
Douglas Gregorbaf69612009-11-18 04:19:12 +00005538
Douglas Gregor68762e72010-08-23 21:17:50 +00005539void Sema::CodeCompleteObjCForCollection(Scope *S,
5540 DeclGroupPtrTy IterationVar) {
5541 CodeCompleteExpressionData Data;
5542 Data.ObjCCollection = true;
5543
5544 if (IterationVar.getAsOpaquePtr()) {
5545 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5546 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5547 if (*I)
5548 Data.IgnoreDecls.push_back(*I);
5549 }
5550 }
5551
5552 CodeCompleteExpression(S, Data);
5553}
5554
Douglas Gregor67c692c2010-08-26 15:07:07 +00005555void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5556 unsigned NumSelIdents) {
5557 // If we have an external source, load the entire class method
5558 // pool from the AST file.
5559 if (ExternalSource) {
5560 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5561 I != N; ++I) {
5562 Selector Sel = ExternalSource->GetExternalSelector(I);
5563 if (Sel.isNull() || MethodPool.count(Sel))
5564 continue;
5565
5566 ReadMethodPool(Sel);
5567 }
5568 }
5569
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005570 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005571 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005572 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00005573 Results.EnterNewScope();
5574 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5575 MEnd = MethodPool.end();
5576 M != MEnd; ++M) {
5577
5578 Selector Sel = M->first;
5579 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5580 continue;
5581
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005582 CodeCompletionBuilder Builder(Results.getAllocator(),
5583 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005584 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005585 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005586 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005587 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005588 continue;
5589 }
5590
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005591 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005592 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005593 if (I == NumSelIdents) {
5594 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005595 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005596 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005597 Accumulator.clear();
5598 }
5599 }
5600
Benjamin Kramer632500c2011-07-26 16:59:25 +00005601 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005602 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00005603 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005604 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005605 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005606 }
5607 Results.ExitScope();
5608
5609 HandleCodeCompleteResults(this, CodeCompleter,
5610 CodeCompletionContext::CCC_SelectorName,
5611 Results.data(), Results.size());
5612}
5613
Douglas Gregorbaf69612009-11-18 04:19:12 +00005614/// \brief Add all of the protocol declarations that we find in the given
5615/// (translation unit) context.
5616static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005617 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00005618 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005619 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00005620
5621 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5622 DEnd = Ctx->decls_end();
5623 D != DEnd; ++D) {
5624 // Record any protocols we find.
5625 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00005626 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregorfc59ce12010-01-14 16:14:35 +00005627 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005628 }
5629}
5630
5631void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5632 unsigned NumProtocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005633 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005634 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005635 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005636
Douglas Gregora3b23b02010-12-09 21:44:02 +00005637 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5638 Results.EnterNewScope();
5639
5640 // Tell the result set to ignore all of the protocols we have
5641 // already seen.
5642 // FIXME: This doesn't work when caching code-completion results.
5643 for (unsigned I = 0; I != NumProtocols; ++I)
5644 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5645 Protocols[I].second))
5646 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005647
Douglas Gregora3b23b02010-12-09 21:44:02 +00005648 // Add all protocols.
5649 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5650 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005651
Douglas Gregora3b23b02010-12-09 21:44:02 +00005652 Results.ExitScope();
5653 }
5654
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005655 HandleCodeCompleteResults(this, CodeCompleter,
5656 CodeCompletionContext::CCC_ObjCProtocolName,
5657 Results.data(),Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005658}
5659
5660void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005661 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005662 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005663 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005664
Douglas Gregora3b23b02010-12-09 21:44:02 +00005665 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5666 Results.EnterNewScope();
5667
5668 // Add all protocols.
5669 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5670 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005671
Douglas Gregora3b23b02010-12-09 21:44:02 +00005672 Results.ExitScope();
5673 }
5674
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005675 HandleCodeCompleteResults(this, CodeCompleter,
5676 CodeCompletionContext::CCC_ObjCProtocolName,
5677 Results.data(),Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00005678}
Douglas Gregor49c22a72009-11-18 16:26:39 +00005679
5680/// \brief Add all of the Objective-C interface declarations that we find in
5681/// the given (translation unit) context.
5682static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5683 bool OnlyForwardDeclarations,
5684 bool OnlyUnimplemented,
5685 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005686 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00005687
5688 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5689 DEnd = Ctx->decls_end();
5690 D != DEnd; ++D) {
Douglas Gregor1c283312010-08-11 12:19:30 +00005691 // Record any interfaces we find.
5692 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00005693 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00005694 (!OnlyUnimplemented || !Class->getImplementation()))
5695 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005696 }
5697}
5698
5699void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005700 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005701 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005702 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005703 Results.EnterNewScope();
5704
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005705 if (CodeCompleter->includeGlobals()) {
5706 // Add all classes.
5707 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5708 false, Results);
5709 }
5710
Douglas Gregor49c22a72009-11-18 16:26:39 +00005711 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005712
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005713 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005714 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005715 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005716}
5717
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005718void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5719 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005720 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005721 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005722 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005723 Results.EnterNewScope();
5724
5725 // Make sure that we ignore the class we're currently defining.
5726 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005727 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005728 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00005729 Results.Ignore(CurClass);
5730
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005731 if (CodeCompleter->includeGlobals()) {
5732 // Add all classes.
5733 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5734 false, Results);
5735 }
5736
Douglas Gregor49c22a72009-11-18 16:26:39 +00005737 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005738
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005739 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005740 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005741 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005742}
5743
5744void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005745 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005746 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005747 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005748 Results.EnterNewScope();
5749
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005750 if (CodeCompleter->includeGlobals()) {
5751 // Add all unimplemented classes.
5752 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5753 true, Results);
5754 }
5755
Douglas Gregor49c22a72009-11-18 16:26:39 +00005756 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005757
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005758 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005759 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005760 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005761}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005762
5763void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005764 IdentifierInfo *ClassName,
5765 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00005766 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005767
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005768 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005769 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00005770 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005771
5772 // Ignore any categories we find that have already been implemented by this
5773 // interface.
5774 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5775 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005776 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005777 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5778 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5779 Category = Category->getNextClassCategory())
5780 CategoryNames.insert(Category->getIdentifier());
5781
5782 // Add all of the categories we know about.
5783 Results.EnterNewScope();
5784 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5785 for (DeclContext::decl_iterator D = TU->decls_begin(),
5786 DEnd = TU->decls_end();
5787 D != DEnd; ++D)
5788 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5789 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregorfc59ce12010-01-14 16:14:35 +00005790 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005791 Results.ExitScope();
5792
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005793 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00005794 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005795 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005796}
5797
5798void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005799 IdentifierInfo *ClassName,
5800 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00005801 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005802
5803 // Find the corresponding interface. If we couldn't find the interface, the
5804 // program itself is ill-formed. However, we'll try to be helpful still by
5805 // providing the list of all of the categories we know about.
5806 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005807 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005808 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5809 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005810 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005811
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005812 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005813 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00005814 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005815
5816 // Add all of the categories that have have corresponding interface
5817 // declarations in this class and any of its superclasses, except for
5818 // already-implemented categories in the class itself.
5819 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5820 Results.EnterNewScope();
5821 bool IgnoreImplemented = true;
5822 while (Class) {
5823 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5824 Category = Category->getNextClassCategory())
5825 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5826 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregorfc59ce12010-01-14 16:14:35 +00005827 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005828
5829 Class = Class->getSuperClass();
5830 IgnoreImplemented = false;
5831 }
5832 Results.ExitScope();
5833
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005834 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00005835 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005836 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005837}
Douglas Gregor5d649882009-11-18 22:32:06 +00005838
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005839void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005840 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005841 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005842 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005843 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00005844
5845 // Figure out where this @synthesize lives.
5846 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005847 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00005848 if (!Container ||
5849 (!isa<ObjCImplementationDecl>(Container) &&
5850 !isa<ObjCCategoryImplDecl>(Container)))
5851 return;
5852
5853 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005854 Container = getContainerDef(Container);
5855 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor5d649882009-11-18 22:32:06 +00005856 DEnd = Container->decls_end();
5857 D != DEnd; ++D)
5858 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5859 Results.Ignore(PropertyImpl->getPropertyDecl());
5860
5861 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00005862 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00005863 Results.EnterNewScope();
5864 if (ObjCImplementationDecl *ClassImpl
5865 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor95147142011-05-05 15:50:42 +00005866 AddObjCProperties(ClassImpl->getClassInterface(), false,
5867 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00005868 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00005869 else
5870 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00005871 false, /*AllowNullaryMethods=*/false, CurContext,
5872 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00005873 Results.ExitScope();
5874
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005875 HandleCodeCompleteResults(this, CodeCompleter,
5876 CodeCompletionContext::CCC_Other,
5877 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00005878}
5879
5880void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005881 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00005882 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005883 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005884 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005885 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00005886
5887 // Figure out where this @synthesize lives.
5888 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005889 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00005890 if (!Container ||
5891 (!isa<ObjCImplementationDecl>(Container) &&
5892 !isa<ObjCCategoryImplDecl>(Container)))
5893 return;
5894
5895 // Figure out which interface we're looking into.
5896 ObjCInterfaceDecl *Class = 0;
5897 if (ObjCImplementationDecl *ClassImpl
5898 = dyn_cast<ObjCImplementationDecl>(Container))
5899 Class = ClassImpl->getClassInterface();
5900 else
5901 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5902 ->getClassInterface();
5903
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005904 // Determine the type of the property we're synthesizing.
5905 QualType PropertyType = Context.getObjCIdType();
5906 if (Class) {
5907 if (ObjCPropertyDecl *Property
5908 = Class->FindPropertyDeclaration(PropertyName)) {
5909 PropertyType
5910 = Property->getType().getNonReferenceType().getUnqualifiedType();
5911
5912 // Give preference to ivars
5913 Results.setPreferredType(PropertyType);
5914 }
5915 }
5916
Douglas Gregor5d649882009-11-18 22:32:06 +00005917 // Add all of the instance variables in this class and its superclasses.
5918 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00005919 bool SawSimilarlyNamedIvar = false;
5920 std::string NameWithPrefix;
5921 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00005922 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00005923 std::string NameWithSuffix = PropertyName->getName().str();
5924 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00005925 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00005926 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5927 Ivar = Ivar->getNextIvar()) {
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005928 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5929
Douglas Gregor331faa02011-04-18 14:13:53 +00005930 // Determine whether we've seen an ivar with a name similar to the
5931 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005932 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00005933 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005934 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00005935 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005936
5937 // Reduce the priority of this result by one, to give it a slight
5938 // advantage over other results whose names don't match so closely.
5939 if (Results.size() &&
5940 Results.data()[Results.size() - 1].Kind
5941 == CodeCompletionResult::RK_Declaration &&
5942 Results.data()[Results.size() - 1].Declaration == Ivar)
5943 Results.data()[Results.size() - 1].Priority--;
5944 }
Douglas Gregor331faa02011-04-18 14:13:53 +00005945 }
Douglas Gregor5d649882009-11-18 22:32:06 +00005946 }
Douglas Gregor331faa02011-04-18 14:13:53 +00005947
5948 if (!SawSimilarlyNamedIvar) {
5949 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005950 // an ivar of the appropriate type.
5951 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00005952 typedef CodeCompletionResult Result;
5953 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005954 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
5955 Priority,CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00005956
Douglas Gregor75acd922011-09-27 23:30:47 +00005957 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005958 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00005959 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00005960 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5961 Results.AddResult(Result(Builder.TakeString(), Priority,
5962 CXCursor_ObjCIvarDecl));
5963 }
5964
Douglas Gregor5d649882009-11-18 22:32:06 +00005965 Results.ExitScope();
5966
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005967 HandleCodeCompleteResults(this, CodeCompleter,
5968 CodeCompletionContext::CCC_Other,
5969 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00005970}
Douglas Gregor636a61e2010-04-07 00:21:17 +00005971
Douglas Gregor416b5752010-08-25 01:08:01 +00005972// Mapping from selectors to the methods that implement that selector, along
5973// with the "in original class" flag.
5974typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5975 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00005976
5977/// \brief Find all of the methods that reside in the given container
5978/// (and its superclasses, protocols, etc.) that meet the given
5979/// criteria. Insert those methods into the map of known methods,
5980/// indexed by selector so they can be easily found.
5981static void FindImplementableMethods(ASTContext &Context,
5982 ObjCContainerDecl *Container,
5983 bool WantInstanceMethods,
5984 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00005985 KnownMethodsMap &KnownMethods,
5986 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00005987 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005988 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005989 if (!IFace->hasDefinition())
5990 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005991
5992 IFace = IFace->getDefinition();
5993 Container = IFace;
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005994
Douglas Gregor636a61e2010-04-07 00:21:17 +00005995 const ObjCList<ObjCProtocolDecl> &Protocols
5996 = IFace->getReferencedProtocols();
5997 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005998 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00005999 I != E; ++I)
6000 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006001 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006002
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006003 // Add methods from any class extensions and categories.
6004 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
6005 Cat = Cat->getNextClassCategory())
Fariborz Jahanian3bf0ded2010-06-22 23:20:40 +00006006 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
6007 WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006008 KnownMethods, false);
6009
6010 // Visit the superclass.
6011 if (IFace->getSuperClass())
6012 FindImplementableMethods(Context, IFace->getSuperClass(),
6013 WantInstanceMethods, ReturnType,
6014 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006015 }
6016
6017 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6018 // Recurse into protocols.
6019 const ObjCList<ObjCProtocolDecl> &Protocols
6020 = Category->getReferencedProtocols();
6021 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006022 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006023 I != E; ++I)
6024 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006025 KnownMethods, InOriginalClass);
6026
6027 // If this category is the original class, jump to the interface.
6028 if (InOriginalClass && Category->getClassInterface())
6029 FindImplementableMethods(Context, Category->getClassInterface(),
6030 WantInstanceMethods, ReturnType, KnownMethods,
6031 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006032 }
6033
6034 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006035 // Make sure we have a definition; that's what we'll walk.
6036 if (!Protocol->hasDefinition())
6037 return;
6038 Protocol = Protocol->getDefinition();
6039 Container = Protocol;
6040
6041 // Recurse into protocols.
6042 const ObjCList<ObjCProtocolDecl> &Protocols
6043 = Protocol->getReferencedProtocols();
6044 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6045 E = Protocols.end();
6046 I != E; ++I)
6047 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6048 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006049 }
6050
6051 // Add methods in this container. This operation occurs last because
6052 // we want the methods from this container to override any methods
6053 // we've previously seen with the same selector.
6054 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6055 MEnd = Container->meth_end();
6056 M != MEnd; ++M) {
David Blaikie2d7c57e2012-04-30 02:36:29 +00006057 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006058 if (!ReturnType.isNull() &&
David Blaikie2d7c57e2012-04-30 02:36:29 +00006059 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006060 continue;
6061
David Blaikie40ed2972012-06-06 20:45:41 +00006062 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006063 }
6064 }
6065}
6066
Douglas Gregor669a25a2011-02-17 00:22:45 +00006067/// \brief Add the parenthesized return or parameter type chunk to a code
6068/// completion string.
6069static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor29979142012-04-10 18:35:07 +00006070 unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006071 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006072 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006073 CodeCompletionBuilder &Builder) {
6074 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor29979142012-04-10 18:35:07 +00006075 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6076 if (!Quals.empty())
6077 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor75acd922011-09-27 23:30:47 +00006078 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006079 Builder.getAllocator()));
6080 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6081}
6082
6083/// \brief Determine whether the given class is or inherits from a class by
6084/// the given name.
6085static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006086 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006087 if (!Class)
6088 return false;
6089
6090 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6091 return true;
6092
6093 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6094}
6095
6096/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6097/// Key-Value Observing (KVO).
6098static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6099 bool IsInstanceMethod,
6100 QualType ReturnType,
6101 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006102 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006103 ResultBuilder &Results) {
6104 IdentifierInfo *PropName = Property->getIdentifier();
6105 if (!PropName || PropName->getLength() == 0)
6106 return;
6107
Douglas Gregor75acd922011-09-27 23:30:47 +00006108 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6109
Douglas Gregor669a25a2011-02-17 00:22:45 +00006110 // Builder that will create each code completion.
6111 typedef CodeCompletionResult Result;
6112 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006113 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor669a25a2011-02-17 00:22:45 +00006114
6115 // The selector table.
6116 SelectorTable &Selectors = Context.Selectors;
6117
6118 // The property name, copied into the code completion allocation region
6119 // on demand.
6120 struct KeyHolder {
6121 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006122 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006123 const char *CopiedKey;
6124
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006125 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006126 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6127
6128 operator const char *() {
6129 if (CopiedKey)
6130 return CopiedKey;
6131
6132 return CopiedKey = Allocator.CopyString(Key);
6133 }
6134 } Key(Allocator, PropName->getName());
6135
6136 // The uppercased name of the property name.
6137 std::string UpperKey = PropName->getName();
6138 if (!UpperKey.empty())
6139 UpperKey[0] = toupper(UpperKey[0]);
6140
6141 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6142 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6143 Property->getType());
6144 bool ReturnTypeMatchesVoid
6145 = ReturnType.isNull() || ReturnType->isVoidType();
6146
6147 // Add the normal accessor -(type)key.
6148 if (IsInstanceMethod &&
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006149 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006150 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6151 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006152 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6153 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006154
6155 Builder.AddTypedTextChunk(Key);
6156 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6157 CXCursor_ObjCInstanceMethodDecl));
6158 }
6159
6160 // If we have an integral or boolean property (or the user has provided
6161 // an integral or boolean return type), add the accessor -(type)isKey.
6162 if (IsInstanceMethod &&
6163 ((!ReturnType.isNull() &&
6164 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6165 (ReturnType.isNull() &&
6166 (Property->getType()->isIntegerType() ||
6167 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006168 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006169 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006170 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006171 if (ReturnType.isNull()) {
6172 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6173 Builder.AddTextChunk("BOOL");
6174 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6175 }
6176
6177 Builder.AddTypedTextChunk(
6178 Allocator.CopyString(SelectorId->getName()));
6179 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6180 CXCursor_ObjCInstanceMethodDecl));
6181 }
6182 }
6183
6184 // Add the normal mutator.
6185 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6186 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006187 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006188 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006189 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006190 if (ReturnType.isNull()) {
6191 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6192 Builder.AddTextChunk("void");
6193 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6194 }
6195
6196 Builder.AddTypedTextChunk(
6197 Allocator.CopyString(SelectorId->getName()));
6198 Builder.AddTypedTextChunk(":");
Douglas Gregor29979142012-04-10 18:35:07 +00006199 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6200 Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006201 Builder.AddTextChunk(Key);
6202 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6203 CXCursor_ObjCInstanceMethodDecl));
6204 }
6205 }
6206
6207 // Indexed and unordered accessors
6208 unsigned IndexedGetterPriority = CCP_CodePattern;
6209 unsigned IndexedSetterPriority = CCP_CodePattern;
6210 unsigned UnorderedGetterPriority = CCP_CodePattern;
6211 unsigned UnorderedSetterPriority = CCP_CodePattern;
6212 if (const ObjCObjectPointerType *ObjCPointer
6213 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6214 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6215 // If this interface type is not provably derived from a known
6216 // collection, penalize the corresponding completions.
6217 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6218 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6219 if (!InheritsFromClassNamed(IFace, "NSArray"))
6220 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6221 }
6222
6223 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6224 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6225 if (!InheritsFromClassNamed(IFace, "NSSet"))
6226 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6227 }
6228 }
6229 } else {
6230 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6231 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6232 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6233 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6234 }
6235
6236 // Add -(NSUInteger)countOf<key>
6237 if (IsInstanceMethod &&
6238 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006239 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006240 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006241 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006242 if (ReturnType.isNull()) {
6243 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6244 Builder.AddTextChunk("NSUInteger");
6245 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6246 }
6247
6248 Builder.AddTypedTextChunk(
6249 Allocator.CopyString(SelectorId->getName()));
6250 Results.AddResult(Result(Builder.TakeString(),
6251 std::min(IndexedGetterPriority,
6252 UnorderedGetterPriority),
6253 CXCursor_ObjCInstanceMethodDecl));
6254 }
6255 }
6256
6257 // Indexed getters
6258 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6259 if (IsInstanceMethod &&
6260 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006261 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006262 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006263 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006264 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006265 if (ReturnType.isNull()) {
6266 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6267 Builder.AddTextChunk("id");
6268 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6269 }
6270
6271 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6272 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6273 Builder.AddTextChunk("NSUInteger");
6274 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6275 Builder.AddTextChunk("index");
6276 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6277 CXCursor_ObjCInstanceMethodDecl));
6278 }
6279 }
6280
6281 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6282 if (IsInstanceMethod &&
6283 (ReturnType.isNull() ||
6284 (ReturnType->isObjCObjectPointerType() &&
6285 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6286 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6287 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006288 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006289 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006290 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006291 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006292 if (ReturnType.isNull()) {
6293 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6294 Builder.AddTextChunk("NSArray *");
6295 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6296 }
6297
6298 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6299 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6300 Builder.AddTextChunk("NSIndexSet *");
6301 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6302 Builder.AddTextChunk("indexes");
6303 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6304 CXCursor_ObjCInstanceMethodDecl));
6305 }
6306 }
6307
6308 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6309 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006310 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006311 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006312 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006313 &Context.Idents.get("range")
6314 };
6315
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006316 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006317 if (ReturnType.isNull()) {
6318 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6319 Builder.AddTextChunk("void");
6320 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6321 }
6322
6323 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6324 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6325 Builder.AddPlaceholderChunk("object-type");
6326 Builder.AddTextChunk(" **");
6327 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6328 Builder.AddTextChunk("buffer");
6329 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6330 Builder.AddTypedTextChunk("range:");
6331 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6332 Builder.AddTextChunk("NSRange");
6333 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6334 Builder.AddTextChunk("inRange");
6335 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6336 CXCursor_ObjCInstanceMethodDecl));
6337 }
6338 }
6339
6340 // Mutable indexed accessors
6341
6342 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6343 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006344 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006345 IdentifierInfo *SelectorIds[2] = {
6346 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006347 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006348 };
6349
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006350 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006351 if (ReturnType.isNull()) {
6352 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6353 Builder.AddTextChunk("void");
6354 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6355 }
6356
6357 Builder.AddTypedTextChunk("insertObject:");
6358 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6359 Builder.AddPlaceholderChunk("object-type");
6360 Builder.AddTextChunk(" *");
6361 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6362 Builder.AddTextChunk("object");
6363 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6364 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6365 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6366 Builder.AddPlaceholderChunk("NSUInteger");
6367 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6368 Builder.AddTextChunk("index");
6369 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6370 CXCursor_ObjCInstanceMethodDecl));
6371 }
6372 }
6373
6374 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6375 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006376 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006377 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006378 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006379 &Context.Idents.get("atIndexes")
6380 };
6381
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006382 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006383 if (ReturnType.isNull()) {
6384 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6385 Builder.AddTextChunk("void");
6386 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6387 }
6388
6389 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6390 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6391 Builder.AddTextChunk("NSArray *");
6392 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6393 Builder.AddTextChunk("array");
6394 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6395 Builder.AddTypedTextChunk("atIndexes:");
6396 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6397 Builder.AddPlaceholderChunk("NSIndexSet *");
6398 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6399 Builder.AddTextChunk("indexes");
6400 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6401 CXCursor_ObjCInstanceMethodDecl));
6402 }
6403 }
6404
6405 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6406 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006407 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006408 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006409 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006410 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006411 if (ReturnType.isNull()) {
6412 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6413 Builder.AddTextChunk("void");
6414 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6415 }
6416
6417 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6418 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6419 Builder.AddTextChunk("NSUInteger");
6420 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6421 Builder.AddTextChunk("index");
6422 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6423 CXCursor_ObjCInstanceMethodDecl));
6424 }
6425 }
6426
6427 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6428 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006429 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006430 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006431 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006432 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006433 if (ReturnType.isNull()) {
6434 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6435 Builder.AddTextChunk("void");
6436 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6437 }
6438
6439 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6440 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6441 Builder.AddTextChunk("NSIndexSet *");
6442 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6443 Builder.AddTextChunk("indexes");
6444 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6445 CXCursor_ObjCInstanceMethodDecl));
6446 }
6447 }
6448
6449 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6450 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006451 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006452 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006453 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006454 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006455 &Context.Idents.get("withObject")
6456 };
6457
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006458 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006459 if (ReturnType.isNull()) {
6460 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6461 Builder.AddTextChunk("void");
6462 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6463 }
6464
6465 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6466 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6467 Builder.AddPlaceholderChunk("NSUInteger");
6468 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6469 Builder.AddTextChunk("index");
6470 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6471 Builder.AddTypedTextChunk("withObject:");
6472 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6473 Builder.AddTextChunk("id");
6474 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6475 Builder.AddTextChunk("object");
6476 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6477 CXCursor_ObjCInstanceMethodDecl));
6478 }
6479 }
6480
6481 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6482 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006483 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006484 = (Twine("replace") + UpperKey + "AtIndexes").str();
6485 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006486 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006487 &Context.Idents.get(SelectorName1),
6488 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006489 };
6490
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006491 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006492 if (ReturnType.isNull()) {
6493 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6494 Builder.AddTextChunk("void");
6495 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6496 }
6497
6498 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6499 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6500 Builder.AddPlaceholderChunk("NSIndexSet *");
6501 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6502 Builder.AddTextChunk("indexes");
6503 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6504 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6505 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6506 Builder.AddTextChunk("NSArray *");
6507 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6508 Builder.AddTextChunk("array");
6509 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6510 CXCursor_ObjCInstanceMethodDecl));
6511 }
6512 }
6513
6514 // Unordered getters
6515 // - (NSEnumerator *)enumeratorOfKey
6516 if (IsInstanceMethod &&
6517 (ReturnType.isNull() ||
6518 (ReturnType->isObjCObjectPointerType() &&
6519 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6520 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6521 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006522 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006523 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006524 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006525 if (ReturnType.isNull()) {
6526 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6527 Builder.AddTextChunk("NSEnumerator *");
6528 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6529 }
6530
6531 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6532 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6533 CXCursor_ObjCInstanceMethodDecl));
6534 }
6535 }
6536
6537 // - (type *)memberOfKey:(type *)object
6538 if (IsInstanceMethod &&
6539 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006540 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006541 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006542 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006543 if (ReturnType.isNull()) {
6544 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6545 Builder.AddPlaceholderChunk("object-type");
6546 Builder.AddTextChunk(" *");
6547 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6548 }
6549
6550 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6551 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6552 if (ReturnType.isNull()) {
6553 Builder.AddPlaceholderChunk("object-type");
6554 Builder.AddTextChunk(" *");
6555 } else {
6556 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006557 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006558 Builder.getAllocator()));
6559 }
6560 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6561 Builder.AddTextChunk("object");
6562 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6563 CXCursor_ObjCInstanceMethodDecl));
6564 }
6565 }
6566
6567 // Mutable unordered accessors
6568 // - (void)addKeyObject:(type *)object
6569 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006570 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006571 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006572 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006573 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006574 if (ReturnType.isNull()) {
6575 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6576 Builder.AddTextChunk("void");
6577 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6578 }
6579
6580 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6581 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6582 Builder.AddPlaceholderChunk("object-type");
6583 Builder.AddTextChunk(" *");
6584 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6585 Builder.AddTextChunk("object");
6586 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6587 CXCursor_ObjCInstanceMethodDecl));
6588 }
6589 }
6590
6591 // - (void)addKey:(NSSet *)objects
6592 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006593 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006594 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006595 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006596 if (ReturnType.isNull()) {
6597 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6598 Builder.AddTextChunk("void");
6599 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6600 }
6601
6602 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6603 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6604 Builder.AddTextChunk("NSSet *");
6605 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6606 Builder.AddTextChunk("objects");
6607 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6608 CXCursor_ObjCInstanceMethodDecl));
6609 }
6610 }
6611
6612 // - (void)removeKeyObject:(type *)object
6613 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006614 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006615 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006616 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006617 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-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.AddPlaceholderChunk("object-type");
6627 Builder.AddTextChunk(" *");
6628 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6629 Builder.AddTextChunk("object");
6630 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6631 CXCursor_ObjCInstanceMethodDecl));
6632 }
6633 }
6634
6635 // - (void)removeKey:(NSSet *)objects
6636 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006637 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006638 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006639 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006640 if (ReturnType.isNull()) {
6641 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6642 Builder.AddTextChunk("void");
6643 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6644 }
6645
6646 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6647 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6648 Builder.AddTextChunk("NSSet *");
6649 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6650 Builder.AddTextChunk("objects");
6651 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6652 CXCursor_ObjCInstanceMethodDecl));
6653 }
6654 }
6655
6656 // - (void)intersectKey:(NSSet *)objects
6657 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006658 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006659 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006660 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006661 if (ReturnType.isNull()) {
6662 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6663 Builder.AddTextChunk("void");
6664 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6665 }
6666
6667 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6668 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6669 Builder.AddTextChunk("NSSet *");
6670 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6671 Builder.AddTextChunk("objects");
6672 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6673 CXCursor_ObjCInstanceMethodDecl));
6674 }
6675 }
6676
6677 // Key-Value Observing
6678 // + (NSSet *)keyPathsForValuesAffectingKey
6679 if (!IsInstanceMethod &&
6680 (ReturnType.isNull() ||
6681 (ReturnType->isObjCObjectPointerType() &&
6682 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6683 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6684 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006685 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006686 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006687 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006688 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006689 if (ReturnType.isNull()) {
6690 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6691 Builder.AddTextChunk("NSSet *");
6692 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6693 }
6694
6695 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6696 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00006697 CXCursor_ObjCClassMethodDecl));
6698 }
6699 }
6700
6701 // + (BOOL)automaticallyNotifiesObserversForKey
6702 if (!IsInstanceMethod &&
6703 (ReturnType.isNull() ||
6704 ReturnType->isIntegerType() ||
6705 ReturnType->isBooleanType())) {
6706 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006707 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00006708 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6709 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6710 if (ReturnType.isNull()) {
6711 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6712 Builder.AddTextChunk("BOOL");
6713 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6714 }
6715
6716 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6717 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6718 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00006719 }
6720 }
6721}
6722
Douglas Gregor636a61e2010-04-07 00:21:17 +00006723void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6724 bool IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006725 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006726 // Determine the return type of the method we're declaring, if
6727 // provided.
6728 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006729 Decl *IDecl = 0;
6730 if (CurContext->isObjCContainer()) {
6731 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6732 IDecl = cast<Decl>(OCD);
6733 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006734 // Determine where we should start searching for methods.
6735 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006736 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00006737 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006738 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6739 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006740 IsInImplementation = true;
6741 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006742 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006743 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006744 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006745 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00006746 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006747 }
6748
6749 if (!SearchDecl && S) {
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006750 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006751 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006752 }
6753
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006754 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006755 HandleCodeCompleteResults(this, CodeCompleter,
6756 CodeCompletionContext::CCC_Other,
6757 0, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006758 return;
6759 }
6760
6761 // Find all of the methods that we could declare/implement here.
6762 KnownMethodsMap KnownMethods;
6763 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006764 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006765
Douglas Gregor636a61e2010-04-07 00:21:17 +00006766 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00006767 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006768 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006769 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006770 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006771 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00006772 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006773 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6774 MEnd = KnownMethods.end();
6775 M != MEnd; ++M) {
Douglas Gregor416b5752010-08-25 01:08:01 +00006776 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006777 CodeCompletionBuilder Builder(Results.getAllocator(),
6778 Results.getCodeCompletionTUInfo());
Douglas Gregor636a61e2010-04-07 00:21:17 +00006779
6780 // If the result type was not already provided, add it to the
6781 // pattern as (type).
Douglas Gregor669a25a2011-02-17 00:22:45 +00006782 if (ReturnType.isNull())
Douglas Gregor29979142012-04-10 18:35:07 +00006783 AddObjCPassingTypeChunk(Method->getResultType(),
6784 Method->getObjCDeclQualifier(),
6785 Context, Policy,
6786 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006787
6788 Selector Sel = Method->getSelector();
6789
6790 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006791 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006792 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006793
6794 // Add parameters to the pattern.
6795 unsigned I = 0;
6796 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6797 PEnd = Method->param_end();
6798 P != PEnd; (void)++P, ++I) {
6799 // Add the part of the selector name.
6800 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006801 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00006802 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006803 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6804 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006805 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006806 } else
6807 break;
6808
6809 // Add the parameter type.
Douglas Gregor29979142012-04-10 18:35:07 +00006810 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6811 (*P)->getObjCDeclQualifier(),
6812 Context, Policy,
Douglas Gregor75acd922011-09-27 23:30:47 +00006813 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006814
6815 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006816 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006817 }
6818
6819 if (Method->isVariadic()) {
6820 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006821 Builder.AddChunk(CodeCompletionString::CK_Comma);
6822 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00006823 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00006824
Douglas Gregord37c59d2010-05-28 00:57:46 +00006825 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006826 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006827 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6828 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6829 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006830 if (!Method->getResultType()->isVoidType()) {
6831 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006832 Builder.AddTextChunk("return");
6833 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6834 Builder.AddPlaceholderChunk("expression");
6835 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006836 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006837 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00006838
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006839 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6840 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006841 }
6842
Douglas Gregor416b5752010-08-25 01:08:01 +00006843 unsigned Priority = CCP_CodePattern;
6844 if (!M->second.second)
6845 Priority += CCD_InBaseClass;
6846
Douglas Gregor78254c82012-03-27 23:34:16 +00006847 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006848 }
6849
Douglas Gregor669a25a2011-02-17 00:22:45 +00006850 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6851 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006852 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006853 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006854 Containers.push_back(SearchDecl);
6855
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006856 VisitedSelectorSet KnownSelectors;
6857 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6858 MEnd = KnownMethods.end();
6859 M != MEnd; ++M)
6860 KnownSelectors.insert(M->first);
6861
6862
Douglas Gregor669a25a2011-02-17 00:22:45 +00006863 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6864 if (!IFace)
6865 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6866 IFace = Category->getClassInterface();
6867
6868 if (IFace) {
6869 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6870 Category = Category->getNextClassCategory())
6871 Containers.push_back(Category);
6872 }
6873
6874 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6875 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6876 PEnd = Containers[I]->prop_end();
6877 P != PEnd; ++P) {
David Blaikie40ed2972012-06-06 20:45:41 +00006878 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006879 KnownSelectors, Results);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006880 }
6881 }
6882 }
6883
Douglas Gregor636a61e2010-04-07 00:21:17 +00006884 Results.ExitScope();
6885
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006886 HandleCodeCompleteResults(this, CodeCompleter,
6887 CodeCompletionContext::CCC_Other,
6888 Results.data(),Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00006889}
Douglas Gregor95887f92010-07-08 23:20:03 +00006890
6891void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6892 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00006893 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00006894 ParsedType ReturnTy,
Douglas Gregor95887f92010-07-08 23:20:03 +00006895 IdentifierInfo **SelIdents,
6896 unsigned NumSelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00006897 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006898 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00006899 if (ExternalSource) {
6900 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6901 I != N; ++I) {
6902 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006903 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00006904 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00006905
6906 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00006907 }
6908 }
6909
6910 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00006911 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006912 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006913 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006914 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00006915
6916 if (ReturnTy)
6917 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00006918
Douglas Gregor95887f92010-07-08 23:20:03 +00006919 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006920 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6921 MEnd = MethodPool.end();
6922 M != MEnd; ++M) {
6923 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6924 &M->second.second;
6925 MethList && MethList->Method;
Douglas Gregor95887f92010-07-08 23:20:03 +00006926 MethList = MethList->Next) {
6927 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6928 NumSelIdents))
6929 continue;
6930
Douglas Gregor45879692010-07-08 23:37:41 +00006931 if (AtParameterName) {
6932 // Suggest parameter names we've seen before.
6933 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6934 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6935 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006936 CodeCompletionBuilder Builder(Results.getAllocator(),
6937 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006938 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006939 Param->getIdentifier()->getName()));
6940 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00006941 }
6942 }
6943
6944 continue;
6945 }
6946
Douglas Gregor95887f92010-07-08 23:20:03 +00006947 Result R(MethList->Method, 0);
6948 R.StartParameter = NumSelIdents;
6949 R.AllParametersAreInformative = false;
6950 R.DeclaringEntity = true;
6951 Results.MaybeAddResult(R, CurContext);
6952 }
6953 }
6954
6955 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006956 HandleCodeCompleteResults(this, CodeCompleter,
6957 CodeCompletionContext::CCC_Other,
6958 Results.data(),Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00006959}
Douglas Gregorb14904c2010-08-13 22:48:40 +00006960
Douglas Gregorec00a262010-08-24 22:20:20 +00006961void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006962 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006963 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00006964 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006965 Results.EnterNewScope();
6966
6967 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006968 CodeCompletionBuilder Builder(Results.getAllocator(),
6969 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006970 Builder.AddTypedTextChunk("if");
6971 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6972 Builder.AddPlaceholderChunk("condition");
6973 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006974
6975 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006976 Builder.AddTypedTextChunk("ifdef");
6977 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6978 Builder.AddPlaceholderChunk("macro");
6979 Results.AddResult(Builder.TakeString());
6980
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006981 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006982 Builder.AddTypedTextChunk("ifndef");
6983 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6984 Builder.AddPlaceholderChunk("macro");
6985 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006986
6987 if (InConditional) {
6988 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006989 Builder.AddTypedTextChunk("elif");
6990 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6991 Builder.AddPlaceholderChunk("condition");
6992 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006993
6994 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006995 Builder.AddTypedTextChunk("else");
6996 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006997
6998 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006999 Builder.AddTypedTextChunk("endif");
7000 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007001 }
7002
7003 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007004 Builder.AddTypedTextChunk("include");
7005 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7006 Builder.AddTextChunk("\"");
7007 Builder.AddPlaceholderChunk("header");
7008 Builder.AddTextChunk("\"");
7009 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007010
7011 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007012 Builder.AddTypedTextChunk("include");
7013 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7014 Builder.AddTextChunk("<");
7015 Builder.AddPlaceholderChunk("header");
7016 Builder.AddTextChunk(">");
7017 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007018
7019 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007020 Builder.AddTypedTextChunk("define");
7021 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7022 Builder.AddPlaceholderChunk("macro");
7023 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007024
7025 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007026 Builder.AddTypedTextChunk("define");
7027 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7028 Builder.AddPlaceholderChunk("macro");
7029 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7030 Builder.AddPlaceholderChunk("args");
7031 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7032 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007033
7034 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007035 Builder.AddTypedTextChunk("undef");
7036 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7037 Builder.AddPlaceholderChunk("macro");
7038 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007039
7040 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007041 Builder.AddTypedTextChunk("line");
7042 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7043 Builder.AddPlaceholderChunk("number");
7044 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007045
7046 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007047 Builder.AddTypedTextChunk("line");
7048 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7049 Builder.AddPlaceholderChunk("number");
7050 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7051 Builder.AddTextChunk("\"");
7052 Builder.AddPlaceholderChunk("filename");
7053 Builder.AddTextChunk("\"");
7054 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007055
7056 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007057 Builder.AddTypedTextChunk("error");
7058 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7059 Builder.AddPlaceholderChunk("message");
7060 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007061
7062 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007063 Builder.AddTypedTextChunk("pragma");
7064 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7065 Builder.AddPlaceholderChunk("arguments");
7066 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007067
David Blaikiebbafb8a2012-03-11 07:00:24 +00007068 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007069 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007070 Builder.AddTypedTextChunk("import");
7071 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7072 Builder.AddTextChunk("\"");
7073 Builder.AddPlaceholderChunk("header");
7074 Builder.AddTextChunk("\"");
7075 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007076
7077 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007078 Builder.AddTypedTextChunk("import");
7079 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7080 Builder.AddTextChunk("<");
7081 Builder.AddPlaceholderChunk("header");
7082 Builder.AddTextChunk(">");
7083 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007084 }
7085
7086 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007087 Builder.AddTypedTextChunk("include_next");
7088 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7089 Builder.AddTextChunk("\"");
7090 Builder.AddPlaceholderChunk("header");
7091 Builder.AddTextChunk("\"");
7092 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007093
7094 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007095 Builder.AddTypedTextChunk("include_next");
7096 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7097 Builder.AddTextChunk("<");
7098 Builder.AddPlaceholderChunk("header");
7099 Builder.AddTextChunk(">");
7100 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007101
7102 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007103 Builder.AddTypedTextChunk("warning");
7104 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7105 Builder.AddPlaceholderChunk("message");
7106 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007107
7108 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7109 // completions for them. And __include_macros is a Clang-internal extension
7110 // that we don't want to encourage anyone to use.
7111
7112 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7113 Results.ExitScope();
7114
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007115 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0de55ce2010-08-25 18:41:16 +00007116 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007117 Results.data(), Results.size());
7118}
7119
7120void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007121 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007122 S->getFnParent()? Sema::PCC_RecoveryInFunction
7123 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007124}
7125
Douglas Gregorec00a262010-08-24 22:20:20 +00007126void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007127 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007128 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007129 IsDefinition? CodeCompletionContext::CCC_MacroName
7130 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007131 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7132 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007133 CodeCompletionBuilder Builder(Results.getAllocator(),
7134 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00007135 Results.EnterNewScope();
7136 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7137 MEnd = PP.macro_end();
7138 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007139 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007140 M->first->getName()));
7141 Results.AddResult(Builder.TakeString());
Douglas Gregor12785102010-08-24 20:21:13 +00007142 }
7143 Results.ExitScope();
7144 } else if (IsDefinition) {
7145 // FIXME: Can we detect when the user just wrote an include guard above?
7146 }
7147
Douglas Gregor0ac41382010-09-23 23:01:17 +00007148 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007149 Results.data(), Results.size());
7150}
7151
Douglas Gregorec00a262010-08-24 22:20:20 +00007152void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007153 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007154 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007155 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007156
7157 if (!CodeCompleter || CodeCompleter->includeMacros())
7158 AddMacroResults(PP, Results);
7159
7160 // defined (<macro>)
7161 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007162 CodeCompletionBuilder Builder(Results.getAllocator(),
7163 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007164 Builder.AddTypedTextChunk("defined");
7165 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7166 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7167 Builder.AddPlaceholderChunk("macro");
7168 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7169 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007170 Results.ExitScope();
7171
7172 HandleCodeCompleteResults(this, CodeCompleter,
7173 CodeCompletionContext::CCC_PreprocessorExpression,
7174 Results.data(), Results.size());
7175}
7176
7177void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7178 IdentifierInfo *Macro,
7179 MacroInfo *MacroInfo,
7180 unsigned Argument) {
7181 // FIXME: In the future, we could provide "overload" results, much like we
7182 // do for function calls.
7183
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007184 // Now just ignore this. There will be another code-completion callback
7185 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007186}
7187
Douglas Gregor11583702010-08-25 17:04:25 +00007188void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007189 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007190 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor11583702010-08-25 17:04:25 +00007191 0, 0);
7192}
7193
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007194void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007195 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007196 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007197 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7198 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00007199 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7200 CodeCompletionDeclConsumer Consumer(Builder,
7201 Context.getTranslationUnitDecl());
7202 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7203 Consumer);
7204 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00007205
7206 if (!CodeCompleter || CodeCompleter->includeMacros())
7207 AddMacroResults(PP, Builder);
7208
7209 Results.clear();
7210 Results.insert(Results.end(),
7211 Builder.data(), Builder.data() + Builder.size());
7212}