blob: 3fd66ec04293d75545213fcdc319006db6b52a2e [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;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000126
127 /// \brief If non-NULL, a filter function used to remove any code-completion
128 /// results that are not desirable.
129 LookupFilter Filter;
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000130
131 /// \brief Whether we should allow declarations as
132 /// nested-name-specifiers that would otherwise be filtered out.
133 bool AllowNestedNameSpecifiers;
134
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000135 /// \brief If set, the type that we would prefer our resulting value
136 /// declarations to have.
137 ///
138 /// Closely matching the preferred type gives a boost to a result's
139 /// priority.
140 CanQualType PreferredType;
141
Douglas Gregor3545ff42009-09-21 16:56:56 +0000142 /// \brief A list of shadow maps, which is used to model name hiding at
143 /// different levels of, e.g., the inheritance hierarchy.
144 std::list<ShadowMap> ShadowMaps;
145
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000146 /// \brief If we're potentially referring to a C++ member function, the set
147 /// of qualifiers applied to the object type.
148 Qualifiers ObjectTypeQualifiers;
149
150 /// \brief Whether the \p ObjectTypeQualifiers field is active.
151 bool HasObjectTypeQualifiers;
152
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000153 /// \brief The selector that we prefer.
154 Selector PreferredSelector;
155
Douglas Gregor05fcf842010-11-02 20:36:02 +0000156 /// \brief The completion context in which we are gathering results.
Douglas Gregor50832e02010-09-20 22:39:41 +0000157 CodeCompletionContext CompletionContext;
158
Douglas Gregor05fcf842010-11-02 20:36:02 +0000159 /// \brief If we are in an instance method definition, the @implementation
160 /// object.
161 ObjCImplementationDecl *ObjCImplementation;
162
Douglas Gregor50832e02010-09-20 22:39:41 +0000163 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor95887f92010-07-08 23:20:03 +0000164
Douglas Gregor0212fd72010-09-21 16:06:22 +0000165 void MaybeAddConstructorResults(Result R);
166
Douglas Gregor3545ff42009-09-21 16:56:56 +0000167 public:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000168 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Douglas Gregor0ac41382010-09-23 23:01:17 +0000169 const CodeCompletionContext &CompletionContext,
170 LookupFilter Filter = 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000171 : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
172 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregor05fcf842010-11-02 20:36:02 +0000173 CompletionContext(CompletionContext),
174 ObjCImplementation(0)
175 {
176 // If this is an Objective-C instance method definition, dig out the
177 // corresponding implementation.
178 switch (CompletionContext.getKind()) {
179 case CodeCompletionContext::CCC_Expression:
180 case CodeCompletionContext::CCC_ObjCMessageReceiver:
181 case CodeCompletionContext::CCC_ParenthesizedExpression:
182 case CodeCompletionContext::CCC_Statement:
183 case CodeCompletionContext::CCC_Recovery:
184 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
185 if (Method->isInstanceMethod())
186 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
187 ObjCImplementation = Interface->getImplementation();
188 break;
189
190 default:
191 break;
192 }
193 }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000194
Douglas Gregorf64acca2010-05-25 21:41:55 +0000195 /// \brief Whether we should include code patterns in the completion
196 /// results.
197 bool includeCodePatterns() const {
198 return SemaRef.CodeCompleter &&
Douglas Gregorac322ec2010-08-27 21:18:54 +0000199 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregorf64acca2010-05-25 21:41:55 +0000200 }
201
Douglas Gregor3545ff42009-09-21 16:56:56 +0000202 /// \brief Set the filter used for code-completion results.
203 void setFilter(LookupFilter Filter) {
204 this->Filter = Filter;
205 }
206
Douglas Gregor3545ff42009-09-21 16:56:56 +0000207 Result *data() { return Results.empty()? 0 : &Results.front(); }
208 unsigned size() const { return Results.size(); }
209 bool empty() const { return Results.empty(); }
210
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000211 /// \brief Specify the preferred type.
212 void setPreferredType(QualType T) {
213 PreferredType = SemaRef.Context.getCanonicalType(T);
214 }
215
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000216 /// \brief Set the cv-qualifiers on the object type, for us in filtering
217 /// calls to member functions.
218 ///
219 /// When there are qualifiers in this set, they will be used to filter
220 /// out member functions that aren't available (because there will be a
221 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
222 /// match.
223 void setObjectTypeQualifiers(Qualifiers Quals) {
224 ObjectTypeQualifiers = Quals;
225 HasObjectTypeQualifiers = true;
226 }
227
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000228 /// \brief Set the preferred selector.
229 ///
230 /// When an Objective-C method declaration result is added, and that
231 /// method's selector matches this preferred selector, we give that method
232 /// a slight priority boost.
233 void setPreferredSelector(Selector Sel) {
234 PreferredSelector = Sel;
235 }
Douglas Gregor05fcf842010-11-02 20:36:02 +0000236
Douglas Gregor50832e02010-09-20 22:39:41 +0000237 /// \brief Retrieve the code-completion context for which results are
238 /// being collected.
239 const CodeCompletionContext &getCompletionContext() const {
240 return CompletionContext;
241 }
242
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000243 /// \brief Specify whether nested-name-specifiers are allowed.
244 void allowNestedNameSpecifiers(bool Allow = true) {
245 AllowNestedNameSpecifiers = Allow;
246 }
247
Douglas Gregor74661272010-09-21 00:03:25 +0000248 /// \brief Return the semantic analysis object for which we are collecting
249 /// code completion results.
250 Sema &getSema() const { return SemaRef; }
251
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000252 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +0000253 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Douglas Gregorb278aaf2011-02-01 19:23:04 +0000254
Douglas Gregor7c208612010-01-14 00:20:49 +0000255 /// \brief Determine whether the given declaration is at all interesting
256 /// as a code-completion result.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000257 ///
258 /// \param ND the declaration that we are inspecting.
259 ///
260 /// \param AsNestedNameSpecifier will be set true if this declaration is
261 /// only interesting when it is a nested-name-specifier.
262 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregore0717ab2010-01-14 00:41:07 +0000263
264 /// \brief Check whether the result is hidden by the Hiding declaration.
265 ///
266 /// \returns true if the result is hidden and cannot be found, false if
267 /// the hidden result could still be found. When false, \p R may be
268 /// modified to describe how the result can be found (e.g., via extra
269 /// qualification).
270 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
271 NamedDecl *Hiding);
272
Douglas Gregor3545ff42009-09-21 16:56:56 +0000273 /// \brief Add a new result to this result set (if it isn't already in one
274 /// of the shadow maps), or replace an existing result (for, e.g., a
275 /// redeclaration).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000276 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000277 /// \param R the result to add (if it is unique).
Douglas Gregor2af2f672009-09-21 20:12:40 +0000278 ///
Douglas Gregord8c61782012-02-15 15:34:24 +0000279 /// \param CurContext the context in which this result will be named.
Douglas Gregor2af2f672009-09-21 20:12:40 +0000280 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000281
Douglas Gregorc580c522010-01-14 01:09:38 +0000282 /// \brief Add a new result to this result set, where we already know
283 /// the hiding declation (if any).
284 ///
285 /// \param R the result to add (if it is unique).
286 ///
287 /// \param CurContext the context in which this result will be named.
288 ///
289 /// \param Hiding the declaration that hides the result.
Douglas Gregor09bbc652010-01-14 15:47:35 +0000290 ///
291 /// \param InBaseClass whether the result was found in a base
292 /// class of the searched context.
293 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
294 bool InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +0000295
Douglas Gregor78a21012010-01-14 16:01:26 +0000296 /// \brief Add a new non-declaration result to this result set.
297 void AddResult(Result R);
298
Douglas Gregor3545ff42009-09-21 16:56:56 +0000299 /// \brief Enter into a new scope.
300 void EnterNewScope();
301
302 /// \brief Exit from the current scope.
303 void ExitScope();
304
Douglas Gregorbaf69612009-11-18 04:19:12 +0000305 /// \brief Ignore this declaration, if it is seen again.
306 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
307
Douglas Gregor3545ff42009-09-21 16:56:56 +0000308 /// \name Name lookup predicates
309 ///
310 /// These predicates can be passed to the name lookup functions to filter the
311 /// results of name lookup. All of the predicates have the same type, so that
312 ///
313 //@{
Douglas Gregor9d64c5e2009-09-21 20:51:25 +0000314 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor70febae2010-05-28 00:49:12 +0000315 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregor85b50632010-07-28 21:50:18 +0000316 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor504a6ae2010-01-10 23:08:15 +0000317 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000318 bool IsNestedNameSpecifier(NamedDecl *ND) const;
319 bool IsEnum(NamedDecl *ND) const;
320 bool IsClassOrStruct(NamedDecl *ND) const;
321 bool IsUnion(NamedDecl *ND) const;
322 bool IsNamespace(NamedDecl *ND) const;
323 bool IsNamespaceOrAlias(NamedDecl *ND) const;
324 bool IsType(NamedDecl *ND) const;
Douglas Gregore412a5a2009-09-23 22:26:46 +0000325 bool IsMember(NamedDecl *ND) const;
Douglas Gregor2b8162b2010-01-14 16:08:12 +0000326 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregora817a192010-05-27 23:06:34 +0000327 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregord8c61782012-02-15 15:34:24 +0000328 bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
Douglas Gregor68762e72010-08-23 21:17:50 +0000329 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor0ac41382010-09-23 23:01:17 +0000330 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000331 //@}
332 };
333}
334
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000335class ResultBuilder::ShadowMapEntry::iterator {
336 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
337 unsigned SingleDeclIndex;
338
339public:
340 typedef DeclIndexPair value_type;
341 typedef value_type reference;
342 typedef std::ptrdiff_t difference_type;
343 typedef std::input_iterator_tag iterator_category;
344
345 class pointer {
346 DeclIndexPair Value;
347
348 public:
349 pointer(const DeclIndexPair &Value) : Value(Value) { }
350
351 const DeclIndexPair *operator->() const {
352 return &Value;
353 }
354 };
355
356 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
357
358 iterator(NamedDecl *SingleDecl, unsigned Index)
359 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
360
361 iterator(const DeclIndexPair *Iterator)
362 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
363
364 iterator &operator++() {
365 if (DeclOrIterator.is<NamedDecl *>()) {
366 DeclOrIterator = (NamedDecl *)0;
367 SingleDeclIndex = 0;
368 return *this;
369 }
370
371 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
372 ++I;
373 DeclOrIterator = I;
374 return *this;
375 }
376
Chris Lattner9795b392010-09-04 18:12:20 +0000377 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000378 iterator tmp(*this);
379 ++(*this);
380 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000381 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000382
383 reference operator*() const {
384 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
385 return reference(ND, SingleDeclIndex);
386
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000387 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000388 }
389
390 pointer operator->() const {
391 return pointer(**this);
392 }
393
394 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000395 return X.DeclOrIterator.getOpaqueValue()
396 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000397 X.SingleDeclIndex == Y.SingleDeclIndex;
398 }
399
400 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000401 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000402 }
403};
404
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000405ResultBuilder::ShadowMapEntry::iterator
406ResultBuilder::ShadowMapEntry::begin() const {
407 if (DeclOrVector.isNull())
408 return iterator();
409
410 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
411 return iterator(ND, SingleDeclIndex);
412
413 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
414}
415
416ResultBuilder::ShadowMapEntry::iterator
417ResultBuilder::ShadowMapEntry::end() const {
418 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
419 return iterator();
420
421 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
422}
423
Douglas Gregor2af2f672009-09-21 20:12:40 +0000424/// \brief Compute the qualification required to get from the current context
425/// (\p CurContext) to the target context (\p TargetContext).
426///
427/// \param Context the AST context in which the qualification will be used.
428///
429/// \param CurContext the context where an entity is being named, which is
430/// typically based on the current scope.
431///
432/// \param TargetContext the context in which the named entity actually
433/// resides.
434///
435/// \returns a nested name specifier that refers into the target context, or
436/// NULL if no qualification is needed.
437static NestedNameSpecifier *
438getRequiredQualification(ASTContext &Context,
439 DeclContext *CurContext,
440 DeclContext *TargetContext) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +0000441 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000442
443 for (DeclContext *CommonAncestor = TargetContext;
444 CommonAncestor && !CommonAncestor->Encloses(CurContext);
445 CommonAncestor = CommonAncestor->getLookupParent()) {
446 if (CommonAncestor->isTransparentContext() ||
447 CommonAncestor->isFunctionOrMethod())
448 continue;
449
450 TargetParents.push_back(CommonAncestor);
451 }
452
453 NestedNameSpecifier *Result = 0;
454 while (!TargetParents.empty()) {
455 DeclContext *Parent = TargetParents.back();
456 TargetParents.pop_back();
457
Douglas Gregor68762e72010-08-23 21:17:50 +0000458 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
459 if (!Namespace->getIdentifier())
460 continue;
461
Douglas Gregor2af2f672009-09-21 20:12:40 +0000462 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregor68762e72010-08-23 21:17:50 +0000463 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000464 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
465 Result = NestedNameSpecifier::Create(Context, Result,
466 false,
467 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor9eb77012009-11-07 00:00:49 +0000468 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000469 return Result;
470}
471
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000472bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
473 bool &AsNestedNameSpecifier) const {
474 AsNestedNameSpecifier = false;
475
Douglas Gregor7c208612010-01-14 00:20:49 +0000476 ND = ND->getUnderlyingDecl();
477 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregor58acf322009-10-09 22:16:47 +0000478
479 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000480 if (!ND->getDeclName())
481 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000482
483 // Friend declarations and declarations introduced due to friends are never
484 // added as results.
John McCallbbbbe4e2010-03-11 07:50:04 +0000485 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregor7c208612010-01-14 00:20:49 +0000486 return false;
487
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000488 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000489 if (isa<ClassTemplateSpecializationDecl>(ND) ||
490 isa<ClassTemplatePartialSpecializationDecl>(ND))
491 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000492
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000493 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000494 if (isa<UsingDecl>(ND))
495 return false;
496
497 // Some declarations have reserved names that we don't want to ever show.
498 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000499 // __va_list_tag is a freak of nature. Find it and skip it.
500 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregor7c208612010-01-14 00:20:49 +0000501 return false;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000502
Douglas Gregor58acf322009-10-09 22:16:47 +0000503 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor9f1570d2010-07-14 17:44:04 +0000504 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbar2c422dc92009-10-18 20:26:12 +0000505 //
506 // FIXME: Add predicate for this.
Douglas Gregor58acf322009-10-09 22:16:47 +0000507 if (Id->getLength() >= 2) {
Daniel Dunbar2c422dc92009-10-18 20:26:12 +0000508 const char *Name = Id->getNameStart();
Douglas Gregor58acf322009-10-09 22:16:47 +0000509 if (Name[0] == '_' &&
Douglas Gregor9f1570d2010-07-14 17:44:04 +0000510 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
511 (ND->getLocation().isInvalid() ||
512 SemaRef.SourceMgr.isInSystemHeader(
513 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregor7c208612010-01-14 00:20:49 +0000514 return false;
Douglas Gregor58acf322009-10-09 22:16:47 +0000515 }
Douglas Gregor3545ff42009-09-21 16:56:56 +0000516 }
Douglas Gregor0212fd72010-09-21 16:06:22 +0000517
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000518 // Skip out-of-line declarations and definitions.
519 // NOTE: Unless it's an Objective-C property, method, or ivar, where
520 // the contexts can be messy.
521 if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) &&
522 !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) ||
523 isa<ObjCMethodDecl>(ND)))
524 return false;
525
Douglas Gregor59cab552010-08-16 23:05:20 +0000526 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
527 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
528 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor0ac41382010-09-23 23:01:17 +0000529 Filter != &ResultBuilder::IsNamespaceOrAlias &&
530 Filter != 0))
Douglas Gregor59cab552010-08-16 23:05:20 +0000531 AsNestedNameSpecifier = true;
532
Douglas Gregor3545ff42009-09-21 16:56:56 +0000533 // Filter out any unwanted results.
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000534 if (Filter && !(this->*Filter)(ND)) {
535 // Check whether it is interesting as a nested-name-specifier.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000536 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000537 IsNestedNameSpecifier(ND) &&
538 (Filter != &ResultBuilder::IsMember ||
539 (isa<CXXRecordDecl>(ND) &&
540 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
541 AsNestedNameSpecifier = true;
542 return true;
543 }
544
Douglas Gregor7c208612010-01-14 00:20:49 +0000545 return false;
Douglas Gregor59cab552010-08-16 23:05:20 +0000546 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000547 // ... then it must be interesting!
548 return true;
549}
550
Douglas Gregore0717ab2010-01-14 00:41:07 +0000551bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
552 NamedDecl *Hiding) {
553 // In C, there is no way to refer to a hidden name.
554 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
555 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000556 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000557 return true;
558
Sebastian Redl50c68252010-08-31 00:36:30 +0000559 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregore0717ab2010-01-14 00:41:07 +0000560
561 // There is no way to qualify a name declared in a function or method.
562 if (HiddenCtx->isFunctionOrMethod())
563 return true;
564
Sebastian Redl50c68252010-08-31 00:36:30 +0000565 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000566 return true;
567
568 // We can refer to the result with the appropriate qualification. Do it.
569 R.Hidden = true;
570 R.QualifierIsInformative = false;
571
572 if (!R.Qualifier)
573 R.Qualifier = getRequiredQualification(SemaRef.Context,
574 CurContext,
575 R.Declaration->getDeclContext());
576 return false;
577}
578
Douglas Gregor95887f92010-07-08 23:20:03 +0000579/// \brief A simplified classification of types used to determine whether two
580/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000581SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000582 switch (T->getTypeClass()) {
583 case Type::Builtin:
584 switch (cast<BuiltinType>(T)->getKind()) {
585 case BuiltinType::Void:
586 return STC_Void;
587
588 case BuiltinType::NullPtr:
589 return STC_Pointer;
590
591 case BuiltinType::Overload:
592 case BuiltinType::Dependent:
Douglas Gregor95887f92010-07-08 23:20:03 +0000593 return STC_Other;
594
595 case BuiltinType::ObjCId:
596 case BuiltinType::ObjCClass:
597 case BuiltinType::ObjCSel:
598 return STC_ObjectiveC;
599
600 default:
601 return STC_Arithmetic;
602 }
David Blaikie8a40f702012-01-17 06:56:22 +0000603
Douglas Gregor95887f92010-07-08 23:20:03 +0000604 case Type::Complex:
605 return STC_Arithmetic;
606
607 case Type::Pointer:
608 return STC_Pointer;
609
610 case Type::BlockPointer:
611 return STC_Block;
612
613 case Type::LValueReference:
614 case Type::RValueReference:
615 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
616
617 case Type::ConstantArray:
618 case Type::IncompleteArray:
619 case Type::VariableArray:
620 case Type::DependentSizedArray:
621 return STC_Array;
622
623 case Type::DependentSizedExtVector:
624 case Type::Vector:
625 case Type::ExtVector:
626 return STC_Arithmetic;
627
628 case Type::FunctionProto:
629 case Type::FunctionNoProto:
630 return STC_Function;
631
632 case Type::Record:
633 return STC_Record;
634
635 case Type::Enum:
636 return STC_Arithmetic;
637
638 case Type::ObjCObject:
639 case Type::ObjCInterface:
640 case Type::ObjCObjectPointer:
641 return STC_ObjectiveC;
642
643 default:
644 return STC_Other;
645 }
646}
647
648/// \brief Get the type that a given expression will have if this declaration
649/// is used as an expression in its "typical" code-completion form.
Douglas Gregor6e240332010-08-16 16:18:59 +0000650QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000651 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
652
653 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
654 return C.getTypeDeclType(Type);
655 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
656 return C.getObjCInterfaceType(Iface);
657
658 QualType T;
659 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000660 T = Function->getCallResultType();
Douglas Gregor95887f92010-07-08 23:20:03 +0000661 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000662 T = Method->getSendResultType();
Douglas Gregor95887f92010-07-08 23:20:03 +0000663 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000664 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor95887f92010-07-08 23:20:03 +0000665 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
666 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
667 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
668 T = Property->getType();
669 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
670 T = Value->getType();
671 else
672 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000673
674 // Dig through references, function pointers, and block pointers to
675 // get down to the likely type of an expression when the entity is
676 // used.
677 do {
678 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
679 T = Ref->getPointeeType();
680 continue;
681 }
682
683 if (const PointerType *Pointer = T->getAs<PointerType>()) {
684 if (Pointer->getPointeeType()->isFunctionType()) {
685 T = Pointer->getPointeeType();
686 continue;
687 }
688
689 break;
690 }
691
692 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
693 T = Block->getPointeeType();
694 continue;
695 }
696
697 if (const FunctionType *Function = T->getAs<FunctionType>()) {
698 T = Function->getResultType();
699 continue;
700 }
701
702 break;
703 } while (true);
704
705 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000706}
707
Douglas Gregor50832e02010-09-20 22:39:41 +0000708void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
709 // If this is an Objective-C method declaration whose selector matches our
710 // preferred selector, give it a priority boost.
711 if (!PreferredSelector.isNull())
712 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
713 if (PreferredSelector == Method->getSelector())
714 R.Priority += CCD_SelectorMatch;
Douglas Gregor5fb901d2010-09-20 23:11:55 +0000715
Douglas Gregor50832e02010-09-20 22:39:41 +0000716 // If we have a preferred type, adjust the priority for results with exactly-
717 // matching or nearly-matching types.
718 if (!PreferredType.isNull()) {
719 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
720 if (!T.isNull()) {
721 CanQualType TC = SemaRef.Context.getCanonicalType(T);
722 // Check for exactly-matching types (modulo qualifiers).
723 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
724 R.Priority /= CCF_ExactTypeMatch;
725 // Check for nearly-matching types, based on classification of each.
726 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor95887f92010-07-08 23:20:03 +0000727 == getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000728 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
729 R.Priority /= CCF_SimilarTypeMatch;
730 }
731 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000732}
733
Douglas Gregor0212fd72010-09-21 16:06:22 +0000734void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000735 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000736 !CompletionContext.wantConstructorResults())
737 return;
738
739 ASTContext &Context = SemaRef.Context;
740 NamedDecl *D = R.Declaration;
741 CXXRecordDecl *Record = 0;
742 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
743 Record = ClassTemplate->getTemplatedDecl();
744 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
745 // Skip specializations and partial specializations.
746 if (isa<ClassTemplateSpecializationDecl>(Record))
747 return;
748 } else {
749 // There are no constructors here.
750 return;
751 }
752
753 Record = Record->getDefinition();
754 if (!Record)
755 return;
756
757
758 QualType RecordTy = Context.getTypeDeclType(Record);
759 DeclarationName ConstructorName
760 = Context.DeclarationNames.getCXXConstructorName(
761 Context.getCanonicalType(RecordTy));
762 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
763 Ctors.first != Ctors.second; ++Ctors.first) {
764 R.Declaration = *Ctors.first;
765 R.CursorKind = getCursorKindForDecl(R.Declaration);
766 Results.push_back(R);
767 }
768}
769
Douglas Gregor7c208612010-01-14 00:20:49 +0000770void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
771 assert(!ShadowMaps.empty() && "Must enter into a results scope");
772
773 if (R.Kind != Result::RK_Declaration) {
774 // For non-declaration results, just add the result.
775 Results.push_back(R);
776 return;
777 }
778
779 // Look through using declarations.
780 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
781 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
782 return;
783 }
784
785 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
786 unsigned IDNS = CanonDecl->getIdentifierNamespace();
787
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000788 bool AsNestedNameSpecifier = false;
789 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000790 return;
791
Douglas Gregor0212fd72010-09-21 16:06:22 +0000792 // C++ constructors are never found by name lookup.
793 if (isa<CXXConstructorDecl>(R.Declaration))
794 return;
795
Douglas Gregor3545ff42009-09-21 16:56:56 +0000796 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000797 ShadowMapEntry::iterator I, IEnd;
798 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
799 if (NamePos != SMap.end()) {
800 I = NamePos->second.begin();
801 IEnd = NamePos->second.end();
802 }
803
804 for (; I != IEnd; ++I) {
805 NamedDecl *ND = I->first;
806 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000807 if (ND->getCanonicalDecl() == CanonDecl) {
808 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000809 Results[Index].Declaration = R.Declaration;
810
Douglas Gregor3545ff42009-09-21 16:56:56 +0000811 // We're done.
812 return;
813 }
814 }
815
816 // This is a new declaration in this scope. However, check whether this
817 // declaration name is hidden by a similarly-named declaration in an outer
818 // scope.
819 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
820 --SMEnd;
821 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000822 ShadowMapEntry::iterator I, IEnd;
823 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
824 if (NamePos != SM->end()) {
825 I = NamePos->second.begin();
826 IEnd = NamePos->second.end();
827 }
828 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000829 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000830 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor3545ff42009-09-21 16:56:56 +0000831 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
832 Decl::IDNS_ObjCProtocol)))
833 continue;
834
835 // Protocols are in distinct namespaces from everything else.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000836 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000837 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000838 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000839 continue;
840
841 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000842 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000843 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000844
845 break;
846 }
847 }
848
849 // Make sure that any given declaration only shows up in the result set once.
850 if (!AllDeclsFound.insert(CanonDecl))
851 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000852
Douglas Gregore412a5a2009-09-23 22:26:46 +0000853 // If the filter is for nested-name-specifiers, then this result starts a
854 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000855 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000856 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000857 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregor50832e02010-09-20 22:39:41 +0000858 } else
859 AdjustResultPriorityForDecl(R);
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000860
Douglas Gregor5bf52692009-09-22 23:15:58 +0000861 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000862 if (R.QualifierIsInformative && !R.Qualifier &&
863 !R.StartsNestedNameSpecifier) {
Douglas Gregor5bf52692009-09-22 23:15:58 +0000864 DeclContext *Ctx = R.Declaration->getDeclContext();
865 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
866 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
867 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
868 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
869 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
870 else
871 R.QualifierIsInformative = false;
872 }
Douglas Gregore412a5a2009-09-23 22:26:46 +0000873
Douglas Gregor3545ff42009-09-21 16:56:56 +0000874 // Insert this result into the set of results and into the current shadow
875 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000876 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000877 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +0000878
879 if (!AsNestedNameSpecifier)
880 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000881}
882
Douglas Gregorc580c522010-01-14 01:09:38 +0000883void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000884 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000885 if (R.Kind != Result::RK_Declaration) {
886 // For non-declaration results, just add the result.
887 Results.push_back(R);
888 return;
889 }
890
Douglas Gregorc580c522010-01-14 01:09:38 +0000891 // Look through using declarations.
892 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
893 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
894 return;
895 }
896
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000897 bool AsNestedNameSpecifier = false;
898 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000899 return;
900
Douglas Gregor0212fd72010-09-21 16:06:22 +0000901 // C++ constructors are never found by name lookup.
902 if (isa<CXXConstructorDecl>(R.Declaration))
903 return;
904
Douglas Gregorc580c522010-01-14 01:09:38 +0000905 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
906 return;
907
908 // Make sure that any given declaration only shows up in the result set once.
909 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
910 return;
911
912 // If the filter is for nested-name-specifiers, then this result starts a
913 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000914 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +0000915 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000916 R.Priority = CCP_NestedNameSpecifier;
917 }
Douglas Gregor09bbc652010-01-14 15:47:35 +0000918 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
919 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl50c68252010-08-31 00:36:30 +0000920 ->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +0000921 R.QualifierIsInformative = true;
922
Douglas Gregorc580c522010-01-14 01:09:38 +0000923 // If this result is supposed to have an informative qualifier, add one.
924 if (R.QualifierIsInformative && !R.Qualifier &&
925 !R.StartsNestedNameSpecifier) {
926 DeclContext *Ctx = R.Declaration->getDeclContext();
927 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
928 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
929 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
930 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000931 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +0000932 else
933 R.QualifierIsInformative = false;
934 }
935
Douglas Gregora2db7932010-05-26 22:00:08 +0000936 // Adjust the priority if this result comes from a base class.
937 if (InBaseClass)
938 R.Priority += CCD_InBaseClass;
939
Douglas Gregor50832e02010-09-20 22:39:41 +0000940 AdjustResultPriorityForDecl(R);
Douglas Gregor7aa6b222010-05-30 01:49:25 +0000941
Douglas Gregor9be0ed42010-08-26 16:36:48 +0000942 if (HasObjectTypeQualifiers)
943 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
944 if (Method->isInstance()) {
945 Qualifiers MethodQuals
946 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
947 if (ObjectTypeQualifiers == MethodQuals)
948 R.Priority += CCD_ObjectQualifierMatch;
949 else if (ObjectTypeQualifiers - MethodQuals) {
950 // The method cannot be invoked, because doing so would drop
951 // qualifiers.
952 return;
953 }
954 }
955
Douglas Gregorc580c522010-01-14 01:09:38 +0000956 // Insert this result into the set of results.
957 Results.push_back(R);
Douglas Gregor0212fd72010-09-21 16:06:22 +0000958
959 if (!AsNestedNameSpecifier)
960 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +0000961}
962
Douglas Gregor78a21012010-01-14 16:01:26 +0000963void ResultBuilder::AddResult(Result R) {
964 assert(R.Kind != Result::RK_Declaration &&
965 "Declaration results need more context");
966 Results.push_back(R);
967}
968
Douglas Gregor3545ff42009-09-21 16:56:56 +0000969/// \brief Enter into a new scope.
970void ResultBuilder::EnterNewScope() {
971 ShadowMaps.push_back(ShadowMap());
972}
973
974/// \brief Exit from the current scope.
975void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000976 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
977 EEnd = ShadowMaps.back().end();
978 E != EEnd;
979 ++E)
980 E->second.Destroy();
981
Douglas Gregor3545ff42009-09-21 16:56:56 +0000982 ShadowMaps.pop_back();
983}
984
Douglas Gregor9d64c5e2009-09-21 20:51:25 +0000985/// \brief Determines whether this given declaration will be found by
986/// ordinary name lookup.
987bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +0000988 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
989
Douglas Gregor9d64c5e2009-09-21 20:51:25 +0000990 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikiebbafb8a2012-03-11 07:00:24 +0000991 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +0000992 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +0000993 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +0000994 if (isa<ObjCIvarDecl>(ND))
995 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +0000996 }
997
Douglas Gregor9d64c5e2009-09-21 20:51:25 +0000998 return ND->getIdentifierNamespace() & IDNS;
999}
1000
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001001/// \brief Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001002/// ordinary name lookup but is not a type name.
1003bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
1004 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1005 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1006 return false;
1007
1008 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001009 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001010 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001011 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001012 if (isa<ObjCIvarDecl>(ND))
1013 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001014 }
1015
Douglas Gregor70febae2010-05-28 00:49:12 +00001016 return ND->getIdentifierNamespace() & IDNS;
1017}
1018
Douglas Gregor85b50632010-07-28 21:50:18 +00001019bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1020 if (!IsOrdinaryNonTypeName(ND))
1021 return 0;
1022
1023 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1024 if (VD->getType()->isIntegralOrEnumerationType())
1025 return true;
1026
1027 return false;
1028}
1029
Douglas Gregor70febae2010-05-28 00:49:12 +00001030/// \brief Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001031/// ordinary name lookup.
1032bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor70febae2010-05-28 00:49:12 +00001033 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1034
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001035 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001036 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001037 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001038
1039 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor70febae2010-05-28 00:49:12 +00001040 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1041 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001042}
1043
Douglas Gregor3545ff42009-09-21 16:56:56 +00001044/// \brief Determines whether the given declaration is suitable as the
1045/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1046bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1047 // Allow us to find class templates, too.
1048 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1049 ND = ClassTemplate->getTemplatedDecl();
1050
1051 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1052}
1053
1054/// \brief Determines whether the given declaration is an enumeration.
1055bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1056 return isa<EnumDecl>(ND);
1057}
1058
1059/// \brief Determines whether the given declaration is a class or struct.
1060bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1061 // Allow us to find class templates, too.
1062 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1063 ND = ClassTemplate->getTemplatedDecl();
1064
1065 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001066 return RD->getTagKind() == TTK_Class ||
1067 RD->getTagKind() == TTK_Struct;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001068
1069 return false;
1070}
1071
1072/// \brief Determines whether the given declaration is a union.
1073bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1074 // Allow us to find class templates, too.
1075 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1076 ND = ClassTemplate->getTemplatedDecl();
1077
1078 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001079 return RD->getTagKind() == TTK_Union;
Douglas Gregor3545ff42009-09-21 16:56:56 +00001080
1081 return false;
1082}
1083
1084/// \brief Determines whether the given declaration is a namespace.
1085bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1086 return isa<NamespaceDecl>(ND);
1087}
1088
1089/// \brief Determines whether the given declaration is a namespace or
1090/// namespace alias.
1091bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1092 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1093}
1094
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001095/// \brief Determines whether the given declaration is a type.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001096bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregor99fa2642010-08-24 01:06:58 +00001097 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1098 ND = Using->getTargetDecl();
1099
1100 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001101}
1102
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001103/// \brief Determines which members of a class should be visible via
1104/// "." or "->". Only value declarations, nested name specifiers, and
1105/// using declarations thereof should show up.
Douglas Gregore412a5a2009-09-23 22:26:46 +00001106bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001107 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1108 ND = Using->getTargetDecl();
1109
Douglas Gregor70788392009-12-11 18:14:22 +00001110 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1111 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001112}
1113
Douglas Gregora817a192010-05-27 23:06:34 +00001114static bool isObjCReceiverType(ASTContext &C, QualType T) {
1115 T = C.getCanonicalType(T);
1116 switch (T->getTypeClass()) {
1117 case Type::ObjCObject:
1118 case Type::ObjCInterface:
1119 case Type::ObjCObjectPointer:
1120 return true;
1121
1122 case Type::Builtin:
1123 switch (cast<BuiltinType>(T)->getKind()) {
1124 case BuiltinType::ObjCId:
1125 case BuiltinType::ObjCClass:
1126 case BuiltinType::ObjCSel:
1127 return true;
1128
1129 default:
1130 break;
1131 }
1132 return false;
1133
1134 default:
1135 break;
1136 }
1137
David Blaikiebbafb8a2012-03-11 07:00:24 +00001138 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001139 return false;
1140
1141 // FIXME: We could perform more analysis here to determine whether a
1142 // particular class type has any conversions to Objective-C types. For now,
1143 // just accept all class types.
1144 return T->isDependentType() || T->isRecordType();
1145}
1146
1147bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1148 QualType T = getDeclUsageType(SemaRef.Context, ND);
1149 if (T.isNull())
1150 return false;
1151
1152 T = SemaRef.Context.getBaseElementType(T);
1153 return isObjCReceiverType(SemaRef.Context, T);
1154}
1155
Douglas Gregord8c61782012-02-15 15:34:24 +00001156bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
1157 if (IsObjCMessageReceiver(ND))
1158 return true;
1159
1160 VarDecl *Var = dyn_cast<VarDecl>(ND);
1161 if (!Var)
1162 return false;
1163
1164 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1165}
1166
Douglas Gregor68762e72010-08-23 21:17:50 +00001167bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001168 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1169 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001170 return false;
1171
1172 QualType T = getDeclUsageType(SemaRef.Context, ND);
1173 if (T.isNull())
1174 return false;
1175
1176 T = SemaRef.Context.getBaseElementType(T);
1177 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1178 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001179 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001180}
Douglas Gregora817a192010-05-27 23:06:34 +00001181
Douglas Gregor0ac41382010-09-23 23:01:17 +00001182bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1183 return false;
1184}
1185
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001186/// \rief Determines whether the given declaration is an Objective-C
1187/// instance variable.
1188bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1189 return isa<ObjCIvarDecl>(ND);
1190}
1191
Douglas Gregorc580c522010-01-14 01:09:38 +00001192namespace {
1193 /// \brief Visible declaration consumer that adds a code-completion result
1194 /// for each visible declaration.
1195 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1196 ResultBuilder &Results;
1197 DeclContext *CurContext;
1198
1199 public:
1200 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1201 : Results(Results), CurContext(CurContext) { }
1202
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001203 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1204 bool InBaseClass) {
1205 bool Accessible = true;
Douglas Gregor03ba1882011-11-03 16:51:37 +00001206 if (Ctx)
1207 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1208
Erik Verbruggen2e657ff2011-10-06 07:27:49 +00001209 ResultBuilder::Result Result(ND, 0, false, Accessible);
1210 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregorc580c522010-01-14 01:09:38 +00001211 }
1212 };
1213}
1214
Douglas Gregor3545ff42009-09-21 16:56:56 +00001215/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001216static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001217 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001218 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001219 Results.AddResult(Result("short", CCP_Type));
1220 Results.AddResult(Result("long", CCP_Type));
1221 Results.AddResult(Result("signed", CCP_Type));
1222 Results.AddResult(Result("unsigned", CCP_Type));
1223 Results.AddResult(Result("void", CCP_Type));
1224 Results.AddResult(Result("char", CCP_Type));
1225 Results.AddResult(Result("int", CCP_Type));
1226 Results.AddResult(Result("float", CCP_Type));
1227 Results.AddResult(Result("double", CCP_Type));
1228 Results.AddResult(Result("enum", CCP_Type));
1229 Results.AddResult(Result("struct", CCP_Type));
1230 Results.AddResult(Result("union", CCP_Type));
1231 Results.AddResult(Result("const", CCP_Type));
1232 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001233
Douglas Gregor3545ff42009-09-21 16:56:56 +00001234 if (LangOpts.C99) {
1235 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001236 Results.AddResult(Result("_Complex", CCP_Type));
1237 Results.AddResult(Result("_Imaginary", CCP_Type));
1238 Results.AddResult(Result("_Bool", CCP_Type));
1239 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001240 }
1241
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001242 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001243 if (LangOpts.CPlusPlus) {
1244 // C++-specific
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00001245 Results.AddResult(Result("bool", CCP_Type +
1246 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001247 Results.AddResult(Result("class", CCP_Type));
1248 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001249
Douglas Gregorf4c33342010-05-28 00:22:41 +00001250 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001251 Builder.AddTypedTextChunk("typename");
1252 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1253 Builder.AddPlaceholderChunk("qualifier");
1254 Builder.AddTextChunk("::");
1255 Builder.AddPlaceholderChunk("name");
1256 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001257
Douglas Gregor3545ff42009-09-21 16:56:56 +00001258 if (LangOpts.CPlusPlus0x) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001259 Results.AddResult(Result("auto", CCP_Type));
1260 Results.AddResult(Result("char16_t", CCP_Type));
1261 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001262
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001263 Builder.AddTypedTextChunk("decltype");
1264 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1265 Builder.AddPlaceholderChunk("expression");
1266 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1267 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001268 }
1269 }
1270
1271 // GNU extensions
1272 if (LangOpts.GNUMode) {
1273 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001274 // Results.AddResult(Result("_Decimal32"));
1275 // Results.AddResult(Result("_Decimal64"));
1276 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001277
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001278 Builder.AddTypedTextChunk("typeof");
1279 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1280 Builder.AddPlaceholderChunk("expression");
1281 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001282
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001283 Builder.AddTypedTextChunk("typeof");
1284 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1285 Builder.AddPlaceholderChunk("type");
1286 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1287 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001288 }
1289}
1290
John McCallfaf5fb42010-08-26 23:41:50 +00001291static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001292 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001293 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001294 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001295 // Note: we don't suggest either "auto" or "register", because both
1296 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1297 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001298 Results.AddResult(Result("extern"));
1299 Results.AddResult(Result("static"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001300}
1301
John McCallfaf5fb42010-08-26 23:41:50 +00001302static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001303 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001304 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001305 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001306 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001307 case Sema::PCC_Class:
1308 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001309 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001310 Results.AddResult(Result("explicit"));
1311 Results.AddResult(Result("friend"));
1312 Results.AddResult(Result("mutable"));
1313 Results.AddResult(Result("virtual"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001314 }
1315 // Fall through
1316
John McCallfaf5fb42010-08-26 23:41:50 +00001317 case Sema::PCC_ObjCInterface:
1318 case Sema::PCC_ObjCImplementation:
1319 case Sema::PCC_Namespace:
1320 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001321 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001322 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001323 break;
1324
John McCallfaf5fb42010-08-26 23:41:50 +00001325 case Sema::PCC_ObjCInstanceVariableList:
1326 case Sema::PCC_Expression:
1327 case Sema::PCC_Statement:
1328 case Sema::PCC_ForInit:
1329 case Sema::PCC_Condition:
1330 case Sema::PCC_RecoveryInFunction:
1331 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001332 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001333 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001334 break;
1335 }
1336}
1337
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001338static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1339static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1340static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00001341 ResultBuilder &Results,
1342 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001343static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001344 ResultBuilder &Results,
1345 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001346static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00001347 ResultBuilder &Results,
1348 bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001349static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001350
Douglas Gregorf4c33342010-05-28 00:22:41 +00001351static void AddTypedefResult(ResultBuilder &Results) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001352 CodeCompletionBuilder Builder(Results.getAllocator());
1353 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))
1417 return BT->getName(Policy);
1418
1419 // Anonymous tag types are constant strings.
1420 if (const TagType *TagT = dyn_cast<TagType>(T))
1421 if (TagDecl *Tag = TagT->getDecl())
1422 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1423 switch (Tag->getTagKind()) {
1424 case TTK_Struct: return "struct <anonymous>";
1425 case TTK_Class: return "class <anonymous>";
1426 case TTK_Union: return "union <anonymous>";
1427 case TTK_Enum: return "enum <anonymous>";
1428 }
1429 }
1430 }
1431
1432 // Slow path: format the type as a string.
1433 std::string Result;
1434 T.getAsStringInternal(Result, Policy);
1435 return Allocator.CopyString(Result);
1436}
1437
Douglas 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();
1445 CodeCompletionBuilder Builder(Allocator);
1446 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();
1461 CodeCompletionBuilder Builder(Allocator);
1462 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");
1545 Builder.AddChunk(CodeCompletionString::CK_Colon);
1546 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001547
1548 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001549 Builder.AddTypedTextChunk("protected");
1550 Builder.AddChunk(CodeCompletionString::CK_Colon);
1551 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001552
1553 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001554 Builder.AddTypedTextChunk("private");
1555 Builder.AddChunk(CodeCompletionString::CK_Colon);
1556 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001557 }
1558 }
1559 // Fall through
1560
John McCallfaf5fb42010-08-26 23:41:50 +00001561 case Sema::PCC_Template:
1562 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001563 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001564 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001565 Builder.AddTypedTextChunk("template");
1566 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1567 Builder.AddPlaceholderChunk("parameters");
1568 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1569 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001570 }
1571
David Blaikiebbafb8a2012-03-11 07:00:24 +00001572 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1573 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001574 break;
1575
John McCallfaf5fb42010-08-26 23:41:50 +00001576 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001577 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1578 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1579 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001580 break;
1581
John McCallfaf5fb42010-08-26 23:41:50 +00001582 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001583 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1584 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1585 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001586 break;
1587
John McCallfaf5fb42010-08-26 23:41:50 +00001588 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001589 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001590 break;
1591
John McCallfaf5fb42010-08-26 23:41:50 +00001592 case Sema::PCC_RecoveryInFunction:
1593 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001594 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001595
David Blaikiebbafb8a2012-03-11 07:00:24 +00001596 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1597 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001598 Builder.AddTypedTextChunk("try");
1599 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1600 Builder.AddPlaceholderChunk("statements");
1601 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1602 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1603 Builder.AddTextChunk("catch");
1604 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1605 Builder.AddPlaceholderChunk("declaration");
1606 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1607 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1608 Builder.AddPlaceholderChunk("statements");
1609 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1610 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1611 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001612 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001613 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001614 AddObjCStatementResults(Results, true);
Douglas Gregorf1934162010-01-13 21:24:21 +00001615
Douglas Gregorf64acca2010-05-25 21:41:55 +00001616 if (Results.includeCodePatterns()) {
1617 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001618 Builder.AddTypedTextChunk("if");
1619 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001620 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001621 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001622 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001623 Builder.AddPlaceholderChunk("expression");
1624 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1625 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1626 Builder.AddPlaceholderChunk("statements");
1627 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1628 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1629 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001630
Douglas Gregorf64acca2010-05-25 21:41:55 +00001631 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001632 Builder.AddTypedTextChunk("switch");
1633 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001634 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001635 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001636 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001637 Builder.AddPlaceholderChunk("expression");
1638 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1639 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1640 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1641 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1642 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001643 }
1644
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001645 // Switch-specific statements.
John McCallaab3e412010-08-25 08:40:02 +00001646 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001647 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001648 Builder.AddTypedTextChunk("case");
1649 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1650 Builder.AddPlaceholderChunk("expression");
1651 Builder.AddChunk(CodeCompletionString::CK_Colon);
1652 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001653
1654 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001655 Builder.AddTypedTextChunk("default");
1656 Builder.AddChunk(CodeCompletionString::CK_Colon);
1657 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001658 }
1659
Douglas Gregorf64acca2010-05-25 21:41:55 +00001660 if (Results.includeCodePatterns()) {
1661 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001662 Builder.AddTypedTextChunk("while");
1663 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001664 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001665 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001666 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001667 Builder.AddPlaceholderChunk("expression");
1668 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1669 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1670 Builder.AddPlaceholderChunk("statements");
1671 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1672 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1673 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001674
1675 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001676 Builder.AddTypedTextChunk("do");
1677 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1678 Builder.AddPlaceholderChunk("statements");
1679 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1680 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1681 Builder.AddTextChunk("while");
1682 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1683 Builder.AddPlaceholderChunk("expression");
1684 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1685 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001686
Douglas Gregorf64acca2010-05-25 21:41:55 +00001687 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001688 Builder.AddTypedTextChunk("for");
1689 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001690 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001691 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001692 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001693 Builder.AddPlaceholderChunk("init-expression");
1694 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1695 Builder.AddPlaceholderChunk("condition");
1696 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1697 Builder.AddPlaceholderChunk("inc-expression");
1698 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1699 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1700 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1701 Builder.AddPlaceholderChunk("statements");
1702 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1703 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1704 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001705 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001706
1707 if (S->getContinueParent()) {
1708 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001709 Builder.AddTypedTextChunk("continue");
1710 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001711 }
1712
1713 if (S->getBreakParent()) {
1714 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("break");
1716 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001717 }
1718
1719 // "return expression ;" or "return ;", depending on whether we
1720 // know the function is void or not.
1721 bool isVoid = false;
1722 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1723 isVoid = Function->getResultType()->isVoidType();
1724 else if (ObjCMethodDecl *Method
1725 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1726 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9a28e842010-03-01 23:15:13 +00001727 else if (SemaRef.getCurBlock() &&
1728 !SemaRef.getCurBlock()->ReturnType.isNull())
1729 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001730 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001731 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001732 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1733 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001734 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001735 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001736
Douglas Gregorf4c33342010-05-28 00:22:41 +00001737 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001738 Builder.AddTypedTextChunk("goto");
1739 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1740 Builder.AddPlaceholderChunk("label");
1741 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001742
Douglas Gregorf4c33342010-05-28 00:22:41 +00001743 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001744 Builder.AddTypedTextChunk("using");
1745 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1746 Builder.AddTextChunk("namespace");
1747 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1748 Builder.AddPlaceholderChunk("identifier");
1749 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001750 }
1751
1752 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00001753 case Sema::PCC_ForInit:
1754 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001755 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001756 // Fall through: conditions and statements can have expressions.
1757
Douglas Gregor5e35d592010-09-14 23:59:36 +00001758 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001759 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00001760 CCC == Sema::PCC_ParenthesizedExpression) {
1761 // (__bridge <type>)<expression>
1762 Builder.AddTypedTextChunk("__bridge");
1763 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1764 Builder.AddPlaceholderChunk("type");
1765 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1766 Builder.AddPlaceholderChunk("expression");
1767 Results.AddResult(Result(Builder.TakeString()));
1768
1769 // (__bridge_transfer <Objective-C type>)<expression>
1770 Builder.AddTypedTextChunk("__bridge_transfer");
1771 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1772 Builder.AddPlaceholderChunk("Objective-C type");
1773 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1774 Builder.AddPlaceholderChunk("expression");
1775 Results.AddResult(Result(Builder.TakeString()));
1776
1777 // (__bridge_retained <CF type>)<expression>
1778 Builder.AddTypedTextChunk("__bridge_retained");
1779 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1780 Builder.AddPlaceholderChunk("CF type");
1781 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1782 Builder.AddPlaceholderChunk("expression");
1783 Results.AddResult(Result(Builder.TakeString()));
1784 }
1785 // Fall through
1786
John McCallfaf5fb42010-08-26 23:41:50 +00001787 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001788 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001789 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001790 addThisCompletion(SemaRef, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001791
Douglas Gregore5c79d52011-10-18 21:20:17 +00001792 // true
1793 Builder.AddResultTypeChunk("bool");
1794 Builder.AddTypedTextChunk("true");
1795 Results.AddResult(Result(Builder.TakeString()));
1796
1797 // false
1798 Builder.AddResultTypeChunk("bool");
1799 Builder.AddTypedTextChunk("false");
1800 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001801
David Blaikiebbafb8a2012-03-11 07:00:24 +00001802 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001803 // dynamic_cast < type-id > ( expression )
1804 Builder.AddTypedTextChunk("dynamic_cast");
1805 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1806 Builder.AddPlaceholderChunk("type");
1807 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1808 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1809 Builder.AddPlaceholderChunk("expression");
1810 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1811 Results.AddResult(Result(Builder.TakeString()));
1812 }
Douglas Gregorf4c33342010-05-28 00:22:41 +00001813
1814 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001815 Builder.AddTypedTextChunk("static_cast");
1816 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1817 Builder.AddPlaceholderChunk("type");
1818 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1819 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1820 Builder.AddPlaceholderChunk("expression");
1821 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1822 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001823
Douglas Gregorf4c33342010-05-28 00:22:41 +00001824 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001825 Builder.AddTypedTextChunk("reinterpret_cast");
1826 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1827 Builder.AddPlaceholderChunk("type");
1828 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1829 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1830 Builder.AddPlaceholderChunk("expression");
1831 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1832 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001833
Douglas Gregorf4c33342010-05-28 00:22:41 +00001834 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001835 Builder.AddTypedTextChunk("const_cast");
1836 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1837 Builder.AddPlaceholderChunk("type");
1838 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1839 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1840 Builder.AddPlaceholderChunk("expression");
1841 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1842 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001843
David Blaikiebbafb8a2012-03-11 07:00:24 +00001844 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001845 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00001846 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00001847 Builder.AddTypedTextChunk("typeid");
1848 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1849 Builder.AddPlaceholderChunk("expression-or-type");
1850 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1851 Results.AddResult(Result(Builder.TakeString()));
1852 }
1853
Douglas Gregorf4c33342010-05-28 00:22:41 +00001854 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001855 Builder.AddTypedTextChunk("new");
1856 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1857 Builder.AddPlaceholderChunk("type");
1858 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1859 Builder.AddPlaceholderChunk("expressions");
1860 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1861 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001862
Douglas Gregorf4c33342010-05-28 00:22:41 +00001863 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001864 Builder.AddTypedTextChunk("new");
1865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1866 Builder.AddPlaceholderChunk("type");
1867 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1868 Builder.AddPlaceholderChunk("size");
1869 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1870 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1871 Builder.AddPlaceholderChunk("expressions");
1872 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1873 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001874
Douglas Gregorf4c33342010-05-28 00:22:41 +00001875 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001876 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001877 Builder.AddTypedTextChunk("delete");
1878 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1879 Builder.AddPlaceholderChunk("expression");
1880 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001881
Douglas Gregorf4c33342010-05-28 00:22:41 +00001882 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001883 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001884 Builder.AddTypedTextChunk("delete");
1885 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1886 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1887 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1888 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1889 Builder.AddPlaceholderChunk("expression");
1890 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001891
David Blaikiebbafb8a2012-03-11 07:00:24 +00001892 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00001893 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001894 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00001895 Builder.AddTypedTextChunk("throw");
1896 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1897 Builder.AddPlaceholderChunk("expression");
1898 Results.AddResult(Result(Builder.TakeString()));
1899 }
Douglas Gregor4205fef2011-10-18 16:29:03 +00001900
Douglas Gregora2db7932010-05-26 22:00:08 +00001901 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00001902
David Blaikiebbafb8a2012-03-11 07:00:24 +00001903 if (SemaRef.getLangOpts().CPlusPlus0x) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00001904 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00001905 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001906 Builder.AddTypedTextChunk("nullptr");
1907 Results.AddResult(Result(Builder.TakeString()));
1908
1909 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00001910 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001911 Builder.AddTypedTextChunk("alignof");
1912 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1913 Builder.AddPlaceholderChunk("type");
1914 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1915 Results.AddResult(Result(Builder.TakeString()));
1916
1917 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00001918 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001919 Builder.AddTypedTextChunk("noexcept");
1920 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1921 Builder.AddPlaceholderChunk("expression");
1922 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1923 Results.AddResult(Result(Builder.TakeString()));
1924
1925 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001926 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00001927 Builder.AddTypedTextChunk("sizeof...");
1928 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1929 Builder.AddPlaceholderChunk("parameter-pack");
1930 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1931 Results.AddResult(Result(Builder.TakeString()));
1932 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001933 }
1934
David Blaikiebbafb8a2012-03-11 07:00:24 +00001935 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001936 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00001937 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1938 // The interface can be NULL.
1939 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00001940 if (ID->getSuperClass()) {
1941 std::string SuperType;
1942 SuperType = ID->getSuperClass()->getNameAsString();
1943 if (Method->isInstanceMethod())
1944 SuperType += " *";
1945
1946 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1947 Builder.AddTypedTextChunk("super");
1948 Results.AddResult(Result(Builder.TakeString()));
1949 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00001950 }
1951
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001952 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001953 }
1954
Douglas Gregorf4c33342010-05-28 00:22:41 +00001955 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00001956 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001957 Builder.AddTypedTextChunk("sizeof");
1958 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1959 Builder.AddPlaceholderChunk("expression-or-type");
1960 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1961 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001962 break;
1963 }
Douglas Gregor99fa2642010-08-24 01:06:58 +00001964
John McCallfaf5fb42010-08-26 23:41:50 +00001965 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00001966 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00001967 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001968 }
1969
David Blaikiebbafb8a2012-03-11 07:00:24 +00001970 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1971 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001972
David Blaikiebbafb8a2012-03-11 07:00:24 +00001973 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00001974 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001975}
1976
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001977/// \brief If the given declaration has an associated type, add it as a result
1978/// type chunk.
1979static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00001980 const PrintingPolicy &Policy,
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001981 NamedDecl *ND,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001982 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001983 if (!ND)
1984 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00001985
1986 // Skip constructors and conversion functions, which have their return types
1987 // built into their names.
1988 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1989 return;
1990
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001991 // Determine the type of the declaration (if it has a type).
Douglas Gregor0212fd72010-09-21 16:06:22 +00001992 QualType T;
Douglas Gregorb3fa9192009-12-18 18:53:37 +00001993 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1994 T = Function->getResultType();
1995 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1996 T = Method->getResultType();
1997 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1998 T = FunTmpl->getTemplatedDecl()->getResultType();
1999 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
2000 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2001 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2002 /* Do nothing: ignore unresolved using declarations*/
John McCall31168b02011-06-15 23:02:42 +00002003 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002004 T = Value->getType();
John McCall31168b02011-06-15 23:02:42 +00002005 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002006 T = Property->getType();
2007
2008 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2009 return;
2010
Douglas Gregor75acd922011-09-27 23:30:47 +00002011 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002012 Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002013}
2014
Douglas Gregordbb71db2010-08-23 23:51:41 +00002015static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002016 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002017 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2018 if (Sentinel->getSentinel() == 0) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002019 if (Context.getLangOpts().ObjC1 &&
Douglas Gregordbb71db2010-08-23 23:51:41 +00002020 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002021 Result.AddTextChunk(", nil");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002022 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002023 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002024 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002025 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002026 }
2027}
2028
Douglas Gregor8f08d742011-07-30 07:55:26 +00002029static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2030 std::string Result;
2031 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002032 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002033 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002034 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002035 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002036 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002037 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002038 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002039 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002040 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002041 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002042 Result += "oneway ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002043 return Result;
2044}
2045
Douglas Gregore90dd002010-08-24 16:15:59 +00002046static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002047 const PrintingPolicy &Policy,
Douglas Gregor981a0c42010-08-29 19:47:46 +00002048 ParmVarDecl *Param,
Douglas Gregord793e7c2011-10-18 04:23:19 +00002049 bool SuppressName = false,
2050 bool SuppressBlock = false) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002051 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2052 if (Param->getType()->isDependentType() ||
2053 !Param->getType()->isBlockPointerType()) {
2054 // The argument for a dependent or non-block parameter is a placeholder
2055 // containing that parameter's type.
2056 std::string Result;
2057
Douglas Gregor981a0c42010-08-29 19:47:46 +00002058 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002059 Result = Param->getIdentifier()->getName();
2060
John McCall31168b02011-06-15 23:02:42 +00002061 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002062
2063 if (ObjCMethodParam) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002064 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2065 + Result + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002066 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002067 Result += Param->getIdentifier()->getName();
2068 }
2069 return Result;
2070 }
2071
2072 // The argument for a block pointer parameter is a block literal with
2073 // the appropriate type.
Douglas Gregor24bbc462011-02-15 22:37:09 +00002074 FunctionTypeLoc *Block = 0;
2075 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregore90dd002010-08-24 16:15:59 +00002076 TypeLoc TL;
2077 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2078 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2079 while (true) {
2080 // Look through typedefs.
Douglas Gregord793e7c2011-10-18 04:23:19 +00002081 if (!SuppressBlock) {
2082 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2083 if (TypeSourceInfo *InnerTSInfo
2084 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2085 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2086 continue;
2087 }
2088 }
2089
2090 // Look through qualified types
2091 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2092 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregore90dd002010-08-24 16:15:59 +00002093 continue;
2094 }
2095 }
2096
Douglas Gregore90dd002010-08-24 16:15:59 +00002097 // Try to get the function prototype behind the block pointer type,
2098 // then we're done.
2099 if (BlockPointerTypeLoc *BlockPtr
2100 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara6d810632010-12-14 22:11:44 +00002101 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor24bbc462011-02-15 22:37:09 +00002102 Block = dyn_cast<FunctionTypeLoc>(&TL);
2103 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregore90dd002010-08-24 16:15:59 +00002104 }
2105 break;
2106 }
2107 }
2108
2109 if (!Block) {
2110 // We were unable to find a FunctionProtoTypeLoc with parameter names
2111 // for the block; just use the parameter type as a placeholder.
2112 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002113 if (!ObjCMethodParam && Param->getIdentifier())
2114 Result = Param->getIdentifier()->getName();
2115
John McCall31168b02011-06-15 23:02:42 +00002116 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002117
2118 if (ObjCMethodParam) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002119 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2120 + Result + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002121 if (Param->getIdentifier())
2122 Result += Param->getIdentifier()->getName();
2123 }
2124
2125 return Result;
2126 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002127
Douglas Gregore90dd002010-08-24 16:15:59 +00002128 // We have the function prototype behind the block pointer type, as it was
2129 // written in the source.
Douglas Gregor67da50e2010-09-08 22:47:51 +00002130 std::string Result;
2131 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002132 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002133 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002134
2135 // Format the parameter list.
2136 std::string Params;
Douglas Gregor24bbc462011-02-15 22:37:09 +00002137 if (!BlockProto || Block->getNumArgs() == 0) {
2138 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002139 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002140 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002141 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002142 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002143 Params += "(";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002144 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2145 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002146 Params += ", ";
2147 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2148 /*SuppressName=*/false,
2149 /*SuppressBlock=*/true);
Douglas Gregor67da50e2010-09-08 22:47:51 +00002150
Douglas Gregor24bbc462011-02-15 22:37:09 +00002151 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002152 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002153 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002154 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002155 }
Douglas Gregor67da50e2010-09-08 22:47:51 +00002156
Douglas Gregord793e7c2011-10-18 04:23:19 +00002157 if (SuppressBlock) {
2158 // Format as a parameter.
2159 Result = Result + " (^";
2160 if (Param->getIdentifier())
2161 Result += Param->getIdentifier()->getName();
2162 Result += ")";
2163 Result += Params;
2164 } else {
2165 // Format as a block literal argument.
2166 Result = '^' + Result;
2167 Result += Params;
2168
2169 if (Param->getIdentifier())
2170 Result += Param->getIdentifier()->getName();
2171 }
2172
Douglas Gregore90dd002010-08-24 16:15:59 +00002173 return Result;
2174}
2175
Douglas Gregor3545ff42009-09-21 16:56:56 +00002176/// \brief Add function parameter chunks to the given code completion string.
2177static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002178 const PrintingPolicy &Policy,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002179 FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002180 CodeCompletionBuilder &Result,
2181 unsigned Start = 0,
2182 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002183 bool FirstParameter = true;
Douglas Gregor9eb77012009-11-07 00:00:49 +00002184
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002185 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002186 ParmVarDecl *Param = Function->getParamDecl(P);
2187
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002188 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002189 // When we see an optional default argument, put that argument and
2190 // the remaining default arguments into a new, optional string.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002191 CodeCompletionBuilder Opt(Result.getAllocator());
2192 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002193 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002194 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002195 Result.AddOptionalChunk(Opt.TakeString());
2196 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002197 }
2198
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002199 if (FirstParameter)
2200 FirstParameter = false;
2201 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002202 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002203
2204 InOptional = false;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002205
2206 // Format the placeholder string.
Douglas Gregor75acd922011-09-27 23:30:47 +00002207 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2208 Param);
Douglas Gregore90dd002010-08-24 16:15:59 +00002209
Douglas Gregor400f5972010-08-31 05:13:43 +00002210 if (Function->isVariadic() && P == N - 1)
2211 PlaceholderStr += ", ...";
2212
Douglas Gregor3545ff42009-09-21 16:56:56 +00002213 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002214 Result.AddPlaceholderChunk(
2215 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002216 }
Douglas Gregorba449032009-09-22 21:42:17 +00002217
2218 if (const FunctionProtoType *Proto
2219 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002220 if (Proto->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00002221 if (Proto->getNumArgs() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002222 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002223
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002224 MaybeAddSentinel(Context, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002225 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002226}
2227
2228/// \brief Add template parameter chunks to the given code completion string.
2229static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002230 const PrintingPolicy &Policy,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002231 TemplateDecl *Template,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002232 CodeCompletionBuilder &Result,
2233 unsigned MaxParameters = 0,
2234 unsigned Start = 0,
2235 bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002236 bool FirstParameter = true;
2237
2238 TemplateParameterList *Params = Template->getTemplateParameters();
2239 TemplateParameterList::iterator PEnd = Params->end();
2240 if (MaxParameters)
2241 PEnd = Params->begin() + MaxParameters;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002242 for (TemplateParameterList::iterator P = Params->begin() + Start;
2243 P != PEnd; ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002244 bool HasDefaultArg = false;
2245 std::string PlaceholderStr;
2246 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2247 if (TTP->wasDeclaredWithTypename())
2248 PlaceholderStr = "typename";
2249 else
2250 PlaceholderStr = "class";
2251
2252 if (TTP->getIdentifier()) {
2253 PlaceholderStr += ' ';
2254 PlaceholderStr += TTP->getIdentifier()->getName();
2255 }
2256
2257 HasDefaultArg = TTP->hasDefaultArgument();
2258 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002259 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002260 if (NTTP->getIdentifier())
2261 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002262 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002263 HasDefaultArg = NTTP->hasDefaultArgument();
2264 } else {
2265 assert(isa<TemplateTemplateParmDecl>(*P));
2266 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2267
2268 // Since putting the template argument list into the placeholder would
2269 // be very, very long, we just use an abbreviation.
2270 PlaceholderStr = "template<...> class";
2271 if (TTP->getIdentifier()) {
2272 PlaceholderStr += ' ';
2273 PlaceholderStr += TTP->getIdentifier()->getName();
2274 }
2275
2276 HasDefaultArg = TTP->hasDefaultArgument();
2277 }
2278
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002279 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002280 // When we see an optional default argument, put that argument and
2281 // the remaining default arguments into a new, optional string.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002282 CodeCompletionBuilder Opt(Result.getAllocator());
2283 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002284 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002285 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002286 P - Params->begin(), true);
2287 Result.AddOptionalChunk(Opt.TakeString());
2288 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002289 }
2290
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002291 InDefaultArg = false;
2292
Douglas Gregor3545ff42009-09-21 16:56:56 +00002293 if (FirstParameter)
2294 FirstParameter = false;
2295 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002296 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002297
2298 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002299 Result.AddPlaceholderChunk(
2300 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002301 }
2302}
2303
Douglas Gregorf2510672009-09-21 19:57:38 +00002304/// \brief Add a qualifier to the given code-completion string, if the
2305/// provided nested-name-specifier is non-NULL.
Douglas Gregor0f622362009-12-11 18:44:16 +00002306static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002307AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregor0f622362009-12-11 18:44:16 +00002308 NestedNameSpecifier *Qualifier,
2309 bool QualifierIsInformative,
Douglas Gregor75acd922011-09-27 23:30:47 +00002310 ASTContext &Context,
2311 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002312 if (!Qualifier)
2313 return;
2314
2315 std::string PrintedNNS;
2316 {
2317 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002318 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002319 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002320 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002321 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002322 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002323 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002324}
2325
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002326static void
2327AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2328 FunctionDecl *Function) {
Douglas Gregor0f622362009-12-11 18:44:16 +00002329 const FunctionProtoType *Proto
2330 = Function->getType()->getAs<FunctionProtoType>();
2331 if (!Proto || !Proto->getTypeQuals())
2332 return;
2333
Douglas Gregor304f9b02011-02-01 21:15:40 +00002334 // FIXME: Add ref-qualifier!
2335
2336 // Handle single qualifiers without copying
2337 if (Proto->getTypeQuals() == Qualifiers::Const) {
2338 Result.AddInformativeChunk(" const");
2339 return;
2340 }
2341
2342 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2343 Result.AddInformativeChunk(" volatile");
2344 return;
2345 }
2346
2347 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2348 Result.AddInformativeChunk(" restrict");
2349 return;
2350 }
2351
2352 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002353 std::string QualsStr;
2354 if (Proto->getTypeQuals() & Qualifiers::Const)
2355 QualsStr += " const";
2356 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2357 QualsStr += " volatile";
2358 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2359 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002360 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002361}
2362
Douglas Gregor0212fd72010-09-21 16:06:22 +00002363/// \brief Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002364static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2365 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002366 DeclarationName Name = ND->getDeclName();
2367 if (!Name)
2368 return;
2369
2370 switch (Name.getNameKind()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002371 case DeclarationName::CXXOperatorName: {
2372 const char *OperatorName = 0;
2373 switch (Name.getCXXOverloadedOperator()) {
2374 case OO_None:
2375 case OO_Conditional:
2376 case NUM_OVERLOADED_OPERATORS:
2377 OperatorName = "operator";
2378 break;
2379
2380#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2381 case OO_##Name: OperatorName = "operator" Spelling; break;
2382#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2383#include "clang/Basic/OperatorKinds.def"
2384
2385 case OO_New: OperatorName = "operator new"; break;
2386 case OO_Delete: OperatorName = "operator delete"; break;
2387 case OO_Array_New: OperatorName = "operator new[]"; break;
2388 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2389 case OO_Call: OperatorName = "operator()"; break;
2390 case OO_Subscript: OperatorName = "operator[]"; break;
2391 }
2392 Result.AddTypedTextChunk(OperatorName);
2393 break;
2394 }
2395
Douglas Gregor0212fd72010-09-21 16:06:22 +00002396 case DeclarationName::Identifier:
2397 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002398 case DeclarationName::CXXDestructorName:
2399 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002400 Result.AddTypedTextChunk(
2401 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002402 break;
2403
2404 case DeclarationName::CXXUsingDirective:
2405 case DeclarationName::ObjCZeroArgSelector:
2406 case DeclarationName::ObjCOneArgSelector:
2407 case DeclarationName::ObjCMultiArgSelector:
2408 break;
2409
2410 case DeclarationName::CXXConstructorName: {
2411 CXXRecordDecl *Record = 0;
2412 QualType Ty = Name.getCXXNameType();
2413 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2414 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2415 else if (const InjectedClassNameType *InjectedTy
2416 = Ty->getAs<InjectedClassNameType>())
2417 Record = InjectedTy->getDecl();
2418 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002419 Result.AddTypedTextChunk(
2420 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002421 break;
2422 }
2423
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002424 Result.AddTypedTextChunk(
2425 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002426 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002427 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002428 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002429 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002430 }
2431 break;
2432 }
2433 }
2434}
2435
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002436CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
2437 CodeCompletionAllocator &Allocator) {
2438 return CreateCodeCompletionString(S.Context, S.PP, Allocator);
2439}
2440
Douglas Gregor3545ff42009-09-21 16:56:56 +00002441/// \brief If possible, create a new code completion string for the given
2442/// result.
2443///
2444/// \returns Either a new, heap-allocated code completion string describing
2445/// how to use this result, or NULL to indicate that the string or name of the
2446/// result is all that is needed.
2447CodeCompletionString *
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002448CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2449 Preprocessor &PP,
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002450 CodeCompletionAllocator &Allocator) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002451 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor9eb77012009-11-07 00:00:49 +00002452
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002453 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002454 if (Kind == RK_Pattern) {
2455 Pattern->Priority = Priority;
2456 Pattern->Availability = Availability;
Douglas Gregor78254c82012-03-27 23:34:16 +00002457
2458 if (Declaration) {
2459 Result.addParentContext(Declaration->getDeclContext());
2460 Pattern->ParentKind = Result.getParentKind();
2461 Pattern->ParentName = Result.getParentName();
2462 }
2463
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002464 return Pattern;
2465 }
Douglas Gregorf09935f2009-12-01 05:55:20 +00002466
Douglas Gregorf09935f2009-12-01 05:55:20 +00002467 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002468 Result.AddTypedTextChunk(Keyword);
2469 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002470 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002471
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002472 if (Kind == RK_Macro) {
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002473 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregorf09935f2009-12-01 05:55:20 +00002474 assert(MI && "Not a macro?");
2475
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002476 Result.AddTypedTextChunk(
2477 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregorf09935f2009-12-01 05:55:20 +00002478
2479 if (!MI->isFunctionLike())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002480 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002481
2482 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002483 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor0c505312011-07-30 08:17:44 +00002484 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002485
2486 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2487 if (MI->isC99Varargs()) {
2488 --AEnd;
2489
2490 if (A == AEnd) {
2491 Result.AddPlaceholderChunk("...");
2492 }
Douglas Gregor0c505312011-07-30 08:17:44 +00002493 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002494
Douglas Gregor0c505312011-07-30 08:17:44 +00002495 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002496 if (A != MI->arg_begin())
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002497 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3aa55262012-01-21 00:43:38 +00002498
2499 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002500 SmallString<32> Arg = (*A)->getName();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002501 if (MI->isC99Varargs())
2502 Arg += ", ...";
2503 else
2504 Arg += "...";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002505 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3aa55262012-01-21 00:43:38 +00002506 break;
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002507 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002508
2509 // Non-variadic macros are simple.
2510 Result.AddPlaceholderChunk(
2511 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor0c505312011-07-30 08:17:44 +00002512 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002513 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002514 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002515 }
2516
Douglas Gregorf64acca2010-05-25 21:41:55 +00002517 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor3545ff42009-09-21 16:56:56 +00002518 NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002519 Result.addParentContext(ND->getDeclContext());
2520
Douglas Gregor9eb77012009-11-07 00:00:49 +00002521 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002522 Result.AddTypedTextChunk(
2523 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002524 Result.AddTextChunk("::");
2525 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002526 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002527
2528 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2529 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2530 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2531 }
2532 }
Douglas Gregor9eb77012009-11-07 00:00:49 +00002533
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002534 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002535
Douglas Gregor3545ff42009-09-21 16:56:56 +00002536 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002537 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002538 Ctx, Policy);
2539 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002540 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002541 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002542 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002543 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002544 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002545 }
2546
2547 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002548 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002549 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002550 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002551 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002552
Douglas Gregor3545ff42009-09-21 16:56:56 +00002553 // Figure out which template parameters are deduced (or have default
2554 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002555 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002556 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002557 unsigned LastDeducibleArgument;
2558 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2559 --LastDeducibleArgument) {
2560 if (!Deduced[LastDeducibleArgument - 1]) {
2561 // C++0x: Figure out if the template argument has a default. If so,
2562 // the user doesn't need to type this argument.
2563 // FIXME: We need to abstract template parameters better!
2564 bool HasDefaultArg = false;
2565 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002566 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002567 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2568 HasDefaultArg = TTP->hasDefaultArgument();
2569 else if (NonTypeTemplateParmDecl *NTTP
2570 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2571 HasDefaultArg = NTTP->hasDefaultArgument();
2572 else {
2573 assert(isa<TemplateTemplateParmDecl>(Param));
2574 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002575 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002576 }
2577
2578 if (!HasDefaultArg)
2579 break;
2580 }
2581 }
2582
2583 if (LastDeducibleArgument) {
2584 // Some of the function template arguments cannot be deduced from a
2585 // function call, so we introduce an explicit template argument list
2586 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002587 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002588 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002589 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002590 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002591 }
2592
2593 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002594 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002595 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002596 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002597 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002598 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002599 }
2600
2601 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002602 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002603 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002604 Result.AddTypedTextChunk(
2605 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002606 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002607 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002608 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002609 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002610 }
2611
Douglas Gregord3c5d792009-11-17 16:44:22 +00002612 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002613 Selector Sel = Method->getSelector();
2614 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002615 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002616 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002617 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002618 }
2619
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002620 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002621 SelName += ':';
2622 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002623 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002624 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002625 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002626
2627 // If there is only one parameter, and we're past it, add an empty
2628 // typed-text chunk since there is nothing to type.
2629 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002630 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002631 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002632 unsigned Idx = 0;
2633 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2634 PEnd = Method->param_end();
2635 P != PEnd; (void)++P, ++Idx) {
2636 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002637 std::string Keyword;
2638 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002639 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002640 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002641 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002642 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002643 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002644 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002645 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002646 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002647 }
Douglas Gregor1b605f72009-11-19 01:08:35 +00002648
2649 // If we're before the starting parameter, skip the placeholder.
2650 if (Idx < StartParameter)
2651 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002652
2653 std::string Arg;
Douglas Gregore90dd002010-08-24 16:15:59 +00002654
2655 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002656 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregore90dd002010-08-24 16:15:59 +00002657 else {
John McCall31168b02011-06-15 23:02:42 +00002658 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor8f08d742011-07-30 07:55:26 +00002659 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2660 + Arg + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002661 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00002662 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00002663 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00002664 }
2665
Douglas Gregor400f5972010-08-31 05:13:43 +00002666 if (Method->isVariadic() && (P + 1) == PEnd)
2667 Arg += ", ...";
2668
Douglas Gregor95887f92010-07-08 23:20:03 +00002669 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002670 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00002671 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002672 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00002673 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002674 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002675 }
2676
Douglas Gregor04c5f972009-12-23 00:21:46 +00002677 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00002678 if (Method->param_size() == 0) {
2679 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002680 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002681 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002682 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002683 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002684 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002685 }
Douglas Gregordbb71db2010-08-23 23:51:41 +00002686
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002687 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00002688 }
2689
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002690 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002691 }
2692
Douglas Gregorf09935f2009-12-01 05:55:20 +00002693 if (Qualifier)
Douglas Gregor5bf52692009-09-22 23:15:58 +00002694 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002695 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00002696
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002697 Result.AddTypedTextChunk(
2698 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002699 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002700}
2701
Douglas Gregorf0f51982009-09-23 00:34:09 +00002702CodeCompletionString *
2703CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2704 unsigned CurrentArg,
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00002705 Sema &S,
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002706 CodeCompletionAllocator &Allocator) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00002707 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00002708
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002709 // FIXME: Set priority, availability appropriately.
2710 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002711 FunctionDecl *FDecl = getFunction();
Douglas Gregor75acd922011-09-27 23:30:47 +00002712 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002713 const FunctionProtoType *Proto
2714 = dyn_cast<FunctionProtoType>(getFunctionType());
2715 if (!FDecl && !Proto) {
2716 // Function without a prototype. Just give the return type and a
2717 // highlighted ellipsis.
2718 const FunctionType *FT = getFunctionType();
Douglas Gregor304f9b02011-02-01 21:15:40 +00002719 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00002720 S.Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002721 Result.getAllocator()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002722 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2723 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2724 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002725 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00002726 }
2727
2728 if (FDecl)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002729 Result.AddTextChunk(
2730 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002731 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002732 Result.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002733 Result.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00002734 Proto->getResultType().getAsString(Policy)));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002735
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002736 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002737 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2738 for (unsigned I = 0; I != NumParams; ++I) {
2739 if (I)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002740 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002741
2742 std::string ArgString;
2743 QualType ArgType;
2744
2745 if (FDecl) {
2746 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2747 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2748 } else {
2749 ArgType = Proto->getArgType(I);
2750 }
2751
John McCall31168b02011-06-15 23:02:42 +00002752 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002753
2754 if (I == CurrentArg)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002755 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2756 Result.getAllocator().CopyString(ArgString));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002757 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002758 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002759 }
2760
2761 if (Proto && Proto->isVariadic()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002762 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002763 if (CurrentArg < NumParams)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002764 Result.AddTextChunk("...");
Douglas Gregorf0f51982009-09-23 00:34:09 +00002765 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002766 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregorf0f51982009-09-23 00:34:09 +00002767 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002768 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002769
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002770 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00002771}
2772
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002773unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002774 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00002775 bool PreferredTypeIsPointer) {
2776 unsigned Priority = CCP_Macro;
2777
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002778 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2779 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2780 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00002781 Priority = CCP_Constant;
2782 if (PreferredTypeIsPointer)
2783 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002784 }
2785 // Treat "YES", "NO", "true", and "false" as constants.
2786 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2787 MacroName.equals("true") || MacroName.equals("false"))
2788 Priority = CCP_Constant;
2789 // Treat "bool" as a type.
2790 else if (MacroName.equals("bool"))
2791 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2792
Douglas Gregor6e240332010-08-16 16:18:59 +00002793
2794 return Priority;
2795}
2796
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002797CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2798 if (!D)
2799 return CXCursor_UnexposedDecl;
2800
2801 switch (D->getKind()) {
2802 case Decl::Enum: return CXCursor_EnumDecl;
2803 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2804 case Decl::Field: return CXCursor_FieldDecl;
2805 case Decl::Function:
2806 return CXCursor_FunctionDecl;
2807 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2808 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002809 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00002810
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00002811 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002812 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2813 case Decl::ObjCMethod:
2814 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2815 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2816 case Decl::CXXMethod: return CXCursor_CXXMethod;
2817 case Decl::CXXConstructor: return CXCursor_Constructor;
2818 case Decl::CXXDestructor: return CXCursor_Destructor;
2819 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2820 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00002821 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002822 case Decl::ParmVar: return CXCursor_ParmDecl;
2823 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00002824 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002825 case Decl::Var: return CXCursor_VarDecl;
2826 case Decl::Namespace: return CXCursor_Namespace;
2827 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2828 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2829 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2830 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2831 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2832 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00002833 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002834 case Decl::ClassTemplatePartialSpecialization:
2835 return CXCursor_ClassTemplatePartialSpecialization;
2836 case Decl::UsingDirective: return CXCursor_UsingDirective;
2837
2838 case Decl::Using:
2839 case Decl::UnresolvedUsingValue:
2840 case Decl::UnresolvedUsingTypename:
2841 return CXCursor_UsingDeclaration;
2842
Douglas Gregor4cd65962011-06-03 23:08:58 +00002843 case Decl::ObjCPropertyImpl:
2844 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2845 case ObjCPropertyImplDecl::Dynamic:
2846 return CXCursor_ObjCDynamicDecl;
2847
2848 case ObjCPropertyImplDecl::Synthesize:
2849 return CXCursor_ObjCSynthesizeDecl;
2850 }
Douglas Gregor4cd65962011-06-03 23:08:58 +00002851
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002852 default:
2853 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2854 switch (TD->getTagKind()) {
2855 case TTK_Struct: return CXCursor_StructDecl;
2856 case TTK_Class: return CXCursor_ClassDecl;
2857 case TTK_Union: return CXCursor_UnionDecl;
2858 case TTK_Enum: return CXCursor_EnumDecl;
2859 }
2860 }
2861 }
2862
2863 return CXCursor_UnexposedDecl;
2864}
2865
Douglas Gregor55b037b2010-07-08 20:55:51 +00002866static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2867 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00002868 typedef CodeCompletionResult Result;
Douglas Gregor55b037b2010-07-08 20:55:51 +00002869
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002870 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002871
Douglas Gregor9eb77012009-11-07 00:00:49 +00002872 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2873 MEnd = PP.macro_end();
Douglas Gregor55b037b2010-07-08 20:55:51 +00002874 M != MEnd; ++M) {
Douglas Gregor6e240332010-08-16 16:18:59 +00002875 Results.AddResult(Result(M->first,
2876 getMacroUsagePriority(M->first->getName(),
David Blaikiebbafb8a2012-03-11 07:00:24 +00002877 PP.getLangOpts(),
Douglas Gregor6e240332010-08-16 16:18:59 +00002878 TargetTypeIsPointer)));
Douglas Gregor55b037b2010-07-08 20:55:51 +00002879 }
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002880
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002881 Results.ExitScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002882
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002883}
2884
Douglas Gregorce0e8562010-08-23 21:54:33 +00002885static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2886 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00002887 typedef CodeCompletionResult Result;
Douglas Gregorce0e8562010-08-23 21:54:33 +00002888
2889 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002890
Douglas Gregorce0e8562010-08-23 21:54:33 +00002891 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2892 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2893 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2894 Results.AddResult(Result("__func__", CCP_Constant));
2895 Results.ExitScope();
2896}
2897
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00002898static void HandleCodeCompleteResults(Sema *S,
2899 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002900 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00002901 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002902 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002903 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002904 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002905}
2906
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002907static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2908 Sema::ParserCompletionContext PCC) {
2909 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00002910 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002911 return CodeCompletionContext::CCC_TopLevel;
2912
John McCallfaf5fb42010-08-26 23:41:50 +00002913 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002914 return CodeCompletionContext::CCC_ClassStructUnion;
2915
John McCallfaf5fb42010-08-26 23:41:50 +00002916 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002917 return CodeCompletionContext::CCC_ObjCInterface;
2918
John McCallfaf5fb42010-08-26 23:41:50 +00002919 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002920 return CodeCompletionContext::CCC_ObjCImplementation;
2921
John McCallfaf5fb42010-08-26 23:41:50 +00002922 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002923 return CodeCompletionContext::CCC_ObjCIvarList;
2924
John McCallfaf5fb42010-08-26 23:41:50 +00002925 case Sema::PCC_Template:
2926 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00002927 if (S.CurContext->isFileContext())
2928 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00002929 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00002930 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00002931 return CodeCompletionContext::CCC_Other;
Douglas Gregor0ac41382010-09-23 23:01:17 +00002932
John McCallfaf5fb42010-08-26 23:41:50 +00002933 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00002934 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00002935
John McCallfaf5fb42010-08-26 23:41:50 +00002936 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002937 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2938 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00002939 return CodeCompletionContext::CCC_ParenthesizedExpression;
2940 else
2941 return CodeCompletionContext::CCC_Expression;
2942
2943 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00002944 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002945 return CodeCompletionContext::CCC_Expression;
2946
John McCallfaf5fb42010-08-26 23:41:50 +00002947 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002948 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00002949
John McCallfaf5fb42010-08-26 23:41:50 +00002950 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00002951 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00002952
2953 case Sema::PCC_ParenthesizedExpression:
2954 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor80039242011-02-15 20:33:25 +00002955
2956 case Sema::PCC_LocalDeclarationSpecifiers:
2957 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002958 }
David Blaikie8a40f702012-01-17 06:56:22 +00002959
2960 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002961}
2962
Douglas Gregorac322ec2010-08-27 21:18:54 +00002963/// \brief If we're in a C++ virtual member function, add completion results
2964/// that invoke the functions we override, since it's common to invoke the
2965/// overridden function as well as adding new functionality.
2966///
2967/// \param S The semantic analysis object for which we are generating results.
2968///
2969/// \param InContext This context in which the nested-name-specifier preceding
2970/// the code-completion point
2971static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2972 ResultBuilder &Results) {
2973 // Look through blocks.
2974 DeclContext *CurContext = S.CurContext;
2975 while (isa<BlockDecl>(CurContext))
2976 CurContext = CurContext->getParent();
2977
2978
2979 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2980 if (!Method || !Method->isVirtual())
2981 return;
2982
2983 // We need to have names for all of the parameters, if we're going to
2984 // generate a forwarding call.
2985 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2986 PEnd = Method->param_end();
2987 P != PEnd;
2988 ++P) {
2989 if (!(*P)->getDeclName())
2990 return;
2991 }
2992
Douglas Gregor75acd922011-09-27 23:30:47 +00002993 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorac322ec2010-08-27 21:18:54 +00002994 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2995 MEnd = Method->end_overridden_methods();
2996 M != MEnd; ++M) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002997 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorac322ec2010-08-27 21:18:54 +00002998 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2999 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3000 continue;
3001
3002 // If we need a nested-name-specifier, add one now.
3003 if (!InContext) {
3004 NestedNameSpecifier *NNS
3005 = getRequiredQualification(S.Context, CurContext,
3006 Overridden->getDeclContext());
3007 if (NNS) {
3008 std::string Str;
3009 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003010 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003011 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003012 }
3013 } else if (!InContext->Equals(Overridden->getDeclContext()))
3014 continue;
3015
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003016 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003017 Overridden->getNameAsString()));
3018 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003019 bool FirstParam = true;
3020 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3021 PEnd = Method->param_end();
3022 P != PEnd; ++P) {
3023 if (FirstParam)
3024 FirstParam = false;
3025 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003026 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003027
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003028 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003029 (*P)->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003030 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003031 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3032 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003033 CCP_SuperCompletion,
Douglas Gregor78254c82012-03-27 23:34:16 +00003034 CXCursor_CXXMethod,
3035 CXAvailability_Available,
3036 Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003037 Results.Ignore(Overridden);
3038 }
3039}
3040
Douglas Gregor07f43572012-01-29 18:15:03 +00003041void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3042 ModuleIdPath Path) {
3043 typedef CodeCompletionResult Result;
3044 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3045 CodeCompletionContext::CCC_Other);
3046 Results.EnterNewScope();
3047
3048 CodeCompletionAllocator &Allocator = Results.getAllocator();
3049 CodeCompletionBuilder Builder(Allocator);
3050 typedef CodeCompletionResult Result;
3051 if (Path.empty()) {
3052 // Enumerate all top-level modules.
3053 llvm::SmallVector<Module *, 8> Modules;
3054 PP.getHeaderSearchInfo().collectAllModules(Modules);
3055 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3056 Builder.AddTypedTextChunk(
3057 Builder.getAllocator().CopyString(Modules[I]->Name));
3058 Results.AddResult(Result(Builder.TakeString(),
3059 CCP_Declaration,
3060 CXCursor_NotImplemented,
3061 Modules[I]->isAvailable()
3062 ? CXAvailability_Available
3063 : CXAvailability_NotAvailable));
3064 }
3065 } else {
3066 // Load the named module.
3067 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3068 Module::AllVisible,
3069 /*IsInclusionDirective=*/false);
3070 // Enumerate submodules.
3071 if (Mod) {
3072 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3073 SubEnd = Mod->submodule_end();
3074 Sub != SubEnd; ++Sub) {
3075
3076 Builder.AddTypedTextChunk(
3077 Builder.getAllocator().CopyString((*Sub)->Name));
3078 Results.AddResult(Result(Builder.TakeString(),
3079 CCP_Declaration,
3080 CXCursor_NotImplemented,
3081 (*Sub)->isAvailable()
3082 ? CXAvailability_Available
3083 : CXAvailability_NotAvailable));
3084 }
3085 }
3086 }
3087 Results.ExitScope();
3088 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3089 Results.data(),Results.size());
3090}
3091
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003092void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003093 ParserCompletionContext CompletionContext) {
John McCall276321a2010-08-25 06:19:51 +00003094 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003095 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003096 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003097 Results.EnterNewScope();
Douglas Gregor50832e02010-09-20 22:39:41 +00003098
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003099 // Determine how to filter results, e.g., so that the names of
3100 // values (functions, enumerators, function templates, etc.) are
3101 // only allowed where we can have an expression.
3102 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003103 case PCC_Namespace:
3104 case PCC_Class:
3105 case PCC_ObjCInterface:
3106 case PCC_ObjCImplementation:
3107 case PCC_ObjCInstanceVariableList:
3108 case PCC_Template:
3109 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003110 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003111 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003112 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3113 break;
3114
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003115 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003116 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003117 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003118 case PCC_ForInit:
3119 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003120 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003121 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3122 else
3123 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003124
David Blaikiebbafb8a2012-03-11 07:00:24 +00003125 if (getLangOpts().CPlusPlus)
Douglas Gregorac322ec2010-08-27 21:18:54 +00003126 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003127 break;
Douglas Gregor6da3db42010-05-25 05:58:43 +00003128
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003129 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003130 // Unfiltered
3131 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003132 }
3133
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003134 // If we are in a C++ non-static member function, check the qualifiers on
3135 // the member function to filter/prioritize the results list.
3136 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3137 if (CurMethod->isInstance())
3138 Results.setObjectTypeQualifiers(
3139 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3140
Douglas Gregorc580c522010-01-14 01:09:38 +00003141 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003142 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3143 CodeCompleter->includeGlobals());
Douglas Gregor92253692009-12-07 09:54:55 +00003144
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003145 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003146 Results.ExitScope();
3147
Douglas Gregorce0e8562010-08-23 21:54:33 +00003148 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003149 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003150 case PCC_Expression:
3151 case PCC_Statement:
3152 case PCC_RecoveryInFunction:
3153 if (S->getFnParent())
David Blaikiebbafb8a2012-03-11 07:00:24 +00003154 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003155 break;
3156
3157 case PCC_Namespace:
3158 case PCC_Class:
3159 case PCC_ObjCInterface:
3160 case PCC_ObjCImplementation:
3161 case PCC_ObjCInstanceVariableList:
3162 case PCC_Template:
3163 case PCC_MemberTemplate:
3164 case PCC_ForInit:
3165 case PCC_Condition:
3166 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003167 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003168 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003169 }
3170
Douglas Gregor9eb77012009-11-07 00:00:49 +00003171 if (CodeCompleter->includeMacros())
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003172 AddMacroResults(PP, Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003173
Douglas Gregor50832e02010-09-20 22:39:41 +00003174 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003175 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003176}
3177
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003178static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3179 ParsedType Receiver,
3180 IdentifierInfo **SelIdents,
3181 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003182 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003183 bool IsSuper,
3184 ResultBuilder &Results);
3185
3186void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3187 bool AllowNonIdentifiers,
3188 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003189 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003190 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003191 AllowNestedNameSpecifiers
3192 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3193 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003194 Results.EnterNewScope();
3195
3196 // Type qualifiers can come after names.
3197 Results.AddResult(Result("const"));
3198 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003199 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003200 Results.AddResult(Result("restrict"));
3201
David Blaikiebbafb8a2012-03-11 07:00:24 +00003202 if (getLangOpts().CPlusPlus) {
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003203 if (AllowNonIdentifiers) {
3204 Results.AddResult(Result("operator"));
3205 }
3206
3207 // Add nested-name-specifiers.
3208 if (AllowNestedNameSpecifiers) {
3209 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003210 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003211 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3212 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3213 CodeCompleter->includeGlobals());
Douglas Gregor0ac41382010-09-23 23:01:17 +00003214 Results.setFilter(0);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003215 }
3216 }
3217 Results.ExitScope();
3218
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003219 // If we're in a context where we might have an expression (rather than a
3220 // declaration), and what we've seen so far is an Objective-C type that could
3221 // be a receiver of a class message, this may be a class message send with
3222 // the initial opening bracket '[' missing. Add appropriate completions.
3223 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3224 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3225 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3226 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3227 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3228 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3229 DS.getTypeQualifiers() == 0 &&
3230 S &&
3231 (S->getFlags() & Scope::DeclScope) != 0 &&
3232 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3233 Scope::FunctionPrototypeScope |
3234 Scope::AtCatchScope)) == 0) {
3235 ParsedType T = DS.getRepAsType();
3236 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003237 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003238 }
3239
Douglas Gregor56ccce02010-08-24 04:59:56 +00003240 // Note that we intentionally suppress macro results here, since we do not
3241 // encourage using macros to produce the names of entities.
3242
Douglas Gregor0ac41382010-09-23 23:01:17 +00003243 HandleCodeCompleteResults(this, CodeCompleter,
3244 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003245 Results.data(), Results.size());
3246}
3247
Douglas Gregor68762e72010-08-23 21:17:50 +00003248struct Sema::CodeCompleteExpressionData {
3249 CodeCompleteExpressionData(QualType PreferredType = QualType())
3250 : PreferredType(PreferredType), IntegralConstantExpression(false),
3251 ObjCCollection(false) { }
3252
3253 QualType PreferredType;
3254 bool IntegralConstantExpression;
3255 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003256 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003257};
3258
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003259/// \brief Perform code-completion in an expression context when we know what
3260/// type we're looking for.
Douglas Gregor85b50632010-07-28 21:50:18 +00003261///
3262/// \param IntegralConstantExpression Only permit integral constant
3263/// expressions.
Douglas Gregor68762e72010-08-23 21:17:50 +00003264void Sema::CodeCompleteExpression(Scope *S,
3265 const CodeCompleteExpressionData &Data) {
John McCall276321a2010-08-25 06:19:51 +00003266 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003267 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3268 CodeCompletionContext::CCC_Expression);
Douglas Gregor68762e72010-08-23 21:17:50 +00003269 if (Data.ObjCCollection)
3270 Results.setFilter(&ResultBuilder::IsObjCCollection);
3271 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003272 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003273 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003274 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3275 else
3276 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003277
3278 if (!Data.PreferredType.isNull())
3279 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3280
3281 // Ignore any declarations that we were told that we don't care about.
3282 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3283 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003284
3285 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003286 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3287 CodeCompleter->includeGlobals());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003288
3289 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003290 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003291 Results.ExitScope();
3292
Douglas Gregor55b037b2010-07-08 20:55:51 +00003293 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003294 if (!Data.PreferredType.isNull())
3295 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3296 || Data.PreferredType->isMemberPointerType()
3297 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003298
Douglas Gregorce0e8562010-08-23 21:54:33 +00003299 if (S->getFnParent() &&
3300 !Data.ObjCCollection &&
3301 !Data.IntegralConstantExpression)
David Blaikiebbafb8a2012-03-11 07:00:24 +00003302 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003303
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003304 if (CodeCompleter->includeMacros())
Douglas Gregor55b037b2010-07-08 20:55:51 +00003305 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003306 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor68762e72010-08-23 21:17:50 +00003307 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3308 Data.PreferredType),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003309 Results.data(),Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003310}
3311
Douglas Gregoreda7e542010-09-18 01:28:11 +00003312void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3313 if (E.isInvalid())
3314 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003315 else if (getLangOpts().ObjC1)
Douglas Gregoreda7e542010-09-18 01:28:11 +00003316 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003317}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003318
Douglas Gregorb888acf2010-12-09 23:01:55 +00003319/// \brief The set of properties that have already been added, referenced by
3320/// property name.
3321typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3322
Douglas Gregor9291bad2009-11-18 01:29:26 +00003323static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor5d649882009-11-18 22:32:06 +00003324 bool AllowCategories,
Douglas Gregor95147142011-05-05 15:50:42 +00003325 bool AllowNullaryMethods,
Douglas Gregor9291bad2009-11-18 01:29:26 +00003326 DeclContext *CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003327 AddedPropertiesSet &AddedProperties,
Douglas Gregor9291bad2009-11-18 01:29:26 +00003328 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003329 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003330
3331 // Add properties in this container.
3332 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3333 PEnd = Container->prop_end();
3334 P != PEnd;
Douglas Gregorb888acf2010-12-09 23:01:55 +00003335 ++P) {
3336 if (AddedProperties.insert(P->getIdentifier()))
3337 Results.MaybeAddResult(Result(*P, 0), CurContext);
3338 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003339
Douglas Gregor95147142011-05-05 15:50:42 +00003340 // Add nullary methods
3341 if (AllowNullaryMethods) {
3342 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003343 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor95147142011-05-05 15:50:42 +00003344 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3345 MEnd = Container->meth_end();
3346 M != MEnd; ++M) {
3347 if (M->getSelector().isUnarySelector())
3348 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3349 if (AddedProperties.insert(Name)) {
3350 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor75acd922011-09-27 23:30:47 +00003351 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor95147142011-05-05 15:50:42 +00003352 Builder.AddTypedTextChunk(
3353 Results.getAllocator().CopyString(Name->getName()));
3354
Douglas Gregor78254c82012-03-27 23:34:16 +00003355 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
3356 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor95147142011-05-05 15:50:42 +00003357 CurContext);
3358 }
3359 }
3360 }
3361
3362
Douglas Gregor9291bad2009-11-18 01:29:26 +00003363 // Add properties in referenced protocols.
3364 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3365 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3366 PEnd = Protocol->protocol_end();
3367 P != PEnd; ++P)
Douglas Gregor95147142011-05-05 15:50:42 +00003368 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3369 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003370 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003371 if (AllowCategories) {
3372 // Look through categories.
3373 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3374 Category; Category = Category->getNextClassCategory())
Douglas Gregor95147142011-05-05 15:50:42 +00003375 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3376 CurContext, AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00003377 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003378
3379 // Look through protocols.
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003380 for (ObjCInterfaceDecl::all_protocol_iterator
3381 I = IFace->all_referenced_protocol_begin(),
3382 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor95147142011-05-05 15:50:42 +00003383 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3384 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003385
3386 // Look in the superclass.
3387 if (IFace->getSuperClass())
Douglas Gregor95147142011-05-05 15:50:42 +00003388 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3389 AllowNullaryMethods, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003390 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003391 } else if (const ObjCCategoryDecl *Category
3392 = dyn_cast<ObjCCategoryDecl>(Container)) {
3393 // Look through protocols.
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003394 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3395 PEnd = Category->protocol_end();
Douglas Gregor9291bad2009-11-18 01:29:26 +00003396 P != PEnd; ++P)
Douglas Gregor95147142011-05-05 15:50:42 +00003397 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3398 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003399 }
3400}
3401
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003402void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor2436e712009-09-17 21:32:03 +00003403 SourceLocation OpLoc,
3404 bool IsArrow) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003405 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00003406 return;
3407
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003408 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3409 if (ConvertedBase.isInvalid())
3410 return;
3411 Base = ConvertedBase.get();
3412
John McCall276321a2010-08-25 06:19:51 +00003413 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003414
Douglas Gregor2436e712009-09-17 21:32:03 +00003415 QualType BaseType = Base->getType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003416
3417 if (IsArrow) {
3418 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3419 BaseType = Ptr->getPointeeType();
3420 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003421 /*Do nothing*/ ;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003422 else
3423 return;
3424 }
3425
Douglas Gregor21325842011-07-07 16:03:39 +00003426 enum CodeCompletionContext::Kind contextKind;
3427
3428 if (IsArrow) {
3429 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3430 }
3431 else {
3432 if (BaseType->isObjCObjectPointerType() ||
3433 BaseType->isObjCObjectOrInterfaceType()) {
3434 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3435 }
3436 else {
3437 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3438 }
3439 }
3440
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003441 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor21325842011-07-07 16:03:39 +00003442 CodeCompletionContext(contextKind,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003443 BaseType),
3444 &ResultBuilder::IsMember);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003445 Results.EnterNewScope();
3446 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003447 // Indicate that we are performing a member access, and the cv-qualifiers
3448 // for the base object type.
3449 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3450
Douglas Gregor9291bad2009-11-18 01:29:26 +00003451 // Access to a C/C++ class, struct, or union.
Douglas Gregor6ae4c522010-01-14 03:21:49 +00003452 Results.allowNestedNameSpecifiers();
Douglas Gregor09bbc652010-01-14 15:47:35 +00003453 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003454 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3455 CodeCompleter->includeGlobals());
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003456
David Blaikiebbafb8a2012-03-11 07:00:24 +00003457 if (getLangOpts().CPlusPlus) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003458 if (!Results.empty()) {
3459 // The "template" keyword can follow "->" or "." in the grammar.
3460 // However, we only want to suggest the template keyword if something
3461 // is dependent.
3462 bool IsDependent = BaseType->isDependentType();
3463 if (!IsDependent) {
3464 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3465 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3466 IsDependent = Ctx->isDependentContext();
3467 break;
3468 }
3469 }
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003470
Douglas Gregor9291bad2009-11-18 01:29:26 +00003471 if (IsDependent)
Douglas Gregor78a21012010-01-14 16:01:26 +00003472 Results.AddResult(Result("template"));
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003473 }
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003474 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003475 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3476 // Objective-C property reference.
Douglas Gregorb888acf2010-12-09 23:01:55 +00003477 AddedPropertiesSet AddedProperties;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003478
3479 // Add property results based on our interface.
3480 const ObjCObjectPointerType *ObjCPtr
3481 = BaseType->getAsObjCInterfacePointerType();
3482 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor95147142011-05-05 15:50:42 +00003483 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3484 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003485 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003486
3487 // Add properties from the protocols in a qualified interface.
3488 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3489 E = ObjCPtr->qual_end();
3490 I != E; ++I)
Douglas Gregor95147142011-05-05 15:50:42 +00003491 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3492 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003493 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCall8b07ec22010-05-15 11:32:37 +00003494 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003495 // Objective-C instance variable access.
3496 ObjCInterfaceDecl *Class = 0;
3497 if (const ObjCObjectPointerType *ObjCPtr
3498 = BaseType->getAs<ObjCObjectPointerType>())
3499 Class = ObjCPtr->getInterfaceDecl();
3500 else
John McCall8b07ec22010-05-15 11:32:37 +00003501 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor9291bad2009-11-18 01:29:26 +00003502
3503 // Add all ivars from this class and its superclasses.
Douglas Gregor2b8162b2010-01-14 16:08:12 +00003504 if (Class) {
3505 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3506 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor39982192010-08-15 06:18:01 +00003507 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3508 CodeCompleter->includeGlobals());
Douglas Gregor9291bad2009-11-18 01:29:26 +00003509 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003510 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003511
3512 // FIXME: How do we cope with isa?
3513
3514 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003515
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003516 // Hand off the results found for code completion.
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003517 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003518 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003519 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00003520}
3521
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003522void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3523 if (!CodeCompleter)
3524 return;
3525
John McCall276321a2010-08-25 06:19:51 +00003526 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003527 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003528 enum CodeCompletionContext::Kind ContextKind
3529 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003530 switch ((DeclSpec::TST)TagSpec) {
3531 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003532 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003533 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003534 break;
3535
3536 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003537 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003538 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003539 break;
3540
3541 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003542 case DeclSpec::TST_class:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003543 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003544 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003545 break;
3546
3547 default:
David Blaikie83d382b2011-09-23 05:06:16 +00003548 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003549 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003550
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003551 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00003552 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00003553
3554 // First pass: look for tags.
3555 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00003556 LookupVisibleDecls(S, LookupTagName, Consumer,
3557 CodeCompleter->includeGlobals());
John McCalle87beb22010-04-23 18:46:30 +00003558
Douglas Gregor39982192010-08-15 06:18:01 +00003559 if (CodeCompleter->includeGlobals()) {
3560 // Second pass: look for nested name specifiers.
3561 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3562 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3563 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003564
Douglas Gregor0ac41382010-09-23 23:01:17 +00003565 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003566 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003567}
3568
Douglas Gregor28c78432010-08-27 17:35:51 +00003569void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003570 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3571 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00003572 Results.EnterNewScope();
3573 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3574 Results.AddResult("const");
3575 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3576 Results.AddResult("volatile");
David Blaikiebbafb8a2012-03-11 07:00:24 +00003577 if (getLangOpts().C99 &&
Douglas Gregor28c78432010-08-27 17:35:51 +00003578 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3579 Results.AddResult("restrict");
3580 Results.ExitScope();
3581 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003582 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00003583 Results.data(), Results.size());
3584}
3585
Douglas Gregord328d572009-09-21 18:10:23 +00003586void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00003587 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00003588 return;
John McCall5939b162011-08-06 07:30:58 +00003589
John McCallaab3e412010-08-25 08:40:02 +00003590 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00003591 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3592 if (!type->isEnumeralType()) {
3593 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00003594 Data.IntegralConstantExpression = true;
3595 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00003596 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00003597 }
Douglas Gregord328d572009-09-21 18:10:23 +00003598
3599 // Code-complete the cases of a switch statement over an enumeration type
3600 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00003601 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregord328d572009-09-21 18:10:23 +00003602
3603 // Determine which enumerators we have already seen in the switch statement.
3604 // FIXME: Ideally, we would also be able to look *past* the code-completion
3605 // token, in case we are code-completing in the middle of the switch and not
3606 // at the end. However, we aren't able to do so at the moment.
3607 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorf2510672009-09-21 19:57:38 +00003608 NestedNameSpecifier *Qualifier = 0;
Douglas Gregord328d572009-09-21 18:10:23 +00003609 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3610 SC = SC->getNextSwitchCase()) {
3611 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3612 if (!Case)
3613 continue;
3614
3615 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3616 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3617 if (EnumConstantDecl *Enumerator
3618 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3619 // We look into the AST of the case statement to determine which
3620 // enumerator was named. Alternatively, we could compute the value of
3621 // the integral constant expression, then compare it against the
3622 // values of each enumerator. However, value-based approach would not
3623 // work as well with C++ templates where enumerators declared within a
3624 // template are type- and value-dependent.
3625 EnumeratorsSeen.insert(Enumerator);
3626
Douglas Gregorf2510672009-09-21 19:57:38 +00003627 // If this is a qualified-id, keep track of the nested-name-specifier
3628 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00003629 //
3630 // switch (TagD.getKind()) {
3631 // case TagDecl::TK_enum:
3632 // break;
3633 // case XXX
3634 //
Douglas Gregorf2510672009-09-21 19:57:38 +00003635 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00003636 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3637 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00003638 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00003639 }
3640 }
3641
David Blaikiebbafb8a2012-03-11 07:00:24 +00003642 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorf2510672009-09-21 19:57:38 +00003643 // If there are no prior enumerators in C++, check whether we have to
3644 // qualify the names of the enumerators that we suggest, because they
3645 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00003646 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00003647 }
3648
Douglas Gregord328d572009-09-21 18:10:23 +00003649 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003650 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3651 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00003652 Results.EnterNewScope();
3653 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3654 EEnd = Enum->enumerator_end();
3655 E != EEnd; ++E) {
3656 if (EnumeratorsSeen.count(*E))
3657 continue;
3658
Douglas Gregor3a69eaf2011-02-18 23:30:37 +00003659 CodeCompletionResult R(*E, Qualifier);
3660 R.Priority = CCP_EnumInCase;
3661 Results.AddResult(R, CurContext, 0, false);
Douglas Gregord328d572009-09-21 18:10:23 +00003662 }
3663 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00003664
Douglas Gregor21325842011-07-07 16:03:39 +00003665 //We need to make sure we're setting the right context,
3666 //so only say we include macros if the code completer says we do
3667 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3668 if (CodeCompleter->includeMacros()) {
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003669 AddMacroResults(PP, Results);
Douglas Gregor21325842011-07-07 16:03:39 +00003670 kind = CodeCompletionContext::CCC_OtherWithMacros;
3671 }
3672
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003673 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00003674 kind,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003675 Results.data(),Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00003676}
3677
Douglas Gregorcabea402009-09-22 15:41:20 +00003678namespace {
3679 struct IsBetterOverloadCandidate {
3680 Sema &S;
John McCallbc077cf2010-02-08 23:07:23 +00003681 SourceLocation Loc;
Douglas Gregorcabea402009-09-22 15:41:20 +00003682
3683 public:
John McCallbc077cf2010-02-08 23:07:23 +00003684 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3685 : S(S), Loc(Loc) { }
Douglas Gregorcabea402009-09-22 15:41:20 +00003686
3687 bool
3688 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall5c32be02010-08-24 20:38:10 +00003689 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregorcabea402009-09-22 15:41:20 +00003690 }
3691 };
3692}
3693
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003694static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3695 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003696 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003697
3698 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003699 if (!Args[I])
3700 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003701
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003702 return false;
3703}
3704
Richard Trieu2bd04012011-09-09 02:00:50 +00003705void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003706 llvm::ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00003707 if (!CodeCompleter)
3708 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003709
3710 // When we're code-completing for a call, we fall back to ordinary
3711 // name code-completion whenever we can't produce specific
3712 // results. We may want to revisit this strategy in the future,
3713 // e.g., by merging the two kinds of results.
3714
Douglas Gregorcabea402009-09-22 15:41:20 +00003715 Expr *Fn = (Expr *)FnIn;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003716
Douglas Gregorcabea402009-09-22 15:41:20 +00003717 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003718 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3719 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003720 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00003721 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003722 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003723
John McCall57500772009-12-16 12:17:52 +00003724 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00003725 SourceLocation Loc = Fn->getExprLoc();
3726 OverloadCandidateSet CandidateSet(Loc);
John McCall57500772009-12-16 12:17:52 +00003727
Douglas Gregorcabea402009-09-22 15:41:20 +00003728 // FIXME: What if we're calling something that isn't a function declaration?
3729 // FIXME: What if we're calling a pseudo-destructor?
3730 // FIXME: What if we're calling a member function?
3731
Douglas Gregorff59f672010-01-21 15:46:19 +00003732 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003733 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00003734
John McCall57500772009-12-16 12:17:52 +00003735 Expr *NakedFn = Fn->IgnoreParenCasts();
3736 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003737 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall57500772009-12-16 12:17:52 +00003738 /*PartialOverloading=*/ true);
3739 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3740 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorff59f672010-01-21 15:46:19 +00003741 if (FDecl) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00003742 if (!getLangOpts().CPlusPlus ||
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003743 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorff59f672010-01-21 15:46:19 +00003744 Results.push_back(ResultCandidate(FDecl));
3745 else
John McCallb89836b2010-01-26 01:37:31 +00003746 // FIXME: access?
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003747 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3748 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorff59f672010-01-21 15:46:19 +00003749 }
John McCall57500772009-12-16 12:17:52 +00003750 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003751
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003752 QualType ParamType;
3753
Douglas Gregorff59f672010-01-21 15:46:19 +00003754 if (!CandidateSet.empty()) {
3755 // Sort the overload candidate set by placing the best overloads first.
3756 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCallbc077cf2010-02-08 23:07:23 +00003757 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregorcabea402009-09-22 15:41:20 +00003758
Douglas Gregorff59f672010-01-21 15:46:19 +00003759 // Add the remaining viable overload candidates as code-completion reslults.
3760 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3761 CandEnd = CandidateSet.end();
3762 Cand != CandEnd; ++Cand) {
3763 if (Cand->Viable)
3764 Results.push_back(ResultCandidate(Cand->Function));
3765 }
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003766
3767 // From the viable candidates, try to determine the type of this parameter.
3768 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3769 if (const FunctionType *FType = Results[I].getFunctionType())
3770 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003771 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003772 if (ParamType.isNull())
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003773 ParamType = Proto->getArgType(Args.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003774 else if (!Context.hasSameUnqualifiedType(
3775 ParamType.getNonReferenceType(),
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003776 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003777 ParamType = QualType();
3778 break;
3779 }
3780 }
3781 }
3782 } else {
3783 // Try to determine the parameter type from the type of the expression
3784 // being called.
3785 QualType FunctionType = Fn->getType();
3786 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3787 FunctionType = Ptr->getPointeeType();
3788 else if (const BlockPointerType *BlockPtr
3789 = FunctionType->getAs<BlockPointerType>())
3790 FunctionType = BlockPtr->getPointeeType();
3791 else if (const MemberPointerType *MemPtr
3792 = FunctionType->getAs<MemberPointerType>())
3793 FunctionType = MemPtr->getPointeeType();
3794
3795 if (const FunctionProtoType *Proto
3796 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003797 if (Args.size() < Proto->getNumArgs())
3798 ParamType = Proto->getArgType(Args.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003799 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003800 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00003801
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003802 if (ParamType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003803 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003804 else
3805 CodeCompleteExpression(S, ParamType);
3806
Douglas Gregorc01890e2010-04-06 20:19:47 +00003807 if (!Results.empty())
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003808 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregor3ef59522009-12-11 19:06:04 +00003809 Results.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00003810}
3811
John McCall48871652010-08-21 09:40:31 +00003812void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3813 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003814 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003815 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003816 return;
3817 }
3818
3819 CodeCompleteExpression(S, VD->getType());
3820}
3821
3822void Sema::CodeCompleteReturn(Scope *S) {
3823 QualType ResultType;
3824 if (isa<BlockDecl>(CurContext)) {
3825 if (BlockScopeInfo *BSI = getCurBlock())
3826 ResultType = BSI->ReturnType;
3827 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3828 ResultType = Function->getResultType();
3829 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3830 ResultType = Method->getResultType();
3831
3832 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003833 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003834 else
3835 CodeCompleteExpression(S, ResultType);
3836}
3837
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003838void Sema::CodeCompleteAfterIf(Scope *S) {
3839 typedef CodeCompletionResult Result;
3840 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3841 mapCodeCompletionContext(*this, PCC_Statement));
3842 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3843 Results.EnterNewScope();
3844
3845 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3846 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3847 CodeCompleter->includeGlobals());
3848
3849 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3850
3851 // "else" block
3852 CodeCompletionBuilder Builder(Results.getAllocator());
3853 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00003854 if (Results.includeCodePatterns()) {
3855 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3856 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3857 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3858 Builder.AddPlaceholderChunk("statements");
3859 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3860 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3861 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003862 Results.AddResult(Builder.TakeString());
3863
3864 // "else if" block
3865 Builder.AddTypedTextChunk("else");
3866 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3867 Builder.AddTextChunk("if");
3868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3869 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003870 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003871 Builder.AddPlaceholderChunk("condition");
3872 else
3873 Builder.AddPlaceholderChunk("expression");
3874 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00003875 if (Results.includeCodePatterns()) {
3876 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3877 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3878 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3879 Builder.AddPlaceholderChunk("statements");
3880 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3881 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3882 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003883 Results.AddResult(Builder.TakeString());
3884
3885 Results.ExitScope();
3886
3887 if (S->getFnParent())
David Blaikiebbafb8a2012-03-11 07:00:24 +00003888 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003889
3890 if (CodeCompleter->includeMacros())
3891 AddMacroResults(PP, Results);
3892
3893 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3894 Results.data(),Results.size());
3895}
3896
Richard Trieu2bd04012011-09-09 02:00:50 +00003897void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003898 if (LHS)
3899 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3900 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003901 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003902}
3903
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00003904void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00003905 bool EnteringContext) {
3906 if (!SS.getScopeRep() || !CodeCompleter)
3907 return;
3908
Douglas Gregor3545ff42009-09-21 16:56:56 +00003909 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3910 if (!Ctx)
3911 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00003912
3913 // Try to instantiate any non-dependent declaration contexts before
3914 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00003915 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00003916 return;
3917
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003918 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3919 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003920 Results.EnterNewScope();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003921
Douglas Gregor3545ff42009-09-21 16:56:56 +00003922 // The "template" keyword can follow "::" in the grammar, but only
3923 // put it into the grammar if the nested-name-specifier is dependent.
3924 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3925 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00003926 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00003927
3928 // Add calls to overridden virtual functions, if there are any.
3929 //
3930 // FIXME: This isn't wonderful, because we don't know whether we're actually
3931 // in a context that permits expressions. This is a general issue with
3932 // qualified-id completions.
3933 if (!EnteringContext)
3934 MaybeAddOverrideCalls(*this, Ctx, Results);
3935 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003936
Douglas Gregorac322ec2010-08-27 21:18:54 +00003937 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3938 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3939
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003940 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorc1679ec2011-07-25 17:48:11 +00003941 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003942 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00003943}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00003944
3945void Sema::CodeCompleteUsing(Scope *S) {
3946 if (!CodeCompleter)
3947 return;
3948
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003949 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003950 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3951 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00003952 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003953
3954 // If we aren't in class scope, we could see the "namespace" keyword.
3955 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00003956 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00003957
3958 // After "using", we can see anything that would start a
3959 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00003960 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003961 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3962 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00003963 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003964
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003965 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003966 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003967 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00003968}
3969
3970void Sema::CodeCompleteUsingDirective(Scope *S) {
3971 if (!CodeCompleter)
3972 return;
3973
Douglas Gregor3545ff42009-09-21 16:56:56 +00003974 // After "using namespace", we expect to see a namespace name or namespace
3975 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003976 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3977 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003978 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00003979 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00003980 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003981 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3982 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00003983 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003984 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00003985 CodeCompletionContext::CCC_Namespace,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003986 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00003987}
3988
3989void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3990 if (!CodeCompleter)
3991 return;
3992
Douglas Gregor3545ff42009-09-21 16:56:56 +00003993 DeclContext *Ctx = (DeclContext *)S->getEntity();
3994 if (!S->getParent())
3995 Ctx = Context.getTranslationUnitDecl();
3996
Douglas Gregor0ac41382010-09-23 23:01:17 +00003997 bool SuppressedGlobalResults
3998 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3999
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004000 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004001 SuppressedGlobalResults
4002 ? CodeCompletionContext::CCC_Namespace
4003 : CodeCompletionContext::CCC_Other,
4004 &ResultBuilder::IsNamespace);
4005
4006 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004007 // We only want to see those namespaces that have already been defined
4008 // within this scope, because its likely that the user is creating an
4009 // extended namespace declaration. Keep track of the most recent
4010 // definition of each namespace.
4011 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4012 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4013 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4014 NS != NSEnd; ++NS)
4015 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4016
4017 // Add the most recent definition (or extended definition) of each
4018 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004019 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004020 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregor78254c82012-03-27 23:34:16 +00004021 NS = OrigToLatest.begin(),
4022 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004023 NS != NSEnd; ++NS)
John McCall276321a2010-08-25 06:19:51 +00004024 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregorfc59ce12010-01-14 16:14:35 +00004025 CurContext, 0, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004026 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004027 }
4028
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004029 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004030 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004031 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004032}
4033
4034void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4035 if (!CodeCompleter)
4036 return;
4037
Douglas Gregor3545ff42009-09-21 16:56:56 +00004038 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004039 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4040 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004041 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004042 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004043 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4044 CodeCompleter->includeGlobals());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004045 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004046 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004047 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004048}
4049
Douglas Gregorc811ede2009-09-18 20:05:18 +00004050void Sema::CodeCompleteOperatorName(Scope *S) {
4051 if (!CodeCompleter)
4052 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004053
John McCall276321a2010-08-25 06:19:51 +00004054 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004055 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4056 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004057 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004058 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004059
Douglas Gregor3545ff42009-09-21 16:56:56 +00004060 // Add the names of overloadable operators.
4061#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4062 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004063 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004064#include "clang/Basic/OperatorKinds.def"
4065
4066 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004067 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004068 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004069 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4070 CodeCompleter->includeGlobals());
Douglas Gregor3545ff42009-09-21 16:56:56 +00004071
4072 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004073 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004074 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004075
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004076 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004077 CodeCompletionContext::CCC_Type,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004078 Results.data(),Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004079}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004080
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004081void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Alexis Hunt1d792652011-01-08 20:30:50 +00004082 CXXCtorInitializer** Initializers,
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004083 unsigned NumInitializers) {
Douglas Gregor75acd922011-09-27 23:30:47 +00004084 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004085 CXXConstructorDecl *Constructor
4086 = static_cast<CXXConstructorDecl *>(ConstructorD);
4087 if (!Constructor)
4088 return;
4089
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004090 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004091 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004092 Results.EnterNewScope();
4093
4094 // Fill in any already-initialized fields or base classes.
4095 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4096 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4097 for (unsigned I = 0; I != NumInitializers; ++I) {
4098 if (Initializers[I]->isBaseInitializer())
4099 InitializedBases.insert(
4100 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4101 else
Francois Pichetd583da02010-12-04 09:14:42 +00004102 InitializedFields.insert(cast<FieldDecl>(
4103 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004104 }
4105
4106 // Add completions for base classes.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004107 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor99129ef2010-08-29 19:27:27 +00004108 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004109 CXXRecordDecl *ClassDecl = Constructor->getParent();
4110 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4111 BaseEnd = ClassDecl->bases_end();
4112 Base != BaseEnd; ++Base) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004113 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4114 SawLastInitializer
4115 = NumInitializers > 0 &&
4116 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4117 Context.hasSameUnqualifiedType(Base->getType(),
4118 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004119 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004120 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004121
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004122 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004123 Results.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00004124 Base->getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004125 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4126 Builder.AddPlaceholderChunk("args");
4127 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4128 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004129 SawLastInitializer? CCP_NextInitializer
4130 : CCP_MemberDeclaration));
4131 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004132 }
4133
4134 // Add completions for virtual base classes.
4135 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4136 BaseEnd = ClassDecl->vbases_end();
4137 Base != BaseEnd; ++Base) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004138 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4139 SawLastInitializer
4140 = NumInitializers > 0 &&
4141 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4142 Context.hasSameUnqualifiedType(Base->getType(),
4143 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004144 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004145 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004146
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004147 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004148 Builder.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00004149 Base->getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004150 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4151 Builder.AddPlaceholderChunk("args");
4152 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4153 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004154 SawLastInitializer? CCP_NextInitializer
4155 : CCP_MemberDeclaration));
4156 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004157 }
4158
4159 // Add completions for members.
4160 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4161 FieldEnd = ClassDecl->field_end();
4162 Field != FieldEnd; ++Field) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004163 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4164 SawLastInitializer
4165 = NumInitializers > 0 &&
Francois Pichetd583da02010-12-04 09:14:42 +00004166 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4167 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004168 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004169 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004170
4171 if (!Field->getDeclName())
4172 continue;
4173
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004174 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004175 Field->getIdentifier()->getName()));
4176 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4177 Builder.AddPlaceholderChunk("args");
4178 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4179 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004180 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00004181 : CCP_MemberDeclaration,
Douglas Gregor78254c82012-03-27 23:34:16 +00004182 CXCursor_MemberRef,
4183 CXAvailability_Available,
4184 *Field));
Douglas Gregor99129ef2010-08-29 19:27:27 +00004185 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004186 }
4187 Results.ExitScope();
4188
Douglas Gregor0ac41382010-09-23 23:01:17 +00004189 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004190 Results.data(), Results.size());
4191}
4192
Douglas Gregord8c61782012-02-15 15:34:24 +00004193/// \brief Determine whether this scope denotes a namespace.
4194static bool isNamespaceScope(Scope *S) {
4195 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4196 if (!DC)
4197 return false;
4198
4199 return DC->isFileContext();
4200}
4201
4202void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4203 bool AfterAmpersand) {
4204 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4205 CodeCompletionContext::CCC_Other);
4206 Results.EnterNewScope();
4207
4208 // Note what has already been captured.
4209 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4210 bool IncludedThis = false;
4211 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4212 CEnd = Intro.Captures.end();
4213 C != CEnd; ++C) {
4214 if (C->Kind == LCK_This) {
4215 IncludedThis = true;
4216 continue;
4217 }
4218
4219 Known.insert(C->Id);
4220 }
4221
4222 // Look for other capturable variables.
4223 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4224 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4225 D != DEnd; ++D) {
4226 VarDecl *Var = dyn_cast<VarDecl>(*D);
4227 if (!Var ||
4228 !Var->hasLocalStorage() ||
4229 Var->hasAttr<BlocksAttr>())
4230 continue;
4231
4232 if (Known.insert(Var->getIdentifier()))
4233 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4234 }
4235 }
4236
4237 // Add 'this', if it would be valid.
4238 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4239 addThisCompletion(*this, Results);
4240
4241 Results.ExitScope();
4242
4243 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4244 Results.data(), Results.size());
4245}
4246
Douglas Gregorf1934162010-01-13 21:24:21 +00004247// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4248// true or false.
4249#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004250static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004251 ResultBuilder &Results,
4252 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004253 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004254 // Since we have an implementation, we can end it.
Douglas Gregor78a21012010-01-14 16:01:26 +00004255 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004256
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004257 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf1934162010-01-13 21:24:21 +00004258 if (LangOpts.ObjC2) {
4259 // @dynamic
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004260 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4261 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4262 Builder.AddPlaceholderChunk("property");
4263 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004264
4265 // @synthesize
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004266 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4267 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4268 Builder.AddPlaceholderChunk("property");
4269 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004270 }
4271}
4272
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004273static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004274 ResultBuilder &Results,
4275 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004276 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004277
4278 // Since we have an interface or protocol, we can end it.
Douglas Gregor78a21012010-01-14 16:01:26 +00004279 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004280
4281 if (LangOpts.ObjC2) {
4282 // @property
Douglas Gregor78a21012010-01-14 16:01:26 +00004283 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004284
4285 // @required
Douglas Gregor78a21012010-01-14 16:01:26 +00004286 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004287
4288 // @optional
Douglas Gregor78a21012010-01-14 16:01:26 +00004289 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004290 }
4291}
4292
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004293static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004294 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004295 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf1934162010-01-13 21:24:21 +00004296
4297 // @class name ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004298 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4299 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4300 Builder.AddPlaceholderChunk("name");
4301 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004302
Douglas Gregorf4c33342010-05-28 00:22:41 +00004303 if (Results.includeCodePatterns()) {
4304 // @interface name
4305 // FIXME: Could introduce the whole pattern, including superclasses and
4306 // such.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004307 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4308 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4309 Builder.AddPlaceholderChunk("class");
4310 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004311
Douglas Gregorf4c33342010-05-28 00:22:41 +00004312 // @protocol name
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004313 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4314 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4315 Builder.AddPlaceholderChunk("protocol");
4316 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004317
4318 // @implementation name
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004319 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4320 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4321 Builder.AddPlaceholderChunk("class");
4322 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004323 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004324
4325 // @compatibility_alias name
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004326 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4327 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4328 Builder.AddPlaceholderChunk("alias");
4329 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4330 Builder.AddPlaceholderChunk("class");
4331 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004332}
4333
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004334void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00004335 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004336 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4337 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00004338 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004339 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00004340 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004341 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00004342 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00004343 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004344 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00004345 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004346 HandleCodeCompleteResults(this, CodeCompleter,
4347 CodeCompletionContext::CCC_Other,
4348 Results.data(),Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00004349}
4350
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004351static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004352 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004353 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004354
4355 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004356 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00004357 if (Results.getSema().getLangOpts().CPlusPlus ||
4358 Results.getSema().getLangOpts().ConstStrings)
Douglas Gregore5c79d52011-10-18 21:20:17 +00004359 EncodeType = " const char[]";
4360 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004361 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4362 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4363 Builder.AddPlaceholderChunk("type-name");
4364 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4365 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004366
4367 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004368 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004369 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4370 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4371 Builder.AddPlaceholderChunk("protocol-name");
4372 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4373 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004374
4375 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004376 Builder.AddResultTypeChunk("SEL");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004377 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4378 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4379 Builder.AddPlaceholderChunk("selector");
4380 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4381 Results.AddResult(Result(Builder.TakeString()));
Ted Kremeneke65b0862012-03-06 20:05:56 +00004382
4383 // @[ objects, ... ]
4384 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[));
4385 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4386 Builder.AddPlaceholderChunk("objects, ...");
4387 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4388 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4389 Results.AddResult(Result(Builder.TakeString()));
4390
4391 // @{ key : object, ... }
4392 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{));
4393 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4394 Builder.AddPlaceholderChunk("key");
4395 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4396 Builder.AddChunk(CodeCompletionString::CK_Colon);
4397 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4398 Builder.AddPlaceholderChunk("object, ...");
4399 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4400 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4401 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004402}
4403
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004404static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004405 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004406 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf1934162010-01-13 21:24:21 +00004407
Douglas Gregorf4c33342010-05-28 00:22:41 +00004408 if (Results.includeCodePatterns()) {
4409 // @try { statements } @catch ( declaration ) { statements } @finally
4410 // { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004411 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4412 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4413 Builder.AddPlaceholderChunk("statements");
4414 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4415 Builder.AddTextChunk("@catch");
4416 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4417 Builder.AddPlaceholderChunk("parameter");
4418 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4419 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4420 Builder.AddPlaceholderChunk("statements");
4421 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4422 Builder.AddTextChunk("@finally");
4423 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4424 Builder.AddPlaceholderChunk("statements");
4425 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4426 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004427 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004428
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004429 // @throw
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004430 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4431 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4432 Builder.AddPlaceholderChunk("expression");
4433 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004434
Douglas Gregorf4c33342010-05-28 00:22:41 +00004435 if (Results.includeCodePatterns()) {
4436 // @synchronized ( expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004437 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4438 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4439 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4440 Builder.AddPlaceholderChunk("expression");
4441 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4442 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4443 Builder.AddPlaceholderChunk("statements");
4444 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4445 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004446 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004447}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004448
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004449static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00004450 ResultBuilder &Results,
4451 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004452 typedef CodeCompletionResult Result;
Douglas Gregor78a21012010-01-14 16:01:26 +00004453 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4454 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4455 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregor48d46252010-01-13 21:54:15 +00004456 if (LangOpts.ObjC2)
Douglas Gregor78a21012010-01-14 16:01:26 +00004457 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregor48d46252010-01-13 21:54:15 +00004458}
4459
4460void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004461 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4462 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00004463 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00004464 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00004465 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004466 HandleCodeCompleteResults(this, CodeCompleter,
4467 CodeCompletionContext::CCC_Other,
4468 Results.data(),Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00004469}
4470
4471void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004472 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4473 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00004474 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004475 AddObjCStatementResults(Results, false);
4476 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004477 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004478 HandleCodeCompleteResults(this, CodeCompleter,
4479 CodeCompletionContext::CCC_Other,
4480 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004481}
4482
4483void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004484 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4485 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004486 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004487 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004488 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004489 HandleCodeCompleteResults(this, CodeCompleter,
4490 CodeCompletionContext::CCC_Other,
4491 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004492}
4493
Douglas Gregore6078da2009-11-19 00:14:45 +00004494/// \brief Determine whether the addition of the given flag to an Objective-C
4495/// property's attributes will cause a conflict.
4496static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4497 // Check if we've already added this flag.
4498 if (Attributes & NewFlag)
4499 return true;
4500
4501 Attributes |= NewFlag;
4502
4503 // Check for collisions with "readonly".
4504 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4505 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4506 ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00004507 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00004508 ObjCDeclSpec::DQ_PR_copy |
John McCall31168b02011-06-15 23:02:42 +00004509 ObjCDeclSpec::DQ_PR_retain |
4510 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregore6078da2009-11-19 00:14:45 +00004511 return true;
4512
John McCall31168b02011-06-15 23:02:42 +00004513 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregore6078da2009-11-19 00:14:45 +00004514 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00004515 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00004516 ObjCDeclSpec::DQ_PR_copy |
John McCall31168b02011-06-15 23:02:42 +00004517 ObjCDeclSpec::DQ_PR_retain|
4518 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregore6078da2009-11-19 00:14:45 +00004519 if (AssignCopyRetMask &&
4520 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00004521 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00004522 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00004523 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4524 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregore6078da2009-11-19 00:14:45 +00004525 return true;
4526
4527 return false;
4528}
4529
Douglas Gregor36029f42009-11-18 23:08:07 +00004530void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00004531 if (!CodeCompleter)
4532 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00004533
Steve Naroff936354c2009-10-08 21:55:05 +00004534 unsigned Attributes = ODS.getPropertyAttributes();
4535
John McCall276321a2010-08-25 06:19:51 +00004536 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004537 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4538 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00004539 Results.EnterNewScope();
Douglas Gregore6078da2009-11-19 00:14:45 +00004540 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00004541 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004542 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00004543 Results.AddResult(CodeCompletionResult("assign"));
John McCall31168b02011-06-15 23:02:42 +00004544 if (!ObjCPropertyFlagConflicts(Attributes,
4545 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4546 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004547 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00004548 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004549 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00004550 Results.AddResult(CodeCompletionResult("retain"));
John McCall31168b02011-06-15 23:02:42 +00004551 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4552 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004553 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00004554 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004555 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00004556 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00004557 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4558 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004559 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004560 CodeCompletionBuilder Setter(Results.getAllocator());
4561 Setter.AddTypedTextChunk("setter");
4562 Setter.AddTextChunk(" = ");
4563 Setter.AddPlaceholderChunk("method");
4564 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00004565 }
Douglas Gregore6078da2009-11-19 00:14:45 +00004566 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004567 CodeCompletionBuilder Getter(Results.getAllocator());
4568 Getter.AddTypedTextChunk("getter");
4569 Getter.AddTextChunk(" = ");
4570 Getter.AddPlaceholderChunk("method");
4571 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00004572 }
Steve Naroff936354c2009-10-08 21:55:05 +00004573 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004574 HandleCodeCompleteResults(this, CodeCompleter,
4575 CodeCompletionContext::CCC_Other,
4576 Results.data(),Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00004577}
Steve Naroffeae65032009-11-07 02:08:14 +00004578
Douglas Gregorc8537c52009-11-19 07:41:15 +00004579/// \brief Descripts the kind of Objective-C method that we want to find
4580/// via code completion.
4581enum ObjCMethodKind {
4582 MK_Any, //< Any kind of method, provided it means other specified criteria.
4583 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4584 MK_OneArgSelector //< One-argument selector.
4585};
4586
Douglas Gregor67c692c2010-08-26 15:07:07 +00004587static bool isAcceptableObjCSelector(Selector Sel,
4588 ObjCMethodKind WantKind,
4589 IdentifierInfo **SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004590 unsigned NumSelIdents,
4591 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00004592 if (NumSelIdents > Sel.getNumArgs())
4593 return false;
4594
4595 switch (WantKind) {
4596 case MK_Any: break;
4597 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4598 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4599 }
4600
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004601 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4602 return false;
4603
Douglas Gregor67c692c2010-08-26 15:07:07 +00004604 for (unsigned I = 0; I != NumSelIdents; ++I)
4605 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4606 return false;
4607
4608 return true;
4609}
4610
Douglas Gregorc8537c52009-11-19 07:41:15 +00004611static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4612 ObjCMethodKind WantKind,
4613 IdentifierInfo **SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004614 unsigned NumSelIdents,
4615 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00004616 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004617 NumSelIdents, AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004618}
Douglas Gregor1154e272010-09-16 16:06:31 +00004619
4620namespace {
4621 /// \brief A set of selectors, which is used to avoid introducing multiple
4622 /// completions with the same selector into the result set.
4623 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4624}
4625
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004626/// \brief Add all of the Objective-C methods in the given Objective-C
4627/// container to the set of results.
4628///
4629/// The container will be a class, protocol, category, or implementation of
4630/// any of the above. This mether will recurse to include methods from
4631/// the superclasses of classes along with their categories, protocols, and
4632/// implementations.
4633///
4634/// \param Container the container in which we'll look to find methods.
4635///
4636/// \param WantInstance whether to add instance methods (only); if false, this
4637/// routine will add factory methods (only).
4638///
4639/// \param CurContext the context in which we're performing the lookup that
4640/// finds methods.
4641///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004642/// \param AllowSameLength Whether we allow a method to be added to the list
4643/// when it has the same number of parameters as we have selector identifiers.
4644///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004645/// \param Results the structure into which we'll add results.
4646static void AddObjCMethods(ObjCContainerDecl *Container,
4647 bool WantInstanceMethods,
Douglas Gregorc8537c52009-11-19 07:41:15 +00004648 ObjCMethodKind WantKind,
Douglas Gregor1b605f72009-11-19 01:08:35 +00004649 IdentifierInfo **SelIdents,
4650 unsigned NumSelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004651 DeclContext *CurContext,
Douglas Gregor1154e272010-09-16 16:06:31 +00004652 VisitedSelectorSet &Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004653 bool AllowSameLength,
Douglas Gregor416b5752010-08-25 01:08:01 +00004654 ResultBuilder &Results,
4655 bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004656 typedef CodeCompletionResult Result;
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004657 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4658 MEnd = Container->meth_end();
4659 M != MEnd; ++M) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00004660 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4661 // Check whether the selector identifiers we've been given are a
4662 // subset of the identifiers for this particular method.
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004663 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4664 AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00004665 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004666
Douglas Gregor1154e272010-09-16 16:06:31 +00004667 if (!Selectors.insert((*M)->getSelector()))
4668 continue;
4669
Douglas Gregor1b605f72009-11-19 01:08:35 +00004670 Result R = Result(*M, 0);
4671 R.StartParameter = NumSelIdents;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004672 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00004673 if (!InOriginalClass)
4674 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00004675 Results.MaybeAddResult(R, CurContext);
4676 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004677 }
4678
Douglas Gregorf37c9492010-09-16 15:34:59 +00004679 // Visit the protocols of protocols.
4680 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00004681 if (Protocol->hasDefinition()) {
4682 const ObjCList<ObjCProtocolDecl> &Protocols
4683 = Protocol->getReferencedProtocols();
4684 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4685 E = Protocols.end();
4686 I != E; ++I)
4687 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4688 NumSelIdents, CurContext, Selectors, AllowSameLength,
4689 Results, false);
4690 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00004691 }
4692
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004693 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00004694 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004695 return;
4696
4697 // Add methods in protocols.
Argyrios Kyrtzidise7f3ef32012-03-13 01:09:41 +00004698 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4699 E = IFace->protocol_end();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004700 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00004701 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004702 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004703
4704 // Add methods in categories.
4705 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4706 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00004707 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004708 NumSelIdents, CurContext, Selectors, AllowSameLength,
4709 Results, InOriginalClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004710
4711 // Add a categories protocol methods.
4712 const ObjCList<ObjCProtocolDecl> &Protocols
4713 = CatDecl->getReferencedProtocols();
4714 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4715 E = Protocols.end();
4716 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00004717 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004718 NumSelIdents, CurContext, Selectors, AllowSameLength,
4719 Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004720
4721 // Add methods in category implementations.
4722 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004723 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004724 NumSelIdents, CurContext, Selectors, AllowSameLength,
4725 Results, InOriginalClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004726 }
4727
4728 // Add methods in superclass.
4729 if (IFace->getSuperClass())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004730 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004731 SelIdents, NumSelIdents, CurContext, Selectors,
4732 AllowSameLength, Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004733
4734 // Add methods in our implementation, if any.
4735 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004736 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004737 NumSelIdents, CurContext, Selectors, AllowSameLength,
4738 Results, InOriginalClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004739}
4740
4741
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004742void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00004743 typedef CodeCompletionResult Result;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004744
4745 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004746 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004747 if (!Class) {
4748 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004749 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00004750 Class = Category->getClassInterface();
4751
4752 if (!Class)
4753 return;
4754 }
4755
4756 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004757 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4758 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004759 Results.EnterNewScope();
4760
Douglas Gregor1154e272010-09-16 16:06:31 +00004761 VisitedSelectorSet Selectors;
4762 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004763 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004764 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004765 HandleCodeCompleteResults(this, CodeCompleter,
4766 CodeCompletionContext::CCC_Other,
4767 Results.data(),Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00004768}
4769
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004770void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00004771 typedef CodeCompletionResult Result;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004772
4773 // Try to find the interface where setters might live.
4774 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004775 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004776 if (!Class) {
4777 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004778 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00004779 Class = Category->getClassInterface();
4780
4781 if (!Class)
4782 return;
4783 }
4784
4785 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004786 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4787 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004788 Results.EnterNewScope();
4789
Douglas Gregor1154e272010-09-16 16:06:31 +00004790 VisitedSelectorSet Selectors;
4791 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004792 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004793
4794 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004795 HandleCodeCompleteResults(this, CodeCompleter,
4796 CodeCompletionContext::CCC_Other,
4797 Results.data(),Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004798}
4799
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004800void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4801 bool IsParameter) {
John McCall276321a2010-08-25 06:19:51 +00004802 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004803 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4804 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00004805 Results.EnterNewScope();
4806
4807 // Add context-sensitive, Objective-C parameter-passing keywords.
4808 bool AddedInOut = false;
4809 if ((DS.getObjCDeclQualifier() &
4810 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4811 Results.AddResult("in");
4812 Results.AddResult("inout");
4813 AddedInOut = true;
4814 }
4815 if ((DS.getObjCDeclQualifier() &
4816 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4817 Results.AddResult("out");
4818 if (!AddedInOut)
4819 Results.AddResult("inout");
4820 }
4821 if ((DS.getObjCDeclQualifier() &
4822 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4823 ObjCDeclSpec::DQ_Oneway)) == 0) {
4824 Results.AddResult("bycopy");
4825 Results.AddResult("byref");
4826 Results.AddResult("oneway");
4827 }
4828
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004829 // If we're completing the return type of an Objective-C method and the
4830 // identifier IBAction refers to a macro, provide a completion item for
4831 // an action, e.g.,
4832 // IBAction)<#selector#>:(id)sender
4833 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4834 Context.Idents.get("IBAction").hasMacroDefinition()) {
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004835 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4836 CXAvailability_Available);
4837 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00004838 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004839 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00004840 Builder.AddChunk(CodeCompletionString::CK_Colon);
4841 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004842 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00004843 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004844 Builder.AddTextChunk("sender");
4845 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4846 }
4847
Douglas Gregor99fa2642010-08-24 01:06:58 +00004848 // Add various builtin type names and specifiers.
4849 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4850 Results.ExitScope();
4851
4852 // Add the various type names
4853 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4854 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4855 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4856 CodeCompleter->includeGlobals());
4857
4858 if (CodeCompleter->includeMacros())
4859 AddMacroResults(PP, Results);
4860
4861 HandleCodeCompleteResults(this, CodeCompleter,
4862 CodeCompletionContext::CCC_Type,
4863 Results.data(), Results.size());
4864}
4865
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004866/// \brief When we have an expression with type "id", we may assume
4867/// that it has some more-specific class type based on knowledge of
4868/// common uses of Objective-C. This routine returns that class type,
4869/// or NULL if no better result could be determined.
4870static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00004871 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004872 if (!Msg)
4873 return 0;
4874
4875 Selector Sel = Msg->getSelector();
4876 if (Sel.isNull())
4877 return 0;
4878
4879 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4880 if (!Id)
4881 return 0;
4882
4883 ObjCMethodDecl *Method = Msg->getMethodDecl();
4884 if (!Method)
4885 return 0;
4886
4887 // Determine the class that we're sending the message to.
Douglas Gregor9a129192010-04-21 00:45:42 +00004888 ObjCInterfaceDecl *IFace = 0;
4889 switch (Msg->getReceiverKind()) {
4890 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00004891 if (const ObjCObjectType *ObjType
4892 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4893 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00004894 break;
4895
4896 case ObjCMessageExpr::Instance: {
4897 QualType T = Msg->getInstanceReceiver()->getType();
4898 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4899 IFace = Ptr->getInterfaceDecl();
4900 break;
4901 }
4902
4903 case ObjCMessageExpr::SuperInstance:
4904 case ObjCMessageExpr::SuperClass:
4905 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004906 }
4907
4908 if (!IFace)
4909 return 0;
4910
4911 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4912 if (Method->isInstanceMethod())
4913 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4914 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00004915 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004916 .Case("autorelease", IFace)
4917 .Case("copy", IFace)
4918 .Case("copyWithZone", IFace)
4919 .Case("mutableCopy", IFace)
4920 .Case("mutableCopyWithZone", IFace)
4921 .Case("awakeFromCoder", IFace)
4922 .Case("replacementObjectFromCoder", IFace)
4923 .Case("class", IFace)
4924 .Case("classForCoder", IFace)
4925 .Case("superclass", Super)
4926 .Default(0);
4927
4928 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4929 .Case("new", IFace)
4930 .Case("alloc", IFace)
4931 .Case("allocWithZone", IFace)
4932 .Case("class", IFace)
4933 .Case("superclass", Super)
4934 .Default(0);
4935}
4936
Douglas Gregor6fc04132010-08-27 15:10:57 +00004937// Add a special completion for a message send to "super", which fills in the
4938// most likely case of forwarding all of our arguments to the superclass
4939// function.
4940///
4941/// \param S The semantic analysis object.
4942///
4943/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4944/// the "super" keyword. Otherwise, we just need to provide the arguments.
4945///
4946/// \param SelIdents The identifiers in the selector that have already been
4947/// provided as arguments for a send to "super".
4948///
4949/// \param NumSelIdents The number of identifiers in \p SelIdents.
4950///
4951/// \param Results The set of results to augment.
4952///
4953/// \returns the Objective-C method declaration that would be invoked by
4954/// this "super" completion. If NULL, no completion was added.
4955static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4956 IdentifierInfo **SelIdents,
4957 unsigned NumSelIdents,
4958 ResultBuilder &Results) {
4959 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4960 if (!CurMethod)
4961 return 0;
4962
4963 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4964 if (!Class)
4965 return 0;
4966
4967 // Try to find a superclass method with the same selector.
4968 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00004969 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4970 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00004971 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4972 CurMethod->isInstanceMethod());
4973
Douglas Gregorb5f1e462011-02-16 00:51:18 +00004974 // Check in categories or class extensions.
4975 if (!SuperMethod) {
4976 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4977 Category = Category->getNextClassCategory())
4978 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4979 CurMethod->isInstanceMethod())))
4980 break;
4981 }
4982 }
4983
Douglas Gregor6fc04132010-08-27 15:10:57 +00004984 if (!SuperMethod)
4985 return 0;
4986
4987 // Check whether the superclass method has the same signature.
4988 if (CurMethod->param_size() != SuperMethod->param_size() ||
4989 CurMethod->isVariadic() != SuperMethod->isVariadic())
4990 return 0;
4991
4992 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4993 CurPEnd = CurMethod->param_end(),
4994 SuperP = SuperMethod->param_begin();
4995 CurP != CurPEnd; ++CurP, ++SuperP) {
4996 // Make sure the parameter types are compatible.
4997 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4998 (*SuperP)->getType()))
4999 return 0;
5000
5001 // Make sure we have a parameter name to forward!
5002 if (!(*CurP)->getIdentifier())
5003 return 0;
5004 }
5005
5006 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005007 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005008
5009 // Give this completion a return type.
Douglas Gregor75acd922011-09-27 23:30:47 +00005010 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5011 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005012
5013 // If we need the "super" keyword, add it (plus some spacing).
5014 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005015 Builder.AddTypedTextChunk("super");
5016 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005017 }
5018
5019 Selector Sel = CurMethod->getSelector();
5020 if (Sel.isUnarySelector()) {
5021 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005022 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005023 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005024 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005025 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005026 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005027 } else {
5028 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5029 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5030 if (I > NumSelIdents)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005031 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005032
5033 if (I < NumSelIdents)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005034 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005035 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005036 Sel.getNameForSlot(I) + ":"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005037 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005038 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005039 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005040 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005041 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005042 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005043 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005044 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005045 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005046 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005047 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005048 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005049 }
5050 }
5051 }
5052
Douglas Gregor78254c82012-03-27 23:34:16 +00005053 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5054 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005055 return SuperMethod;
5056}
5057
Douglas Gregora817a192010-05-27 23:06:34 +00005058void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005059 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005060 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5061 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikiebbafb8a2012-03-11 07:00:24 +00005062 getLangOpts().CPlusPlus0x
Douglas Gregord8c61782012-02-15 15:34:24 +00005063 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5064 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005065
Douglas Gregora817a192010-05-27 23:06:34 +00005066 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5067 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005068 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5069 CodeCompleter->includeGlobals());
Douglas Gregora817a192010-05-27 23:06:34 +00005070
5071 // If we are in an Objective-C method inside a class that has a superclass,
5072 // add "super" as an option.
5073 if (ObjCMethodDecl *Method = getCurMethodDecl())
5074 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005075 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005076 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005077
5078 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5079 }
Douglas Gregora817a192010-05-27 23:06:34 +00005080
David Blaikiebbafb8a2012-03-11 07:00:24 +00005081 if (getLangOpts().CPlusPlus0x)
Douglas Gregord8c61782012-02-15 15:34:24 +00005082 addThisCompletion(*this, Results);
5083
Douglas Gregora817a192010-05-27 23:06:34 +00005084 Results.ExitScope();
5085
5086 if (CodeCompleter->includeMacros())
5087 AddMacroResults(PP, Results);
Douglas Gregor50832e02010-09-20 22:39:41 +00005088 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005089 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005090
5091}
5092
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005093void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5094 IdentifierInfo **SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005095 unsigned NumSelIdents,
5096 bool AtArgumentExpression) {
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005097 ObjCInterfaceDecl *CDecl = 0;
5098 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5099 // Figure out which interface we're in.
5100 CDecl = CurMethod->getClassInterface();
5101 if (!CDecl)
5102 return;
5103
5104 // Find the superclass of this class.
5105 CDecl = CDecl->getSuperClass();
5106 if (!CDecl)
5107 return;
5108
5109 if (CurMethod->isInstanceMethod()) {
5110 // We are inside an instance method, which means that the message
5111 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005112 // current object.
5113 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor6fc04132010-08-27 15:10:57 +00005114 SelIdents, NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005115 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005116 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005117 }
5118
5119 // Fall through to send to the superclass in CDecl.
5120 } else {
5121 // "super" may be the name of a type or variable. Figure out which
5122 // it is.
5123 IdentifierInfo *Super = &Context.Idents.get("super");
5124 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5125 LookupOrdinaryName);
5126 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5127 // "super" names an interface. Use it.
5128 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005129 if (const ObjCObjectType *Iface
5130 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5131 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005132 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5133 // "super" names an unresolved type; we can't be more specific.
5134 } else {
5135 // Assume that "super" names some kind of value and parse that way.
5136 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005137 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005138 UnqualifiedId id;
5139 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005140 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5141 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005142 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005143 SelIdents, NumSelIdents,
5144 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005145 }
5146
5147 // Fall through
5148 }
5149
John McCallba7bf592010-08-24 05:47:05 +00005150 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005151 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00005152 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005153 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005154 NumSelIdents, AtArgumentExpression,
5155 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005156}
5157
Douglas Gregor74661272010-09-21 00:03:25 +00005158/// \brief Given a set of code-completion results for the argument of a message
5159/// send, determine the preferred type (if any) for that argument expression.
5160static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5161 unsigned NumSelIdents) {
5162 typedef CodeCompletionResult Result;
5163 ASTContext &Context = Results.getSema().Context;
5164
5165 QualType PreferredType;
5166 unsigned BestPriority = CCP_Unlikely * 2;
5167 Result *ResultsData = Results.data();
5168 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5169 Result &R = ResultsData[I];
5170 if (R.Kind == Result::RK_Declaration &&
5171 isa<ObjCMethodDecl>(R.Declaration)) {
5172 if (R.Priority <= BestPriority) {
5173 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5174 if (NumSelIdents <= Method->param_size()) {
5175 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5176 ->getType();
5177 if (R.Priority < BestPriority || PreferredType.isNull()) {
5178 BestPriority = R.Priority;
5179 PreferredType = MyPreferredType;
5180 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5181 MyPreferredType)) {
5182 PreferredType = QualType();
5183 }
5184 }
5185 }
5186 }
5187 }
5188
5189 return PreferredType;
5190}
5191
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005192static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5193 ParsedType Receiver,
5194 IdentifierInfo **SelIdents,
5195 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005196 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005197 bool IsSuper,
5198 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005199 typedef CodeCompletionResult Result;
Douglas Gregor8ce33212009-11-17 17:59:40 +00005200 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005201
Douglas Gregor8ce33212009-11-17 17:59:40 +00005202 // If the given name refers to an interface type, retrieve the
5203 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005204 if (Receiver) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005205 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005206 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00005207 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5208 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00005209 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005210
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005211 // Add all of the factory methods in this Objective-C class, its protocols,
5212 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00005213 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005214
Douglas Gregor6fc04132010-08-27 15:10:57 +00005215 // If this is a send-to-super, try to add the special "super" send
5216 // completion.
5217 if (IsSuper) {
5218 if (ObjCMethodDecl *SuperMethod
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005219 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5220 Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00005221 Results.Ignore(SuperMethod);
5222 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005223
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005224 // If we're inside an Objective-C method definition, prefer its selector to
5225 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005226 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005227 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005228
Douglas Gregor1154e272010-09-16 16:06:31 +00005229 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00005230 if (CDecl)
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005231 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005232 SemaRef.CurContext, Selectors, AtArgumentExpression,
5233 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005234 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00005235 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005236
Douglas Gregord720daf2010-04-06 17:30:22 +00005237 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005238 // pool from the AST file.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005239 if (SemaRef.ExternalSource) {
5240 for (uint32_t I = 0,
5241 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00005242 I != N; ++I) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005243 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5244 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005245 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005246
5247 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00005248 }
5249 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005250
5251 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5252 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00005253 M != MEnd; ++M) {
5254 for (ObjCMethodList *MethList = &M->second.second;
5255 MethList && MethList->Method;
Douglas Gregor6285f752010-04-06 16:40:00 +00005256 MethList = MethList->Next) {
5257 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5258 NumSelIdents))
5259 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005260
Douglas Gregor6285f752010-04-06 16:40:00 +00005261 Result R(MethList->Method, 0);
5262 R.StartParameter = NumSelIdents;
5263 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005264 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00005265 }
5266 }
5267 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005268
5269 Results.ExitScope();
5270}
Douglas Gregor6285f752010-04-06 16:40:00 +00005271
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005272void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5273 IdentifierInfo **SelIdents,
5274 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005275 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005276 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00005277
5278 QualType T = this->GetTypeFromParser(Receiver);
5279
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005280 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor63745d52011-07-21 01:05:26 +00005281 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregorea777402011-07-26 15:24:30 +00005282 T, SelIdents, NumSelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00005283
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005284 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5285 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00005286
5287 // If we're actually at the argument expression (rather than prior to the
5288 // selector), we're actually performing code completion for an expression.
5289 // Determine whether we have a single, best method. If so, we can
5290 // code-complete the expression using the corresponding parameter type as
5291 // our preferred type, improving completion results.
5292 if (AtArgumentExpression) {
5293 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregor63745d52011-07-21 01:05:26 +00005294 NumSelIdents);
Douglas Gregor74661272010-09-21 00:03:25 +00005295 if (PreferredType.isNull())
5296 CodeCompleteOrdinaryName(S, PCC_Expression);
5297 else
5298 CodeCompleteExpression(S, PreferredType);
5299 return;
5300 }
5301
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005302 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00005303 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005304 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00005305}
5306
Richard Trieu2bd04012011-09-09 02:00:50 +00005307void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregor1b605f72009-11-19 01:08:35 +00005308 IdentifierInfo **SelIdents,
Douglas Gregor6fc04132010-08-27 15:10:57 +00005309 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005310 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005311 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00005312 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00005313
5314 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00005315
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005316 // If necessary, apply function/array conversion to the receiver.
5317 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00005318 if (RecExpr) {
5319 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5320 if (Conv.isInvalid()) // conversion failed. bail.
5321 return;
5322 RecExpr = Conv.take();
5323 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00005324 QualType ReceiverType = RecExpr? RecExpr->getType()
5325 : Super? Context.getObjCObjectPointerType(
5326 Context.getObjCInterfaceType(Super))
5327 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00005328
Douglas Gregordc520b02010-11-08 21:12:30 +00005329 // If we're messaging an expression with type "id" or "Class", check
5330 // whether we know something special about the receiver that allows
5331 // us to assume a more-specific receiver type.
5332 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5333 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5334 if (ReceiverType->isObjCClassType())
5335 return CodeCompleteObjCClassMessage(S,
5336 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5337 SelIdents, NumSelIdents,
5338 AtArgumentExpression, Super);
5339
5340 ReceiverType = Context.getObjCObjectPointerType(
5341 Context.getObjCInterfaceType(IFace));
5342 }
5343
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005344 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005345 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor63745d52011-07-21 01:05:26 +00005346 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregorea777402011-07-26 15:24:30 +00005347 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00005348
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005349 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005350
Douglas Gregor6fc04132010-08-27 15:10:57 +00005351 // If this is a send-to-super, try to add the special "super" send
5352 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00005353 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005354 if (ObjCMethodDecl *SuperMethod
5355 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5356 Results))
5357 Results.Ignore(SuperMethod);
5358 }
5359
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005360 // If we're inside an Objective-C method definition, prefer its selector to
5361 // others.
5362 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5363 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005364
Douglas Gregor1154e272010-09-16 16:06:31 +00005365 // Keep track of the selectors we've already added.
5366 VisitedSelectorSet Selectors;
5367
Douglas Gregora3329fa2009-11-18 00:06:18 +00005368 // Handle messages to Class. This really isn't a message to an instance
5369 // method, so we treat it the same way we would treat a message send to a
5370 // class method.
5371 if (ReceiverType->isObjCClassType() ||
5372 ReceiverType->isObjCQualifiedClassType()) {
5373 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5374 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregorc8537c52009-11-19 07:41:15 +00005375 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005376 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005377 }
5378 }
5379 // Handle messages to a qualified ID ("id<foo>").
5380 else if (const ObjCObjectPointerType *QualID
5381 = ReceiverType->getAsObjCQualifiedIdType()) {
5382 // Search protocols for instance methods.
5383 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5384 E = QualID->qual_end();
5385 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00005386 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005387 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005388 }
5389 // Handle messages to a pointer to interface type.
5390 else if (const ObjCObjectPointerType *IFacePtr
5391 = ReceiverType->getAsObjCInterfacePointerType()) {
5392 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005393 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005394 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5395 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005396
5397 // Search protocols for instance methods.
5398 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5399 E = IFacePtr->qual_end();
5400 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00005401 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005402 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005403 }
Douglas Gregor6285f752010-04-06 16:40:00 +00005404 // Handle messages to "id".
5405 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00005406 // We're messaging "id", so provide all instance methods we know
5407 // about as code-completion results.
5408
5409 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005410 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00005411 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00005412 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5413 I != N; ++I) {
5414 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00005415 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005416 continue;
5417
Sebastian Redl75d8a322010-08-02 23:18:59 +00005418 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00005419 }
5420 }
5421
Sebastian Redl75d8a322010-08-02 23:18:59 +00005422 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5423 MEnd = MethodPool.end();
5424 M != MEnd; ++M) {
5425 for (ObjCMethodList *MethList = &M->second.first;
5426 MethList && MethList->Method;
Douglas Gregor6285f752010-04-06 16:40:00 +00005427 MethList = MethList->Next) {
5428 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5429 NumSelIdents))
5430 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00005431
5432 if (!Selectors.insert(MethList->Method->getSelector()))
5433 continue;
5434
Douglas Gregor6285f752010-04-06 16:40:00 +00005435 Result R(MethList->Method, 0);
5436 R.StartParameter = NumSelIdents;
5437 R.AllParametersAreInformative = false;
5438 Results.MaybeAddResult(R, CurContext);
5439 }
5440 }
5441 }
Steve Naroffeae65032009-11-07 02:08:14 +00005442 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00005443
5444
5445 // If we're actually at the argument expression (rather than prior to the
5446 // selector), we're actually performing code completion for an expression.
5447 // Determine whether we have a single, best method. If so, we can
5448 // code-complete the expression using the corresponding parameter type as
5449 // our preferred type, improving completion results.
5450 if (AtArgumentExpression) {
5451 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5452 NumSelIdents);
5453 if (PreferredType.isNull())
5454 CodeCompleteOrdinaryName(S, PCC_Expression);
5455 else
5456 CodeCompleteExpression(S, PreferredType);
5457 return;
5458 }
5459
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005460 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00005461 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005462 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00005463}
Douglas Gregorbaf69612009-11-18 04:19:12 +00005464
Douglas Gregor68762e72010-08-23 21:17:50 +00005465void Sema::CodeCompleteObjCForCollection(Scope *S,
5466 DeclGroupPtrTy IterationVar) {
5467 CodeCompleteExpressionData Data;
5468 Data.ObjCCollection = true;
5469
5470 if (IterationVar.getAsOpaquePtr()) {
5471 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5472 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5473 if (*I)
5474 Data.IgnoreDecls.push_back(*I);
5475 }
5476 }
5477
5478 CodeCompleteExpression(S, Data);
5479}
5480
Douglas Gregor67c692c2010-08-26 15:07:07 +00005481void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5482 unsigned NumSelIdents) {
5483 // If we have an external source, load the entire class method
5484 // pool from the AST file.
5485 if (ExternalSource) {
5486 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5487 I != N; ++I) {
5488 Selector Sel = ExternalSource->GetExternalSelector(I);
5489 if (Sel.isNull() || MethodPool.count(Sel))
5490 continue;
5491
5492 ReadMethodPool(Sel);
5493 }
5494 }
5495
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005496 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5497 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00005498 Results.EnterNewScope();
5499 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5500 MEnd = MethodPool.end();
5501 M != MEnd; ++M) {
5502
5503 Selector Sel = M->first;
5504 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5505 continue;
5506
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005507 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005508 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005509 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005510 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005511 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005512 continue;
5513 }
5514
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005515 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005516 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005517 if (I == NumSelIdents) {
5518 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005519 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005520 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005521 Accumulator.clear();
5522 }
5523 }
5524
Benjamin Kramer632500c2011-07-26 16:59:25 +00005525 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005526 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00005527 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005528 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005529 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005530 }
5531 Results.ExitScope();
5532
5533 HandleCodeCompleteResults(this, CodeCompleter,
5534 CodeCompletionContext::CCC_SelectorName,
5535 Results.data(), Results.size());
5536}
5537
Douglas Gregorbaf69612009-11-18 04:19:12 +00005538/// \brief Add all of the protocol declarations that we find in the given
5539/// (translation unit) context.
5540static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005541 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00005542 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005543 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00005544
5545 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5546 DEnd = Ctx->decls_end();
5547 D != DEnd; ++D) {
5548 // Record any protocols we find.
5549 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00005550 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregorfc59ce12010-01-14 16:14:35 +00005551 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005552 }
5553}
5554
5555void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5556 unsigned NumProtocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005557 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5558 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005559
Douglas Gregora3b23b02010-12-09 21:44:02 +00005560 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5561 Results.EnterNewScope();
5562
5563 // Tell the result set to ignore all of the protocols we have
5564 // already seen.
5565 // FIXME: This doesn't work when caching code-completion results.
5566 for (unsigned I = 0; I != NumProtocols; ++I)
5567 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5568 Protocols[I].second))
5569 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005570
Douglas Gregora3b23b02010-12-09 21:44:02 +00005571 // Add all protocols.
5572 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5573 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005574
Douglas Gregora3b23b02010-12-09 21:44:02 +00005575 Results.ExitScope();
5576 }
5577
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005578 HandleCodeCompleteResults(this, CodeCompleter,
5579 CodeCompletionContext::CCC_ObjCProtocolName,
5580 Results.data(),Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005581}
5582
5583void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005584 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5585 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005586
Douglas Gregora3b23b02010-12-09 21:44:02 +00005587 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5588 Results.EnterNewScope();
5589
5590 // Add all protocols.
5591 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5592 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005593
Douglas Gregora3b23b02010-12-09 21:44:02 +00005594 Results.ExitScope();
5595 }
5596
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005597 HandleCodeCompleteResults(this, CodeCompleter,
5598 CodeCompletionContext::CCC_ObjCProtocolName,
5599 Results.data(),Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00005600}
Douglas Gregor49c22a72009-11-18 16:26:39 +00005601
5602/// \brief Add all of the Objective-C interface declarations that we find in
5603/// the given (translation unit) context.
5604static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5605 bool OnlyForwardDeclarations,
5606 bool OnlyUnimplemented,
5607 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005608 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00005609
5610 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5611 DEnd = Ctx->decls_end();
5612 D != DEnd; ++D) {
Douglas Gregor1c283312010-08-11 12:19:30 +00005613 // Record any interfaces we find.
5614 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00005615 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00005616 (!OnlyUnimplemented || !Class->getImplementation()))
5617 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005618 }
5619}
5620
5621void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005622 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5623 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005624 Results.EnterNewScope();
5625
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005626 if (CodeCompleter->includeGlobals()) {
5627 // Add all classes.
5628 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5629 false, Results);
5630 }
5631
Douglas Gregor49c22a72009-11-18 16:26:39 +00005632 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005633
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005634 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005635 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005636 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005637}
5638
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005639void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5640 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005641 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005642 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005643 Results.EnterNewScope();
5644
5645 // Make sure that we ignore the class we're currently defining.
5646 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005647 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005648 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00005649 Results.Ignore(CurClass);
5650
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005651 if (CodeCompleter->includeGlobals()) {
5652 // Add all classes.
5653 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5654 false, Results);
5655 }
5656
Douglas Gregor49c22a72009-11-18 16:26:39 +00005657 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005658
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005659 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005660 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005661 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005662}
5663
5664void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005665 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5666 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005667 Results.EnterNewScope();
5668
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005669 if (CodeCompleter->includeGlobals()) {
5670 // Add all unimplemented classes.
5671 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5672 true, Results);
5673 }
5674
Douglas Gregor49c22a72009-11-18 16:26:39 +00005675 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005676
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005677 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005678 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005679 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005680}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005681
5682void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005683 IdentifierInfo *ClassName,
5684 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00005685 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005686
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005687 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor21325842011-07-07 16:03:39 +00005688 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005689
5690 // Ignore any categories we find that have already been implemented by this
5691 // interface.
5692 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5693 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005694 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005695 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5696 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5697 Category = Category->getNextClassCategory())
5698 CategoryNames.insert(Category->getIdentifier());
5699
5700 // Add all of the categories we know about.
5701 Results.EnterNewScope();
5702 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5703 for (DeclContext::decl_iterator D = TU->decls_begin(),
5704 DEnd = TU->decls_end();
5705 D != DEnd; ++D)
5706 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5707 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregorfc59ce12010-01-14 16:14:35 +00005708 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005709 Results.ExitScope();
5710
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005711 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00005712 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005713 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005714}
5715
5716void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005717 IdentifierInfo *ClassName,
5718 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00005719 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005720
5721 // Find the corresponding interface. If we couldn't find the interface, the
5722 // program itself is ill-formed. However, we'll try to be helpful still by
5723 // providing the list of all of the categories we know about.
5724 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005725 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005726 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5727 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005728 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005729
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005730 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor21325842011-07-07 16:03:39 +00005731 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005732
5733 // Add all of the categories that have have corresponding interface
5734 // declarations in this class and any of its superclasses, except for
5735 // already-implemented categories in the class itself.
5736 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5737 Results.EnterNewScope();
5738 bool IgnoreImplemented = true;
5739 while (Class) {
5740 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5741 Category = Category->getNextClassCategory())
5742 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5743 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregorfc59ce12010-01-14 16:14:35 +00005744 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005745
5746 Class = Class->getSuperClass();
5747 IgnoreImplemented = false;
5748 }
5749 Results.ExitScope();
5750
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005751 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00005752 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005753 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005754}
Douglas Gregor5d649882009-11-18 22:32:06 +00005755
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005756void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005757 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005758 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5759 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00005760
5761 // Figure out where this @synthesize lives.
5762 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005763 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00005764 if (!Container ||
5765 (!isa<ObjCImplementationDecl>(Container) &&
5766 !isa<ObjCCategoryImplDecl>(Container)))
5767 return;
5768
5769 // Ignore any properties that have already been implemented.
5770 for (DeclContext::decl_iterator D = Container->decls_begin(),
5771 DEnd = Container->decls_end();
5772 D != DEnd; ++D)
5773 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5774 Results.Ignore(PropertyImpl->getPropertyDecl());
5775
5776 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00005777 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00005778 Results.EnterNewScope();
5779 if (ObjCImplementationDecl *ClassImpl
5780 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor95147142011-05-05 15:50:42 +00005781 AddObjCProperties(ClassImpl->getClassInterface(), false,
5782 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00005783 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00005784 else
5785 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00005786 false, /*AllowNullaryMethods=*/false, CurContext,
5787 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00005788 Results.ExitScope();
5789
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005790 HandleCodeCompleteResults(this, CodeCompleter,
5791 CodeCompletionContext::CCC_Other,
5792 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00005793}
5794
5795void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005796 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00005797 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005798 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5799 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00005800
5801 // Figure out where this @synthesize lives.
5802 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005803 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00005804 if (!Container ||
5805 (!isa<ObjCImplementationDecl>(Container) &&
5806 !isa<ObjCCategoryImplDecl>(Container)))
5807 return;
5808
5809 // Figure out which interface we're looking into.
5810 ObjCInterfaceDecl *Class = 0;
5811 if (ObjCImplementationDecl *ClassImpl
5812 = dyn_cast<ObjCImplementationDecl>(Container))
5813 Class = ClassImpl->getClassInterface();
5814 else
5815 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5816 ->getClassInterface();
5817
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005818 // Determine the type of the property we're synthesizing.
5819 QualType PropertyType = Context.getObjCIdType();
5820 if (Class) {
5821 if (ObjCPropertyDecl *Property
5822 = Class->FindPropertyDeclaration(PropertyName)) {
5823 PropertyType
5824 = Property->getType().getNonReferenceType().getUnqualifiedType();
5825
5826 // Give preference to ivars
5827 Results.setPreferredType(PropertyType);
5828 }
5829 }
5830
Douglas Gregor5d649882009-11-18 22:32:06 +00005831 // Add all of the instance variables in this class and its superclasses.
5832 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00005833 bool SawSimilarlyNamedIvar = false;
5834 std::string NameWithPrefix;
5835 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00005836 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00005837 std::string NameWithSuffix = PropertyName->getName().str();
5838 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00005839 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00005840 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5841 Ivar = Ivar->getNextIvar()) {
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005842 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5843
Douglas Gregor331faa02011-04-18 14:13:53 +00005844 // Determine whether we've seen an ivar with a name similar to the
5845 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005846 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00005847 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005848 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00005849 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005850
5851 // Reduce the priority of this result by one, to give it a slight
5852 // advantage over other results whose names don't match so closely.
5853 if (Results.size() &&
5854 Results.data()[Results.size() - 1].Kind
5855 == CodeCompletionResult::RK_Declaration &&
5856 Results.data()[Results.size() - 1].Declaration == Ivar)
5857 Results.data()[Results.size() - 1].Priority--;
5858 }
Douglas Gregor331faa02011-04-18 14:13:53 +00005859 }
Douglas Gregor5d649882009-11-18 22:32:06 +00005860 }
Douglas Gregor331faa02011-04-18 14:13:53 +00005861
5862 if (!SawSimilarlyNamedIvar) {
5863 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005864 // an ivar of the appropriate type.
5865 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00005866 typedef CodeCompletionResult Result;
5867 CodeCompletionAllocator &Allocator = Results.getAllocator();
5868 CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
5869
Douglas Gregor75acd922011-09-27 23:30:47 +00005870 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005871 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00005872 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00005873 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5874 Results.AddResult(Result(Builder.TakeString(), Priority,
5875 CXCursor_ObjCIvarDecl));
5876 }
5877
Douglas Gregor5d649882009-11-18 22:32:06 +00005878 Results.ExitScope();
5879
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005880 HandleCodeCompleteResults(this, CodeCompleter,
5881 CodeCompletionContext::CCC_Other,
5882 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00005883}
Douglas Gregor636a61e2010-04-07 00:21:17 +00005884
Douglas Gregor416b5752010-08-25 01:08:01 +00005885// Mapping from selectors to the methods that implement that selector, along
5886// with the "in original class" flag.
5887typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5888 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00005889
5890/// \brief Find all of the methods that reside in the given container
5891/// (and its superclasses, protocols, etc.) that meet the given
5892/// criteria. Insert those methods into the map of known methods,
5893/// indexed by selector so they can be easily found.
5894static void FindImplementableMethods(ASTContext &Context,
5895 ObjCContainerDecl *Container,
5896 bool WantInstanceMethods,
5897 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00005898 KnownMethodsMap &KnownMethods,
5899 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00005900 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5901 // Recurse into protocols.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005902 if (!IFace->hasDefinition())
5903 return;
5904
Douglas Gregor636a61e2010-04-07 00:21:17 +00005905 const ObjCList<ObjCProtocolDecl> &Protocols
5906 = IFace->getReferencedProtocols();
5907 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005908 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00005909 I != E; ++I)
5910 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005911 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00005912
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005913 // Add methods from any class extensions and categories.
5914 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5915 Cat = Cat->getNextClassCategory())
Fariborz Jahanian3bf0ded2010-06-22 23:20:40 +00005916 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5917 WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005918 KnownMethods, false);
5919
5920 // Visit the superclass.
5921 if (IFace->getSuperClass())
5922 FindImplementableMethods(Context, IFace->getSuperClass(),
5923 WantInstanceMethods, ReturnType,
5924 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00005925 }
5926
5927 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5928 // Recurse into protocols.
5929 const ObjCList<ObjCProtocolDecl> &Protocols
5930 = Category->getReferencedProtocols();
5931 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005932 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00005933 I != E; ++I)
5934 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005935 KnownMethods, InOriginalClass);
5936
5937 // If this category is the original class, jump to the interface.
5938 if (InOriginalClass && Category->getClassInterface())
5939 FindImplementableMethods(Context, Category->getClassInterface(),
5940 WantInstanceMethods, ReturnType, KnownMethods,
5941 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00005942 }
5943
5944 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005945 if (Protocol->hasDefinition()) {
5946 // Recurse into protocols.
5947 const ObjCList<ObjCProtocolDecl> &Protocols
5948 = Protocol->getReferencedProtocols();
5949 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5950 E = Protocols.end();
5951 I != E; ++I)
5952 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
5953 KnownMethods, false);
5954 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00005955 }
5956
5957 // Add methods in this container. This operation occurs last because
5958 // we want the methods from this container to override any methods
5959 // we've previously seen with the same selector.
5960 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5961 MEnd = Container->meth_end();
5962 M != MEnd; ++M) {
5963 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5964 if (!ReturnType.isNull() &&
5965 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5966 continue;
5967
Douglas Gregor416b5752010-08-25 01:08:01 +00005968 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00005969 }
5970 }
5971}
5972
Douglas Gregor669a25a2011-02-17 00:22:45 +00005973/// \brief Add the parenthesized return or parameter type chunk to a code
5974/// completion string.
5975static void AddObjCPassingTypeChunk(QualType Type,
5976 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00005977 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00005978 CodeCompletionBuilder &Builder) {
5979 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor75acd922011-09-27 23:30:47 +00005980 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00005981 Builder.getAllocator()));
5982 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5983}
5984
5985/// \brief Determine whether the given class is or inherits from a class by
5986/// the given name.
5987static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005988 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00005989 if (!Class)
5990 return false;
5991
5992 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
5993 return true;
5994
5995 return InheritsFromClassNamed(Class->getSuperClass(), Name);
5996}
5997
5998/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
5999/// Key-Value Observing (KVO).
6000static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6001 bool IsInstanceMethod,
6002 QualType ReturnType,
6003 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006004 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006005 ResultBuilder &Results) {
6006 IdentifierInfo *PropName = Property->getIdentifier();
6007 if (!PropName || PropName->getLength() == 0)
6008 return;
6009
Douglas Gregor75acd922011-09-27 23:30:47 +00006010 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6011
Douglas Gregor669a25a2011-02-17 00:22:45 +00006012 // Builder that will create each code completion.
6013 typedef CodeCompletionResult Result;
6014 CodeCompletionAllocator &Allocator = Results.getAllocator();
6015 CodeCompletionBuilder Builder(Allocator);
6016
6017 // The selector table.
6018 SelectorTable &Selectors = Context.Selectors;
6019
6020 // The property name, copied into the code completion allocation region
6021 // on demand.
6022 struct KeyHolder {
6023 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006024 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006025 const char *CopiedKey;
6026
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006027 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006028 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6029
6030 operator const char *() {
6031 if (CopiedKey)
6032 return CopiedKey;
6033
6034 return CopiedKey = Allocator.CopyString(Key);
6035 }
6036 } Key(Allocator, PropName->getName());
6037
6038 // The uppercased name of the property name.
6039 std::string UpperKey = PropName->getName();
6040 if (!UpperKey.empty())
6041 UpperKey[0] = toupper(UpperKey[0]);
6042
6043 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6044 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6045 Property->getType());
6046 bool ReturnTypeMatchesVoid
6047 = ReturnType.isNull() || ReturnType->isVoidType();
6048
6049 // Add the normal accessor -(type)key.
6050 if (IsInstanceMethod &&
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006051 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006052 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6053 if (ReturnType.isNull())
Douglas Gregor75acd922011-09-27 23:30:47 +00006054 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006055
6056 Builder.AddTypedTextChunk(Key);
6057 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6058 CXCursor_ObjCInstanceMethodDecl));
6059 }
6060
6061 // If we have an integral or boolean property (or the user has provided
6062 // an integral or boolean return type), add the accessor -(type)isKey.
6063 if (IsInstanceMethod &&
6064 ((!ReturnType.isNull() &&
6065 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6066 (ReturnType.isNull() &&
6067 (Property->getType()->isIntegerType() ||
6068 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006069 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006070 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006071 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006072 if (ReturnType.isNull()) {
6073 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6074 Builder.AddTextChunk("BOOL");
6075 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6076 }
6077
6078 Builder.AddTypedTextChunk(
6079 Allocator.CopyString(SelectorId->getName()));
6080 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6081 CXCursor_ObjCInstanceMethodDecl));
6082 }
6083 }
6084
6085 // Add the normal mutator.
6086 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6087 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006088 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006089 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006090 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006091 if (ReturnType.isNull()) {
6092 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6093 Builder.AddTextChunk("void");
6094 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6095 }
6096
6097 Builder.AddTypedTextChunk(
6098 Allocator.CopyString(SelectorId->getName()));
6099 Builder.AddTypedTextChunk(":");
Douglas Gregor75acd922011-09-27 23:30:47 +00006100 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006101 Builder.AddTextChunk(Key);
6102 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6103 CXCursor_ObjCInstanceMethodDecl));
6104 }
6105 }
6106
6107 // Indexed and unordered accessors
6108 unsigned IndexedGetterPriority = CCP_CodePattern;
6109 unsigned IndexedSetterPriority = CCP_CodePattern;
6110 unsigned UnorderedGetterPriority = CCP_CodePattern;
6111 unsigned UnorderedSetterPriority = CCP_CodePattern;
6112 if (const ObjCObjectPointerType *ObjCPointer
6113 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6114 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6115 // If this interface type is not provably derived from a known
6116 // collection, penalize the corresponding completions.
6117 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6118 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6119 if (!InheritsFromClassNamed(IFace, "NSArray"))
6120 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6121 }
6122
6123 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6124 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6125 if (!InheritsFromClassNamed(IFace, "NSSet"))
6126 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6127 }
6128 }
6129 } else {
6130 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6131 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6132 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6133 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6134 }
6135
6136 // Add -(NSUInteger)countOf<key>
6137 if (IsInstanceMethod &&
6138 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006139 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006140 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006141 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006142 if (ReturnType.isNull()) {
6143 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6144 Builder.AddTextChunk("NSUInteger");
6145 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6146 }
6147
6148 Builder.AddTypedTextChunk(
6149 Allocator.CopyString(SelectorId->getName()));
6150 Results.AddResult(Result(Builder.TakeString(),
6151 std::min(IndexedGetterPriority,
6152 UnorderedGetterPriority),
6153 CXCursor_ObjCInstanceMethodDecl));
6154 }
6155 }
6156
6157 // Indexed getters
6158 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6159 if (IsInstanceMethod &&
6160 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006161 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006162 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006163 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006164 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006165 if (ReturnType.isNull()) {
6166 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6167 Builder.AddTextChunk("id");
6168 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6169 }
6170
6171 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6172 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6173 Builder.AddTextChunk("NSUInteger");
6174 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6175 Builder.AddTextChunk("index");
6176 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6177 CXCursor_ObjCInstanceMethodDecl));
6178 }
6179 }
6180
6181 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6182 if (IsInstanceMethod &&
6183 (ReturnType.isNull() ||
6184 (ReturnType->isObjCObjectPointerType() &&
6185 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6186 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6187 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006188 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006189 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006190 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006191 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006192 if (ReturnType.isNull()) {
6193 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6194 Builder.AddTextChunk("NSArray *");
6195 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6196 }
6197
6198 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6199 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6200 Builder.AddTextChunk("NSIndexSet *");
6201 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6202 Builder.AddTextChunk("indexes");
6203 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6204 CXCursor_ObjCInstanceMethodDecl));
6205 }
6206 }
6207
6208 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6209 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006210 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006211 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006212 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006213 &Context.Idents.get("range")
6214 };
6215
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006216 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006217 if (ReturnType.isNull()) {
6218 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6219 Builder.AddTextChunk("void");
6220 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6221 }
6222
6223 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6224 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6225 Builder.AddPlaceholderChunk("object-type");
6226 Builder.AddTextChunk(" **");
6227 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6228 Builder.AddTextChunk("buffer");
6229 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6230 Builder.AddTypedTextChunk("range:");
6231 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6232 Builder.AddTextChunk("NSRange");
6233 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6234 Builder.AddTextChunk("inRange");
6235 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6236 CXCursor_ObjCInstanceMethodDecl));
6237 }
6238 }
6239
6240 // Mutable indexed accessors
6241
6242 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6243 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006244 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006245 IdentifierInfo *SelectorIds[2] = {
6246 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006247 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006248 };
6249
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006250 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006251 if (ReturnType.isNull()) {
6252 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6253 Builder.AddTextChunk("void");
6254 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6255 }
6256
6257 Builder.AddTypedTextChunk("insertObject:");
6258 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6259 Builder.AddPlaceholderChunk("object-type");
6260 Builder.AddTextChunk(" *");
6261 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6262 Builder.AddTextChunk("object");
6263 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6264 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6265 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6266 Builder.AddPlaceholderChunk("NSUInteger");
6267 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6268 Builder.AddTextChunk("index");
6269 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6270 CXCursor_ObjCInstanceMethodDecl));
6271 }
6272 }
6273
6274 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6275 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006276 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006277 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006278 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006279 &Context.Idents.get("atIndexes")
6280 };
6281
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006282 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006283 if (ReturnType.isNull()) {
6284 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6285 Builder.AddTextChunk("void");
6286 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6287 }
6288
6289 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6290 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6291 Builder.AddTextChunk("NSArray *");
6292 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6293 Builder.AddTextChunk("array");
6294 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6295 Builder.AddTypedTextChunk("atIndexes:");
6296 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6297 Builder.AddPlaceholderChunk("NSIndexSet *");
6298 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6299 Builder.AddTextChunk("indexes");
6300 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6301 CXCursor_ObjCInstanceMethodDecl));
6302 }
6303 }
6304
6305 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6306 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006307 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006308 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006309 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006310 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006311 if (ReturnType.isNull()) {
6312 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6313 Builder.AddTextChunk("void");
6314 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6315 }
6316
6317 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6318 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6319 Builder.AddTextChunk("NSUInteger");
6320 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6321 Builder.AddTextChunk("index");
6322 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6323 CXCursor_ObjCInstanceMethodDecl));
6324 }
6325 }
6326
6327 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6328 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006329 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006330 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006331 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006332 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006333 if (ReturnType.isNull()) {
6334 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6335 Builder.AddTextChunk("void");
6336 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6337 }
6338
6339 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6340 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6341 Builder.AddTextChunk("NSIndexSet *");
6342 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6343 Builder.AddTextChunk("indexes");
6344 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6345 CXCursor_ObjCInstanceMethodDecl));
6346 }
6347 }
6348
6349 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6350 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006351 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006352 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006353 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006354 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006355 &Context.Idents.get("withObject")
6356 };
6357
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006358 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006359 if (ReturnType.isNull()) {
6360 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6361 Builder.AddTextChunk("void");
6362 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6363 }
6364
6365 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6366 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6367 Builder.AddPlaceholderChunk("NSUInteger");
6368 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6369 Builder.AddTextChunk("index");
6370 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6371 Builder.AddTypedTextChunk("withObject:");
6372 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6373 Builder.AddTextChunk("id");
6374 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6375 Builder.AddTextChunk("object");
6376 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6377 CXCursor_ObjCInstanceMethodDecl));
6378 }
6379 }
6380
6381 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6382 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006383 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006384 = (Twine("replace") + UpperKey + "AtIndexes").str();
6385 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006386 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006387 &Context.Idents.get(SelectorName1),
6388 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006389 };
6390
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006391 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006392 if (ReturnType.isNull()) {
6393 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6394 Builder.AddTextChunk("void");
6395 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6396 }
6397
6398 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6399 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6400 Builder.AddPlaceholderChunk("NSIndexSet *");
6401 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6402 Builder.AddTextChunk("indexes");
6403 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6404 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6405 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6406 Builder.AddTextChunk("NSArray *");
6407 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6408 Builder.AddTextChunk("array");
6409 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6410 CXCursor_ObjCInstanceMethodDecl));
6411 }
6412 }
6413
6414 // Unordered getters
6415 // - (NSEnumerator *)enumeratorOfKey
6416 if (IsInstanceMethod &&
6417 (ReturnType.isNull() ||
6418 (ReturnType->isObjCObjectPointerType() &&
6419 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6420 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6421 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006422 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006423 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006424 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006425 if (ReturnType.isNull()) {
6426 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6427 Builder.AddTextChunk("NSEnumerator *");
6428 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6429 }
6430
6431 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6432 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6433 CXCursor_ObjCInstanceMethodDecl));
6434 }
6435 }
6436
6437 // - (type *)memberOfKey:(type *)object
6438 if (IsInstanceMethod &&
6439 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006440 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006441 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006442 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006443 if (ReturnType.isNull()) {
6444 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6445 Builder.AddPlaceholderChunk("object-type");
6446 Builder.AddTextChunk(" *");
6447 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6448 }
6449
6450 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6451 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6452 if (ReturnType.isNull()) {
6453 Builder.AddPlaceholderChunk("object-type");
6454 Builder.AddTextChunk(" *");
6455 } else {
6456 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006457 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006458 Builder.getAllocator()));
6459 }
6460 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6461 Builder.AddTextChunk("object");
6462 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6463 CXCursor_ObjCInstanceMethodDecl));
6464 }
6465 }
6466
6467 // Mutable unordered accessors
6468 // - (void)addKeyObject:(type *)object
6469 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006470 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006471 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006472 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006473 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006474 if (ReturnType.isNull()) {
6475 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6476 Builder.AddTextChunk("void");
6477 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6478 }
6479
6480 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6481 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6482 Builder.AddPlaceholderChunk("object-type");
6483 Builder.AddTextChunk(" *");
6484 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6485 Builder.AddTextChunk("object");
6486 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6487 CXCursor_ObjCInstanceMethodDecl));
6488 }
6489 }
6490
6491 // - (void)addKey:(NSSet *)objects
6492 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006493 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006494 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006495 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006496 if (ReturnType.isNull()) {
6497 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6498 Builder.AddTextChunk("void");
6499 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6500 }
6501
6502 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6503 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6504 Builder.AddTextChunk("NSSet *");
6505 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6506 Builder.AddTextChunk("objects");
6507 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6508 CXCursor_ObjCInstanceMethodDecl));
6509 }
6510 }
6511
6512 // - (void)removeKeyObject:(type *)object
6513 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006514 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006515 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006516 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006517 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006518 if (ReturnType.isNull()) {
6519 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6520 Builder.AddTextChunk("void");
6521 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6522 }
6523
6524 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6525 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6526 Builder.AddPlaceholderChunk("object-type");
6527 Builder.AddTextChunk(" *");
6528 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6529 Builder.AddTextChunk("object");
6530 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6531 CXCursor_ObjCInstanceMethodDecl));
6532 }
6533 }
6534
6535 // - (void)removeKey:(NSSet *)objects
6536 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006537 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006538 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006539 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006540 if (ReturnType.isNull()) {
6541 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6542 Builder.AddTextChunk("void");
6543 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6544 }
6545
6546 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6547 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6548 Builder.AddTextChunk("NSSet *");
6549 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6550 Builder.AddTextChunk("objects");
6551 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6552 CXCursor_ObjCInstanceMethodDecl));
6553 }
6554 }
6555
6556 // - (void)intersectKey:(NSSet *)objects
6557 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006558 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006559 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006560 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006561 if (ReturnType.isNull()) {
6562 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6563 Builder.AddTextChunk("void");
6564 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6565 }
6566
6567 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6568 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6569 Builder.AddTextChunk("NSSet *");
6570 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6571 Builder.AddTextChunk("objects");
6572 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6573 CXCursor_ObjCInstanceMethodDecl));
6574 }
6575 }
6576
6577 // Key-Value Observing
6578 // + (NSSet *)keyPathsForValuesAffectingKey
6579 if (!IsInstanceMethod &&
6580 (ReturnType.isNull() ||
6581 (ReturnType->isObjCObjectPointerType() &&
6582 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6583 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6584 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006585 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006586 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006587 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006588 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006589 if (ReturnType.isNull()) {
6590 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6591 Builder.AddTextChunk("NSSet *");
6592 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6593 }
6594
6595 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6596 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00006597 CXCursor_ObjCClassMethodDecl));
6598 }
6599 }
6600
6601 // + (BOOL)automaticallyNotifiesObserversForKey
6602 if (!IsInstanceMethod &&
6603 (ReturnType.isNull() ||
6604 ReturnType->isIntegerType() ||
6605 ReturnType->isBooleanType())) {
6606 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006607 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00006608 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6609 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6610 if (ReturnType.isNull()) {
6611 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6612 Builder.AddTextChunk("BOOL");
6613 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6614 }
6615
6616 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6617 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6618 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00006619 }
6620 }
6621}
6622
Douglas Gregor636a61e2010-04-07 00:21:17 +00006623void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6624 bool IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006625 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006626 // Determine the return type of the method we're declaring, if
6627 // provided.
6628 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006629 Decl *IDecl = 0;
6630 if (CurContext->isObjCContainer()) {
6631 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6632 IDecl = cast<Decl>(OCD);
6633 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006634 // Determine where we should start searching for methods.
6635 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006636 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00006637 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006638 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6639 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006640 IsInImplementation = true;
6641 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006642 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006643 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006644 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006645 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00006646 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006647 }
6648
6649 if (!SearchDecl && S) {
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006650 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006651 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006652 }
6653
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006654 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006655 HandleCodeCompleteResults(this, CodeCompleter,
6656 CodeCompletionContext::CCC_Other,
6657 0, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006658 return;
6659 }
6660
6661 // Find all of the methods that we could declare/implement here.
6662 KnownMethodsMap KnownMethods;
6663 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006664 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006665
Douglas Gregor636a61e2010-04-07 00:21:17 +00006666 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00006667 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006668 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6669 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006670 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00006671 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006672 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6673 MEnd = KnownMethods.end();
6674 M != MEnd; ++M) {
Douglas Gregor416b5752010-08-25 01:08:01 +00006675 ObjCMethodDecl *Method = M->second.first;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006676 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor636a61e2010-04-07 00:21:17 +00006677
6678 // If the result type was not already provided, add it to the
6679 // pattern as (type).
Douglas Gregor669a25a2011-02-17 00:22:45 +00006680 if (ReturnType.isNull())
Douglas Gregor75acd922011-09-27 23:30:47 +00006681 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6682 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006683
6684 Selector Sel = Method->getSelector();
6685
6686 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006687 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006688 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006689
6690 // Add parameters to the pattern.
6691 unsigned I = 0;
6692 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6693 PEnd = Method->param_end();
6694 P != PEnd; (void)++P, ++I) {
6695 // Add the part of the selector name.
6696 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006697 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00006698 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006699 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6700 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006701 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006702 } else
6703 break;
6704
6705 // Add the parameter type.
Douglas Gregor75acd922011-09-27 23:30:47 +00006706 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6707 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006708
6709 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006710 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006711 }
6712
6713 if (Method->isVariadic()) {
6714 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006715 Builder.AddChunk(CodeCompletionString::CK_Comma);
6716 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00006717 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00006718
Douglas Gregord37c59d2010-05-28 00:57:46 +00006719 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006720 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006721 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6722 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6723 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006724 if (!Method->getResultType()->isVoidType()) {
6725 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006726 Builder.AddTextChunk("return");
6727 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6728 Builder.AddPlaceholderChunk("expression");
6729 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006730 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006731 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00006732
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006733 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6734 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006735 }
6736
Douglas Gregor416b5752010-08-25 01:08:01 +00006737 unsigned Priority = CCP_CodePattern;
6738 if (!M->second.second)
6739 Priority += CCD_InBaseClass;
6740
Douglas Gregor78254c82012-03-27 23:34:16 +00006741 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006742 }
6743
Douglas Gregor669a25a2011-02-17 00:22:45 +00006744 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6745 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006746 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006747 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006748 Containers.push_back(SearchDecl);
6749
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006750 VisitedSelectorSet KnownSelectors;
6751 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6752 MEnd = KnownMethods.end();
6753 M != MEnd; ++M)
6754 KnownSelectors.insert(M->first);
6755
6756
Douglas Gregor669a25a2011-02-17 00:22:45 +00006757 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6758 if (!IFace)
6759 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6760 IFace = Category->getClassInterface();
6761
6762 if (IFace) {
6763 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6764 Category = Category->getNextClassCategory())
6765 Containers.push_back(Category);
6766 }
6767
6768 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6769 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6770 PEnd = Containers[I]->prop_end();
6771 P != PEnd; ++P) {
6772 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006773 KnownSelectors, Results);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006774 }
6775 }
6776 }
6777
Douglas Gregor636a61e2010-04-07 00:21:17 +00006778 Results.ExitScope();
6779
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006780 HandleCodeCompleteResults(this, CodeCompleter,
6781 CodeCompletionContext::CCC_Other,
6782 Results.data(),Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00006783}
Douglas Gregor95887f92010-07-08 23:20:03 +00006784
6785void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6786 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00006787 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00006788 ParsedType ReturnTy,
Douglas Gregor95887f92010-07-08 23:20:03 +00006789 IdentifierInfo **SelIdents,
6790 unsigned NumSelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00006791 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006792 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00006793 if (ExternalSource) {
6794 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6795 I != N; ++I) {
6796 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006797 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00006798 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00006799
6800 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00006801 }
6802 }
6803
6804 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00006805 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006806 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6807 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00006808
6809 if (ReturnTy)
6810 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00006811
Douglas Gregor95887f92010-07-08 23:20:03 +00006812 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006813 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6814 MEnd = MethodPool.end();
6815 M != MEnd; ++M) {
6816 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6817 &M->second.second;
6818 MethList && MethList->Method;
Douglas Gregor95887f92010-07-08 23:20:03 +00006819 MethList = MethList->Next) {
6820 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6821 NumSelIdents))
6822 continue;
6823
Douglas Gregor45879692010-07-08 23:37:41 +00006824 if (AtParameterName) {
6825 // Suggest parameter names we've seen before.
6826 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6827 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6828 if (Param->getIdentifier()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006829 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006830 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006831 Param->getIdentifier()->getName()));
6832 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00006833 }
6834 }
6835
6836 continue;
6837 }
6838
Douglas Gregor95887f92010-07-08 23:20:03 +00006839 Result R(MethList->Method, 0);
6840 R.StartParameter = NumSelIdents;
6841 R.AllParametersAreInformative = false;
6842 R.DeclaringEntity = true;
6843 Results.MaybeAddResult(R, CurContext);
6844 }
6845 }
6846
6847 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006848 HandleCodeCompleteResults(this, CodeCompleter,
6849 CodeCompletionContext::CCC_Other,
6850 Results.data(),Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00006851}
Douglas Gregorb14904c2010-08-13 22:48:40 +00006852
Douglas Gregorec00a262010-08-24 22:20:20 +00006853void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006854 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00006855 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006856 Results.EnterNewScope();
6857
6858 // #if <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006859 CodeCompletionBuilder Builder(Results.getAllocator());
6860 Builder.AddTypedTextChunk("if");
6861 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6862 Builder.AddPlaceholderChunk("condition");
6863 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006864
6865 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006866 Builder.AddTypedTextChunk("ifdef");
6867 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6868 Builder.AddPlaceholderChunk("macro");
6869 Results.AddResult(Builder.TakeString());
6870
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006871 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006872 Builder.AddTypedTextChunk("ifndef");
6873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6874 Builder.AddPlaceholderChunk("macro");
6875 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006876
6877 if (InConditional) {
6878 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006879 Builder.AddTypedTextChunk("elif");
6880 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6881 Builder.AddPlaceholderChunk("condition");
6882 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006883
6884 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006885 Builder.AddTypedTextChunk("else");
6886 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006887
6888 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006889 Builder.AddTypedTextChunk("endif");
6890 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006891 }
6892
6893 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006894 Builder.AddTypedTextChunk("include");
6895 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6896 Builder.AddTextChunk("\"");
6897 Builder.AddPlaceholderChunk("header");
6898 Builder.AddTextChunk("\"");
6899 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006900
6901 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006902 Builder.AddTypedTextChunk("include");
6903 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6904 Builder.AddTextChunk("<");
6905 Builder.AddPlaceholderChunk("header");
6906 Builder.AddTextChunk(">");
6907 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006908
6909 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006910 Builder.AddTypedTextChunk("define");
6911 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6912 Builder.AddPlaceholderChunk("macro");
6913 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006914
6915 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006916 Builder.AddTypedTextChunk("define");
6917 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6918 Builder.AddPlaceholderChunk("macro");
6919 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6920 Builder.AddPlaceholderChunk("args");
6921 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6922 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006923
6924 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006925 Builder.AddTypedTextChunk("undef");
6926 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6927 Builder.AddPlaceholderChunk("macro");
6928 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006929
6930 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006931 Builder.AddTypedTextChunk("line");
6932 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6933 Builder.AddPlaceholderChunk("number");
6934 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006935
6936 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006937 Builder.AddTypedTextChunk("line");
6938 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6939 Builder.AddPlaceholderChunk("number");
6940 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6941 Builder.AddTextChunk("\"");
6942 Builder.AddPlaceholderChunk("filename");
6943 Builder.AddTextChunk("\"");
6944 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006945
6946 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006947 Builder.AddTypedTextChunk("error");
6948 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6949 Builder.AddPlaceholderChunk("message");
6950 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006951
6952 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006953 Builder.AddTypedTextChunk("pragma");
6954 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6955 Builder.AddPlaceholderChunk("arguments");
6956 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006957
David Blaikiebbafb8a2012-03-11 07:00:24 +00006958 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006959 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006960 Builder.AddTypedTextChunk("import");
6961 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6962 Builder.AddTextChunk("\"");
6963 Builder.AddPlaceholderChunk("header");
6964 Builder.AddTextChunk("\"");
6965 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006966
6967 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006968 Builder.AddTypedTextChunk("import");
6969 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6970 Builder.AddTextChunk("<");
6971 Builder.AddPlaceholderChunk("header");
6972 Builder.AddTextChunk(">");
6973 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006974 }
6975
6976 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006977 Builder.AddTypedTextChunk("include_next");
6978 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6979 Builder.AddTextChunk("\"");
6980 Builder.AddPlaceholderChunk("header");
6981 Builder.AddTextChunk("\"");
6982 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006983
6984 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006985 Builder.AddTypedTextChunk("include_next");
6986 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6987 Builder.AddTextChunk("<");
6988 Builder.AddPlaceholderChunk("header");
6989 Builder.AddTextChunk(">");
6990 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006991
6992 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006993 Builder.AddTypedTextChunk("warning");
6994 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6995 Builder.AddPlaceholderChunk("message");
6996 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006997
6998 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
6999 // completions for them. And __include_macros is a Clang-internal extension
7000 // that we don't want to encourage anyone to use.
7001
7002 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7003 Results.ExitScope();
7004
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007005 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0de55ce2010-08-25 18:41:16 +00007006 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007007 Results.data(), Results.size());
7008}
7009
7010void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007011 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007012 S->getFnParent()? Sema::PCC_RecoveryInFunction
7013 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007014}
7015
Douglas Gregorec00a262010-08-24 22:20:20 +00007016void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007017 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007018 IsDefinition? CodeCompletionContext::CCC_MacroName
7019 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007020 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7021 // Add just the names of macros, not their arguments.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007022 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor12785102010-08-24 20:21:13 +00007023 Results.EnterNewScope();
7024 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7025 MEnd = PP.macro_end();
7026 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007027 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007028 M->first->getName()));
7029 Results.AddResult(Builder.TakeString());
Douglas Gregor12785102010-08-24 20:21:13 +00007030 }
7031 Results.ExitScope();
7032 } else if (IsDefinition) {
7033 // FIXME: Can we detect when the user just wrote an include guard above?
7034 }
7035
Douglas Gregor0ac41382010-09-23 23:01:17 +00007036 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007037 Results.data(), Results.size());
7038}
7039
Douglas Gregorec00a262010-08-24 22:20:20 +00007040void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007041 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007042 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007043
7044 if (!CodeCompleter || CodeCompleter->includeMacros())
7045 AddMacroResults(PP, Results);
7046
7047 // defined (<macro>)
7048 Results.EnterNewScope();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007049 CodeCompletionBuilder Builder(Results.getAllocator());
7050 Builder.AddTypedTextChunk("defined");
7051 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7052 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7053 Builder.AddPlaceholderChunk("macro");
7054 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7055 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007056 Results.ExitScope();
7057
7058 HandleCodeCompleteResults(this, CodeCompleter,
7059 CodeCompletionContext::CCC_PreprocessorExpression,
7060 Results.data(), Results.size());
7061}
7062
7063void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7064 IdentifierInfo *Macro,
7065 MacroInfo *MacroInfo,
7066 unsigned Argument) {
7067 // FIXME: In the future, we could provide "overload" results, much like we
7068 // do for function calls.
7069
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007070 // Now just ignore this. There will be another code-completion callback
7071 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007072}
7073
Douglas Gregor11583702010-08-25 17:04:25 +00007074void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007075 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007076 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor11583702010-08-25 17:04:25 +00007077 0, 0);
7078}
7079
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007080void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007081 SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007082 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00007083 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7084 CodeCompletionDeclConsumer Consumer(Builder,
7085 Context.getTranslationUnitDecl());
7086 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7087 Consumer);
7088 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00007089
7090 if (!CodeCompleter || CodeCompleter->includeMacros())
7091 AddMacroResults(PP, Builder);
7092
7093 Results.clear();
7094 Results.insert(Results.end(),
7095 Builder.data(), Builder.data() + Builder.size());
7096}