blob: b33c1697bf49126869c0a7c079bce5cd9a879870 [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;
2457 return Pattern;
2458 }
Douglas Gregorf09935f2009-12-01 05:55:20 +00002459
Douglas Gregorf09935f2009-12-01 05:55:20 +00002460 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002461 Result.AddTypedTextChunk(Keyword);
2462 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002463 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002464
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002465 if (Kind == RK_Macro) {
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002466 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregorf09935f2009-12-01 05:55:20 +00002467 assert(MI && "Not a macro?");
2468
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002469 Result.AddTypedTextChunk(
2470 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregorf09935f2009-12-01 05:55:20 +00002471
2472 if (!MI->isFunctionLike())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002473 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002474
2475 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002476 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor0c505312011-07-30 08:17:44 +00002477 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002478
2479 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2480 if (MI->isC99Varargs()) {
2481 --AEnd;
2482
2483 if (A == AEnd) {
2484 Result.AddPlaceholderChunk("...");
2485 }
Douglas Gregor0c505312011-07-30 08:17:44 +00002486 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002487
Douglas Gregor0c505312011-07-30 08:17:44 +00002488 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002489 if (A != MI->arg_begin())
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002490 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor3aa55262012-01-21 00:43:38 +00002491
2492 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmith2c1dd272012-02-05 02:13:05 +00002493 SmallString<32> Arg = (*A)->getName();
Douglas Gregor3aa55262012-01-21 00:43:38 +00002494 if (MI->isC99Varargs())
2495 Arg += ", ...";
2496 else
2497 Arg += "...";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002498 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3aa55262012-01-21 00:43:38 +00002499 break;
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002500 }
Douglas Gregor3aa55262012-01-21 00:43:38 +00002501
2502 // Non-variadic macros are simple.
2503 Result.AddPlaceholderChunk(
2504 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor0c505312011-07-30 08:17:44 +00002505 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002506 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002507 return Result.TakeString();
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002508 }
2509
Douglas Gregorf64acca2010-05-25 21:41:55 +00002510 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor3545ff42009-09-21 16:56:56 +00002511 NamedDecl *ND = Declaration;
2512
Douglas Gregor9eb77012009-11-07 00:00:49 +00002513 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002514 Result.AddTypedTextChunk(
2515 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002516 Result.AddTextChunk("::");
2517 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002518 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002519
2520 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2521 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2522 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2523 }
2524 }
Douglas Gregor9eb77012009-11-07 00:00:49 +00002525
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002526 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002527
Douglas Gregor3545ff42009-09-21 16:56:56 +00002528 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002529 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002530 Ctx, Policy);
2531 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002532 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002533 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002534 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002535 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002536 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002537 }
2538
2539 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002540 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002541 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002542 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002543 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002544
Douglas Gregor3545ff42009-09-21 16:56:56 +00002545 // Figure out which template parameters are deduced (or have default
2546 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00002547 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002548 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002549 unsigned LastDeducibleArgument;
2550 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2551 --LastDeducibleArgument) {
2552 if (!Deduced[LastDeducibleArgument - 1]) {
2553 // C++0x: Figure out if the template argument has a default. If so,
2554 // the user doesn't need to type this argument.
2555 // FIXME: We need to abstract template parameters better!
2556 bool HasDefaultArg = false;
2557 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002558 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002559 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2560 HasDefaultArg = TTP->hasDefaultArgument();
2561 else if (NonTypeTemplateParmDecl *NTTP
2562 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2563 HasDefaultArg = NTTP->hasDefaultArgument();
2564 else {
2565 assert(isa<TemplateTemplateParmDecl>(Param));
2566 HasDefaultArg
Douglas Gregor9eb77012009-11-07 00:00:49 +00002567 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002568 }
2569
2570 if (!HasDefaultArg)
2571 break;
2572 }
2573 }
2574
2575 if (LastDeducibleArgument) {
2576 // Some of the function template arguments cannot be deduced from a
2577 // function call, so we introduce an explicit template argument list
2578 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002579 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002580 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00002581 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002582 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002583 }
2584
2585 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002586 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002587 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002588 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00002589 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002590 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002591 }
2592
2593 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor5bf52692009-09-22 23:15:58 +00002594 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002595 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002596 Result.AddTypedTextChunk(
2597 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002598 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002599 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002600 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002601 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002602 }
2603
Douglas Gregord3c5d792009-11-17 16:44:22 +00002604 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00002605 Selector Sel = Method->getSelector();
2606 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002607 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002608 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002609 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002610 }
2611
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00002612 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00002613 SelName += ':';
2614 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002615 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002616 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002617 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00002618
2619 // If there is only one parameter, and we're past it, add an empty
2620 // typed-text chunk since there is nothing to type.
2621 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002622 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00002623 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00002624 unsigned Idx = 0;
2625 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2626 PEnd = Method->param_end();
2627 P != PEnd; (void)++P, ++Idx) {
2628 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00002629 std::string Keyword;
2630 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002631 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00002632 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00002633 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002634 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00002635 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002636 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002637 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002638 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002639 }
Douglas Gregor1b605f72009-11-19 01:08:35 +00002640
2641 // If we're before the starting parameter, skip the placeholder.
2642 if (Idx < StartParameter)
2643 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00002644
2645 std::string Arg;
Douglas Gregore90dd002010-08-24 16:15:59 +00002646
2647 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002648 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregore90dd002010-08-24 16:15:59 +00002649 else {
John McCall31168b02011-06-15 23:02:42 +00002650 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor8f08d742011-07-30 07:55:26 +00002651 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2652 + Arg + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00002653 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00002654 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00002655 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00002656 }
2657
Douglas Gregor400f5972010-08-31 05:13:43 +00002658 if (Method->isVariadic() && (P + 1) == PEnd)
2659 Arg += ", ...";
2660
Douglas Gregor95887f92010-07-08 23:20:03 +00002661 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002662 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00002663 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002664 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00002665 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002666 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00002667 }
2668
Douglas Gregor04c5f972009-12-23 00:21:46 +00002669 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00002670 if (Method->param_size() == 0) {
2671 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002672 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002673 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002674 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002675 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002676 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00002677 }
Douglas Gregordbb71db2010-08-23 23:51:41 +00002678
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002679 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00002680 }
2681
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002682 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00002683 }
2684
Douglas Gregorf09935f2009-12-01 05:55:20 +00002685 if (Qualifier)
Douglas Gregor5bf52692009-09-22 23:15:58 +00002686 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002687 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00002688
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002689 Result.AddTypedTextChunk(
2690 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002691 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00002692}
2693
Douglas Gregorf0f51982009-09-23 00:34:09 +00002694CodeCompletionString *
2695CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2696 unsigned CurrentArg,
Douglas Gregor36e3b5c2010-10-11 21:37:58 +00002697 Sema &S,
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002698 CodeCompletionAllocator &Allocator) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00002699 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00002700
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002701 // FIXME: Set priority, availability appropriately.
2702 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002703 FunctionDecl *FDecl = getFunction();
Douglas Gregor75acd922011-09-27 23:30:47 +00002704 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002705 const FunctionProtoType *Proto
2706 = dyn_cast<FunctionProtoType>(getFunctionType());
2707 if (!FDecl && !Proto) {
2708 // Function without a prototype. Just give the return type and a
2709 // highlighted ellipsis.
2710 const FunctionType *FT = getFunctionType();
Douglas Gregor304f9b02011-02-01 21:15:40 +00002711 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor75acd922011-09-27 23:30:47 +00002712 S.Context, Policy,
Douglas Gregor304f9b02011-02-01 21:15:40 +00002713 Result.getAllocator()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002714 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2715 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2716 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002717 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00002718 }
2719
2720 if (FDecl)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002721 Result.AddTextChunk(
2722 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002723 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002724 Result.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002725 Result.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00002726 Proto->getResultType().getAsString(Policy)));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002727
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002728 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002729 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2730 for (unsigned I = 0; I != NumParams; ++I) {
2731 if (I)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002732 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002733
2734 std::string ArgString;
2735 QualType ArgType;
2736
2737 if (FDecl) {
2738 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2739 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2740 } else {
2741 ArgType = Proto->getArgType(I);
2742 }
2743
John McCall31168b02011-06-15 23:02:42 +00002744 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002745
2746 if (I == CurrentArg)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002747 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2748 Result.getAllocator().CopyString(ArgString));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002749 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002750 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregorf0f51982009-09-23 00:34:09 +00002751 }
2752
2753 if (Proto && Proto->isVariadic()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002754 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002755 if (CurrentArg < NumParams)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002756 Result.AddTextChunk("...");
Douglas Gregorf0f51982009-09-23 00:34:09 +00002757 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002758 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregorf0f51982009-09-23 00:34:09 +00002759 }
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002760 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf0f51982009-09-23 00:34:09 +00002761
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002762 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00002763}
2764
Chris Lattner0e62c1c2011-07-23 10:55:15 +00002765unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002766 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00002767 bool PreferredTypeIsPointer) {
2768 unsigned Priority = CCP_Macro;
2769
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002770 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2771 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2772 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00002773 Priority = CCP_Constant;
2774 if (PreferredTypeIsPointer)
2775 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00002776 }
2777 // Treat "YES", "NO", "true", and "false" as constants.
2778 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2779 MacroName.equals("true") || MacroName.equals("false"))
2780 Priority = CCP_Constant;
2781 // Treat "bool" as a type.
2782 else if (MacroName.equals("bool"))
2783 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2784
Douglas Gregor6e240332010-08-16 16:18:59 +00002785
2786 return Priority;
2787}
2788
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002789CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2790 if (!D)
2791 return CXCursor_UnexposedDecl;
2792
2793 switch (D->getKind()) {
2794 case Decl::Enum: return CXCursor_EnumDecl;
2795 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2796 case Decl::Field: return CXCursor_FieldDecl;
2797 case Decl::Function:
2798 return CXCursor_FunctionDecl;
2799 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2800 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002801 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00002802
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00002803 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002804 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2805 case Decl::ObjCMethod:
2806 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2807 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2808 case Decl::CXXMethod: return CXCursor_CXXMethod;
2809 case Decl::CXXConstructor: return CXCursor_Constructor;
2810 case Decl::CXXDestructor: return CXCursor_Destructor;
2811 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2812 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidis3698cef2012-01-24 21:39:26 +00002813 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002814 case Decl::ParmVar: return CXCursor_ParmDecl;
2815 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smithdda56e42011-04-15 14:24:37 +00002816 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002817 case Decl::Var: return CXCursor_VarDecl;
2818 case Decl::Namespace: return CXCursor_Namespace;
2819 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2820 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2821 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2822 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2823 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2824 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis12afd702011-09-30 17:58:23 +00002825 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002826 case Decl::ClassTemplatePartialSpecialization:
2827 return CXCursor_ClassTemplatePartialSpecialization;
2828 case Decl::UsingDirective: return CXCursor_UsingDirective;
2829
2830 case Decl::Using:
2831 case Decl::UnresolvedUsingValue:
2832 case Decl::UnresolvedUsingTypename:
2833 return CXCursor_UsingDeclaration;
2834
Douglas Gregor4cd65962011-06-03 23:08:58 +00002835 case Decl::ObjCPropertyImpl:
2836 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2837 case ObjCPropertyImplDecl::Dynamic:
2838 return CXCursor_ObjCDynamicDecl;
2839
2840 case ObjCPropertyImplDecl::Synthesize:
2841 return CXCursor_ObjCSynthesizeDecl;
2842 }
Douglas Gregor4cd65962011-06-03 23:08:58 +00002843
Douglas Gregor09c0eb12010-09-03 23:30:36 +00002844 default:
2845 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2846 switch (TD->getTagKind()) {
2847 case TTK_Struct: return CXCursor_StructDecl;
2848 case TTK_Class: return CXCursor_ClassDecl;
2849 case TTK_Union: return CXCursor_UnionDecl;
2850 case TTK_Enum: return CXCursor_EnumDecl;
2851 }
2852 }
2853 }
2854
2855 return CXCursor_UnexposedDecl;
2856}
2857
Douglas Gregor55b037b2010-07-08 20:55:51 +00002858static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2859 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00002860 typedef CodeCompletionResult Result;
Douglas Gregor55b037b2010-07-08 20:55:51 +00002861
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002862 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002863
Douglas Gregor9eb77012009-11-07 00:00:49 +00002864 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2865 MEnd = PP.macro_end();
Douglas Gregor55b037b2010-07-08 20:55:51 +00002866 M != MEnd; ++M) {
Douglas Gregor6e240332010-08-16 16:18:59 +00002867 Results.AddResult(Result(M->first,
2868 getMacroUsagePriority(M->first->getName(),
David Blaikiebbafb8a2012-03-11 07:00:24 +00002869 PP.getLangOpts(),
Douglas Gregor6e240332010-08-16 16:18:59 +00002870 TargetTypeIsPointer)));
Douglas Gregor55b037b2010-07-08 20:55:51 +00002871 }
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002872
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002873 Results.ExitScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002874
Douglas Gregorf329c7c2009-10-30 16:50:04 +00002875}
2876
Douglas Gregorce0e8562010-08-23 21:54:33 +00002877static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2878 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00002879 typedef CodeCompletionResult Result;
Douglas Gregorce0e8562010-08-23 21:54:33 +00002880
2881 Results.EnterNewScope();
Douglas Gregor8e3e8742010-10-18 21:05:04 +00002882
Douglas Gregorce0e8562010-08-23 21:54:33 +00002883 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2884 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2885 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2886 Results.AddResult(Result("__func__", CCP_Constant));
2887 Results.ExitScope();
2888}
2889
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00002890static void HandleCodeCompleteResults(Sema *S,
2891 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002892 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00002893 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002894 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002895 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002896 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002897}
2898
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002899static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2900 Sema::ParserCompletionContext PCC) {
2901 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00002902 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002903 return CodeCompletionContext::CCC_TopLevel;
2904
John McCallfaf5fb42010-08-26 23:41:50 +00002905 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002906 return CodeCompletionContext::CCC_ClassStructUnion;
2907
John McCallfaf5fb42010-08-26 23:41:50 +00002908 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002909 return CodeCompletionContext::CCC_ObjCInterface;
2910
John McCallfaf5fb42010-08-26 23:41:50 +00002911 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002912 return CodeCompletionContext::CCC_ObjCImplementation;
2913
John McCallfaf5fb42010-08-26 23:41:50 +00002914 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002915 return CodeCompletionContext::CCC_ObjCIvarList;
2916
John McCallfaf5fb42010-08-26 23:41:50 +00002917 case Sema::PCC_Template:
2918 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00002919 if (S.CurContext->isFileContext())
2920 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00002921 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00002922 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00002923 return CodeCompletionContext::CCC_Other;
Douglas Gregor0ac41382010-09-23 23:01:17 +00002924
John McCallfaf5fb42010-08-26 23:41:50 +00002925 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00002926 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00002927
John McCallfaf5fb42010-08-26 23:41:50 +00002928 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002929 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2930 S.getLangOpts().ObjC1)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00002931 return CodeCompletionContext::CCC_ParenthesizedExpression;
2932 else
2933 return CodeCompletionContext::CCC_Expression;
2934
2935 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00002936 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002937 return CodeCompletionContext::CCC_Expression;
2938
John McCallfaf5fb42010-08-26 23:41:50 +00002939 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002940 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00002941
John McCallfaf5fb42010-08-26 23:41:50 +00002942 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00002943 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00002944
2945 case Sema::PCC_ParenthesizedExpression:
2946 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor80039242011-02-15 20:33:25 +00002947
2948 case Sema::PCC_LocalDeclarationSpecifiers:
2949 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002950 }
David Blaikie8a40f702012-01-17 06:56:22 +00002951
2952 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00002953}
2954
Douglas Gregorac322ec2010-08-27 21:18:54 +00002955/// \brief If we're in a C++ virtual member function, add completion results
2956/// that invoke the functions we override, since it's common to invoke the
2957/// overridden function as well as adding new functionality.
2958///
2959/// \param S The semantic analysis object for which we are generating results.
2960///
2961/// \param InContext This context in which the nested-name-specifier preceding
2962/// the code-completion point
2963static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2964 ResultBuilder &Results) {
2965 // Look through blocks.
2966 DeclContext *CurContext = S.CurContext;
2967 while (isa<BlockDecl>(CurContext))
2968 CurContext = CurContext->getParent();
2969
2970
2971 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2972 if (!Method || !Method->isVirtual())
2973 return;
2974
2975 // We need to have names for all of the parameters, if we're going to
2976 // generate a forwarding call.
2977 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2978 PEnd = Method->param_end();
2979 P != PEnd;
2980 ++P) {
2981 if (!(*P)->getDeclName())
2982 return;
2983 }
2984
Douglas Gregor75acd922011-09-27 23:30:47 +00002985 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorac322ec2010-08-27 21:18:54 +00002986 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2987 MEnd = Method->end_overridden_methods();
2988 M != MEnd; ++M) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002989 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorac322ec2010-08-27 21:18:54 +00002990 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2991 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2992 continue;
2993
2994 // If we need a nested-name-specifier, add one now.
2995 if (!InContext) {
2996 NestedNameSpecifier *NNS
2997 = getRequiredQualification(S.Context, CurContext,
2998 Overridden->getDeclContext());
2999 if (NNS) {
3000 std::string Str;
3001 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003002 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003003 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003004 }
3005 } else if (!InContext->Equals(Overridden->getDeclContext()))
3006 continue;
3007
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003008 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003009 Overridden->getNameAsString()));
3010 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003011 bool FirstParam = true;
3012 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3013 PEnd = Method->param_end();
3014 P != PEnd; ++P) {
3015 if (FirstParam)
3016 FirstParam = false;
3017 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003018 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003019
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003020 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003021 (*P)->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003022 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003023 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3024 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorac322ec2010-08-27 21:18:54 +00003025 CCP_SuperCompletion,
3026 CXCursor_CXXMethod));
3027 Results.Ignore(Overridden);
3028 }
3029}
3030
Douglas Gregor07f43572012-01-29 18:15:03 +00003031void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3032 ModuleIdPath Path) {
3033 typedef CodeCompletionResult Result;
3034 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3035 CodeCompletionContext::CCC_Other);
3036 Results.EnterNewScope();
3037
3038 CodeCompletionAllocator &Allocator = Results.getAllocator();
3039 CodeCompletionBuilder Builder(Allocator);
3040 typedef CodeCompletionResult Result;
3041 if (Path.empty()) {
3042 // Enumerate all top-level modules.
3043 llvm::SmallVector<Module *, 8> Modules;
3044 PP.getHeaderSearchInfo().collectAllModules(Modules);
3045 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3046 Builder.AddTypedTextChunk(
3047 Builder.getAllocator().CopyString(Modules[I]->Name));
3048 Results.AddResult(Result(Builder.TakeString(),
3049 CCP_Declaration,
3050 CXCursor_NotImplemented,
3051 Modules[I]->isAvailable()
3052 ? CXAvailability_Available
3053 : CXAvailability_NotAvailable));
3054 }
3055 } else {
3056 // Load the named module.
3057 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3058 Module::AllVisible,
3059 /*IsInclusionDirective=*/false);
3060 // Enumerate submodules.
3061 if (Mod) {
3062 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3063 SubEnd = Mod->submodule_end();
3064 Sub != SubEnd; ++Sub) {
3065
3066 Builder.AddTypedTextChunk(
3067 Builder.getAllocator().CopyString((*Sub)->Name));
3068 Results.AddResult(Result(Builder.TakeString(),
3069 CCP_Declaration,
3070 CXCursor_NotImplemented,
3071 (*Sub)->isAvailable()
3072 ? CXAvailability_Available
3073 : CXAvailability_NotAvailable));
3074 }
3075 }
3076 }
3077 Results.ExitScope();
3078 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3079 Results.data(),Results.size());
3080}
3081
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003082void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003083 ParserCompletionContext CompletionContext) {
John McCall276321a2010-08-25 06:19:51 +00003084 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003085 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003086 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003087 Results.EnterNewScope();
Douglas Gregor50832e02010-09-20 22:39:41 +00003088
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003089 // Determine how to filter results, e.g., so that the names of
3090 // values (functions, enumerators, function templates, etc.) are
3091 // only allowed where we can have an expression.
3092 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003093 case PCC_Namespace:
3094 case PCC_Class:
3095 case PCC_ObjCInterface:
3096 case PCC_ObjCImplementation:
3097 case PCC_ObjCInstanceVariableList:
3098 case PCC_Template:
3099 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003100 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003101 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003102 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3103 break;
3104
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003105 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003106 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003107 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003108 case PCC_ForInit:
3109 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003110 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003111 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3112 else
3113 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003114
David Blaikiebbafb8a2012-03-11 07:00:24 +00003115 if (getLangOpts().CPlusPlus)
Douglas Gregorac322ec2010-08-27 21:18:54 +00003116 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003117 break;
Douglas Gregor6da3db42010-05-25 05:58:43 +00003118
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003119 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003120 // Unfiltered
3121 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003122 }
3123
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003124 // If we are in a C++ non-static member function, check the qualifiers on
3125 // the member function to filter/prioritize the results list.
3126 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3127 if (CurMethod->isInstance())
3128 Results.setObjectTypeQualifiers(
3129 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3130
Douglas Gregorc580c522010-01-14 01:09:38 +00003131 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003132 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3133 CodeCompleter->includeGlobals());
Douglas Gregor92253692009-12-07 09:54:55 +00003134
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003135 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003136 Results.ExitScope();
3137
Douglas Gregorce0e8562010-08-23 21:54:33 +00003138 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003139 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003140 case PCC_Expression:
3141 case PCC_Statement:
3142 case PCC_RecoveryInFunction:
3143 if (S->getFnParent())
David Blaikiebbafb8a2012-03-11 07:00:24 +00003144 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003145 break;
3146
3147 case PCC_Namespace:
3148 case PCC_Class:
3149 case PCC_ObjCInterface:
3150 case PCC_ObjCImplementation:
3151 case PCC_ObjCInstanceVariableList:
3152 case PCC_Template:
3153 case PCC_MemberTemplate:
3154 case PCC_ForInit:
3155 case PCC_Condition:
3156 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003157 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003158 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003159 }
3160
Douglas Gregor9eb77012009-11-07 00:00:49 +00003161 if (CodeCompleter->includeMacros())
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003162 AddMacroResults(PP, Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003163
Douglas Gregor50832e02010-09-20 22:39:41 +00003164 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003165 Results.data(),Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003166}
3167
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003168static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3169 ParsedType Receiver,
3170 IdentifierInfo **SelIdents,
3171 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003172 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003173 bool IsSuper,
3174 ResultBuilder &Results);
3175
3176void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3177 bool AllowNonIdentifiers,
3178 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003179 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003180 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003181 AllowNestedNameSpecifiers
3182 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3183 : CodeCompletionContext::CCC_Name);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003184 Results.EnterNewScope();
3185
3186 // Type qualifiers can come after names.
3187 Results.AddResult(Result("const"));
3188 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003189 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003190 Results.AddResult(Result("restrict"));
3191
David Blaikiebbafb8a2012-03-11 07:00:24 +00003192 if (getLangOpts().CPlusPlus) {
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003193 if (AllowNonIdentifiers) {
3194 Results.AddResult(Result("operator"));
3195 }
3196
3197 // Add nested-name-specifiers.
3198 if (AllowNestedNameSpecifiers) {
3199 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003200 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003201 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3202 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3203 CodeCompleter->includeGlobals());
Douglas Gregor0ac41382010-09-23 23:01:17 +00003204 Results.setFilter(0);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003205 }
3206 }
3207 Results.ExitScope();
3208
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003209 // If we're in a context where we might have an expression (rather than a
3210 // declaration), and what we've seen so far is an Objective-C type that could
3211 // be a receiver of a class message, this may be a class message send with
3212 // the initial opening bracket '[' missing. Add appropriate completions.
3213 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3214 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3215 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3216 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3217 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3218 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3219 DS.getTypeQualifiers() == 0 &&
3220 S &&
3221 (S->getFlags() & Scope::DeclScope) != 0 &&
3222 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3223 Scope::FunctionPrototypeScope |
3224 Scope::AtCatchScope)) == 0) {
3225 ParsedType T = DS.getRepAsType();
3226 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregorf86e4da2010-09-20 23:34:21 +00003227 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003228 }
3229
Douglas Gregor56ccce02010-08-24 04:59:56 +00003230 // Note that we intentionally suppress macro results here, since we do not
3231 // encourage using macros to produce the names of entities.
3232
Douglas Gregor0ac41382010-09-23 23:01:17 +00003233 HandleCodeCompleteResults(this, CodeCompleter,
3234 Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003235 Results.data(), Results.size());
3236}
3237
Douglas Gregor68762e72010-08-23 21:17:50 +00003238struct Sema::CodeCompleteExpressionData {
3239 CodeCompleteExpressionData(QualType PreferredType = QualType())
3240 : PreferredType(PreferredType), IntegralConstantExpression(false),
3241 ObjCCollection(false) { }
3242
3243 QualType PreferredType;
3244 bool IntegralConstantExpression;
3245 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003246 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003247};
3248
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003249/// \brief Perform code-completion in an expression context when we know what
3250/// type we're looking for.
Douglas Gregor85b50632010-07-28 21:50:18 +00003251///
3252/// \param IntegralConstantExpression Only permit integral constant
3253/// expressions.
Douglas Gregor68762e72010-08-23 21:17:50 +00003254void Sema::CodeCompleteExpression(Scope *S,
3255 const CodeCompleteExpressionData &Data) {
John McCall276321a2010-08-25 06:19:51 +00003256 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003257 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3258 CodeCompletionContext::CCC_Expression);
Douglas Gregor68762e72010-08-23 21:17:50 +00003259 if (Data.ObjCCollection)
3260 Results.setFilter(&ResultBuilder::IsObjCCollection);
3261 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003262 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003263 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003264 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3265 else
3266 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003267
3268 if (!Data.PreferredType.isNull())
3269 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3270
3271 // Ignore any declarations that we were told that we don't care about.
3272 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3273 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003274
3275 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003276 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3277 CodeCompleter->includeGlobals());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003278
3279 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003280 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003281 Results.ExitScope();
3282
Douglas Gregor55b037b2010-07-08 20:55:51 +00003283 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003284 if (!Data.PreferredType.isNull())
3285 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3286 || Data.PreferredType->isMemberPointerType()
3287 || Data.PreferredType->isBlockPointerType();
Douglas Gregor55b037b2010-07-08 20:55:51 +00003288
Douglas Gregorce0e8562010-08-23 21:54:33 +00003289 if (S->getFnParent() &&
3290 !Data.ObjCCollection &&
3291 !Data.IntegralConstantExpression)
David Blaikiebbafb8a2012-03-11 07:00:24 +00003292 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003293
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003294 if (CodeCompleter->includeMacros())
Douglas Gregor55b037b2010-07-08 20:55:51 +00003295 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003296 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor68762e72010-08-23 21:17:50 +00003297 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3298 Data.PreferredType),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003299 Results.data(),Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003300}
3301
Douglas Gregoreda7e542010-09-18 01:28:11 +00003302void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3303 if (E.isInvalid())
3304 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003305 else if (getLangOpts().ObjC1)
Douglas Gregoreda7e542010-09-18 01:28:11 +00003306 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003307}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003308
Douglas Gregorb888acf2010-12-09 23:01:55 +00003309/// \brief The set of properties that have already been added, referenced by
3310/// property name.
3311typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3312
Douglas Gregor9291bad2009-11-18 01:29:26 +00003313static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor5d649882009-11-18 22:32:06 +00003314 bool AllowCategories,
Douglas Gregor95147142011-05-05 15:50:42 +00003315 bool AllowNullaryMethods,
Douglas Gregor9291bad2009-11-18 01:29:26 +00003316 DeclContext *CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003317 AddedPropertiesSet &AddedProperties,
Douglas Gregor9291bad2009-11-18 01:29:26 +00003318 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003319 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003320
3321 // Add properties in this container.
3322 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3323 PEnd = Container->prop_end();
3324 P != PEnd;
Douglas Gregorb888acf2010-12-09 23:01:55 +00003325 ++P) {
3326 if (AddedProperties.insert(P->getIdentifier()))
3327 Results.MaybeAddResult(Result(*P, 0), CurContext);
3328 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003329
Douglas Gregor95147142011-05-05 15:50:42 +00003330 // Add nullary methods
3331 if (AllowNullaryMethods) {
3332 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00003333 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor95147142011-05-05 15:50:42 +00003334 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3335 MEnd = Container->meth_end();
3336 M != MEnd; ++M) {
3337 if (M->getSelector().isUnarySelector())
3338 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3339 if (AddedProperties.insert(Name)) {
3340 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor75acd922011-09-27 23:30:47 +00003341 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor95147142011-05-05 15:50:42 +00003342 Builder.AddTypedTextChunk(
3343 Results.getAllocator().CopyString(Name->getName()));
3344
3345 CXAvailabilityKind Availability = CXAvailability_Available;
3346 switch (M->getAvailability()) {
3347 case AR_Available:
3348 case AR_NotYetIntroduced:
3349 Availability = CXAvailability_Available;
3350 break;
3351
3352 case AR_Deprecated:
3353 Availability = CXAvailability_Deprecated;
3354 break;
3355
3356 case AR_Unavailable:
3357 Availability = CXAvailability_NotAvailable;
3358 break;
3359 }
3360
3361 Results.MaybeAddResult(Result(Builder.TakeString(),
3362 CCP_MemberDeclaration + CCD_MethodAsProperty,
3363 M->isInstanceMethod()
3364 ? CXCursor_ObjCInstanceMethodDecl
3365 : CXCursor_ObjCClassMethodDecl,
3366 Availability),
3367 CurContext);
3368 }
3369 }
3370 }
3371
3372
Douglas Gregor9291bad2009-11-18 01:29:26 +00003373 // Add properties in referenced protocols.
3374 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3375 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3376 PEnd = Protocol->protocol_end();
3377 P != PEnd; ++P)
Douglas Gregor95147142011-05-05 15:50:42 +00003378 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3379 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003380 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor5d649882009-11-18 22:32:06 +00003381 if (AllowCategories) {
3382 // Look through categories.
3383 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3384 Category; Category = Category->getNextClassCategory())
Douglas Gregor95147142011-05-05 15:50:42 +00003385 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3386 CurContext, AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00003387 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003388
3389 // Look through protocols.
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003390 for (ObjCInterfaceDecl::all_protocol_iterator
3391 I = IFace->all_referenced_protocol_begin(),
3392 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor95147142011-05-05 15:50:42 +00003393 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3394 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003395
3396 // Look in the superclass.
3397 if (IFace->getSuperClass())
Douglas Gregor95147142011-05-05 15:50:42 +00003398 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3399 AllowNullaryMethods, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003400 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003401 } else if (const ObjCCategoryDecl *Category
3402 = dyn_cast<ObjCCategoryDecl>(Container)) {
3403 // Look through protocols.
Ted Kremenek0ef508d2010-09-01 01:21:15 +00003404 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3405 PEnd = Category->protocol_end();
Douglas Gregor9291bad2009-11-18 01:29:26 +00003406 P != PEnd; ++P)
Douglas Gregor95147142011-05-05 15:50:42 +00003407 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3408 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003409 }
3410}
3411
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003412void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor2436e712009-09-17 21:32:03 +00003413 SourceLocation OpLoc,
3414 bool IsArrow) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003415 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00003416 return;
3417
Douglas Gregor1cc88a92012-01-23 15:59:30 +00003418 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3419 if (ConvertedBase.isInvalid())
3420 return;
3421 Base = ConvertedBase.get();
3422
John McCall276321a2010-08-25 06:19:51 +00003423 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003424
Douglas Gregor2436e712009-09-17 21:32:03 +00003425 QualType BaseType = Base->getType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003426
3427 if (IsArrow) {
3428 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3429 BaseType = Ptr->getPointeeType();
3430 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003431 /*Do nothing*/ ;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003432 else
3433 return;
3434 }
3435
Douglas Gregor21325842011-07-07 16:03:39 +00003436 enum CodeCompletionContext::Kind contextKind;
3437
3438 if (IsArrow) {
3439 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3440 }
3441 else {
3442 if (BaseType->isObjCObjectPointerType() ||
3443 BaseType->isObjCObjectOrInterfaceType()) {
3444 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3445 }
3446 else {
3447 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3448 }
3449 }
3450
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003451 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor21325842011-07-07 16:03:39 +00003452 CodeCompletionContext(contextKind,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003453 BaseType),
3454 &ResultBuilder::IsMember);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003455 Results.EnterNewScope();
3456 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003457 // Indicate that we are performing a member access, and the cv-qualifiers
3458 // for the base object type.
3459 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3460
Douglas Gregor9291bad2009-11-18 01:29:26 +00003461 // Access to a C/C++ class, struct, or union.
Douglas Gregor6ae4c522010-01-14 03:21:49 +00003462 Results.allowNestedNameSpecifiers();
Douglas Gregor09bbc652010-01-14 15:47:35 +00003463 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003464 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3465 CodeCompleter->includeGlobals());
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003466
David Blaikiebbafb8a2012-03-11 07:00:24 +00003467 if (getLangOpts().CPlusPlus) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003468 if (!Results.empty()) {
3469 // The "template" keyword can follow "->" or "." in the grammar.
3470 // However, we only want to suggest the template keyword if something
3471 // is dependent.
3472 bool IsDependent = BaseType->isDependentType();
3473 if (!IsDependent) {
3474 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3475 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3476 IsDependent = Ctx->isDependentContext();
3477 break;
3478 }
3479 }
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003480
Douglas Gregor9291bad2009-11-18 01:29:26 +00003481 if (IsDependent)
Douglas Gregor78a21012010-01-14 16:01:26 +00003482 Results.AddResult(Result("template"));
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003483 }
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003484 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003485 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3486 // Objective-C property reference.
Douglas Gregorb888acf2010-12-09 23:01:55 +00003487 AddedPropertiesSet AddedProperties;
Douglas Gregor9291bad2009-11-18 01:29:26 +00003488
3489 // Add property results based on our interface.
3490 const ObjCObjectPointerType *ObjCPtr
3491 = BaseType->getAsObjCInterfacePointerType();
3492 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor95147142011-05-05 15:50:42 +00003493 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3494 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00003495 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003496
3497 // Add properties from the protocols in a qualified interface.
3498 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3499 E = ObjCPtr->qual_end();
3500 I != E; ++I)
Douglas Gregor95147142011-05-05 15:50:42 +00003501 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3502 AddedProperties, Results);
Douglas Gregor9291bad2009-11-18 01:29:26 +00003503 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCall8b07ec22010-05-15 11:32:37 +00003504 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00003505 // Objective-C instance variable access.
3506 ObjCInterfaceDecl *Class = 0;
3507 if (const ObjCObjectPointerType *ObjCPtr
3508 = BaseType->getAs<ObjCObjectPointerType>())
3509 Class = ObjCPtr->getInterfaceDecl();
3510 else
John McCall8b07ec22010-05-15 11:32:37 +00003511 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor9291bad2009-11-18 01:29:26 +00003512
3513 // Add all ivars from this class and its superclasses.
Douglas Gregor2b8162b2010-01-14 16:08:12 +00003514 if (Class) {
3515 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3516 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor39982192010-08-15 06:18:01 +00003517 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3518 CodeCompleter->includeGlobals());
Douglas Gregor9291bad2009-11-18 01:29:26 +00003519 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003520 }
Douglas Gregor9291bad2009-11-18 01:29:26 +00003521
3522 // FIXME: How do we cope with isa?
3523
3524 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003525
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003526 // Hand off the results found for code completion.
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003527 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003528 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003529 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00003530}
3531
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003532void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3533 if (!CodeCompleter)
3534 return;
3535
John McCall276321a2010-08-25 06:19:51 +00003536 typedef CodeCompletionResult Result;
Douglas Gregor3545ff42009-09-21 16:56:56 +00003537 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003538 enum CodeCompletionContext::Kind ContextKind
3539 = CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003540 switch ((DeclSpec::TST)TagSpec) {
3541 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003542 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003543 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003544 break;
3545
3546 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003547 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003548 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003549 break;
3550
3551 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003552 case DeclSpec::TST_class:
Douglas Gregor3545ff42009-09-21 16:56:56 +00003553 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003554 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003555 break;
3556
3557 default:
David Blaikie83d382b2011-09-23 05:06:16 +00003558 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003559 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003560
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003561 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00003562 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00003563
3564 // First pass: look for tags.
3565 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00003566 LookupVisibleDecls(S, LookupTagName, Consumer,
3567 CodeCompleter->includeGlobals());
John McCalle87beb22010-04-23 18:46:30 +00003568
Douglas Gregor39982192010-08-15 06:18:01 +00003569 if (CodeCompleter->includeGlobals()) {
3570 // Second pass: look for nested name specifiers.
3571 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3572 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3573 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00003574
Douglas Gregor0ac41382010-09-23 23:01:17 +00003575 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003576 Results.data(),Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00003577}
3578
Douglas Gregor28c78432010-08-27 17:35:51 +00003579void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003580 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3581 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00003582 Results.EnterNewScope();
3583 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3584 Results.AddResult("const");
3585 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3586 Results.AddResult("volatile");
David Blaikiebbafb8a2012-03-11 07:00:24 +00003587 if (getLangOpts().C99 &&
Douglas Gregor28c78432010-08-27 17:35:51 +00003588 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3589 Results.AddResult("restrict");
3590 Results.ExitScope();
3591 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003592 Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00003593 Results.data(), Results.size());
3594}
3595
Douglas Gregord328d572009-09-21 18:10:23 +00003596void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00003597 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00003598 return;
John McCall5939b162011-08-06 07:30:58 +00003599
John McCallaab3e412010-08-25 08:40:02 +00003600 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCall5939b162011-08-06 07:30:58 +00003601 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3602 if (!type->isEnumeralType()) {
3603 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00003604 Data.IntegralConstantExpression = true;
3605 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00003606 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00003607 }
Douglas Gregord328d572009-09-21 18:10:23 +00003608
3609 // Code-complete the cases of a switch statement over an enumeration type
3610 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00003611 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregord328d572009-09-21 18:10:23 +00003612
3613 // Determine which enumerators we have already seen in the switch statement.
3614 // FIXME: Ideally, we would also be able to look *past* the code-completion
3615 // token, in case we are code-completing in the middle of the switch and not
3616 // at the end. However, we aren't able to do so at the moment.
3617 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorf2510672009-09-21 19:57:38 +00003618 NestedNameSpecifier *Qualifier = 0;
Douglas Gregord328d572009-09-21 18:10:23 +00003619 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3620 SC = SC->getNextSwitchCase()) {
3621 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3622 if (!Case)
3623 continue;
3624
3625 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3626 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3627 if (EnumConstantDecl *Enumerator
3628 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3629 // We look into the AST of the case statement to determine which
3630 // enumerator was named. Alternatively, we could compute the value of
3631 // the integral constant expression, then compare it against the
3632 // values of each enumerator. However, value-based approach would not
3633 // work as well with C++ templates where enumerators declared within a
3634 // template are type- and value-dependent.
3635 EnumeratorsSeen.insert(Enumerator);
3636
Douglas Gregorf2510672009-09-21 19:57:38 +00003637 // If this is a qualified-id, keep track of the nested-name-specifier
3638 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00003639 //
3640 // switch (TagD.getKind()) {
3641 // case TagDecl::TK_enum:
3642 // break;
3643 // case XXX
3644 //
Douglas Gregorf2510672009-09-21 19:57:38 +00003645 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00003646 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3647 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00003648 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00003649 }
3650 }
3651
David Blaikiebbafb8a2012-03-11 07:00:24 +00003652 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorf2510672009-09-21 19:57:38 +00003653 // If there are no prior enumerators in C++, check whether we have to
3654 // qualify the names of the enumerators that we suggest, because they
3655 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00003656 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00003657 }
3658
Douglas Gregord328d572009-09-21 18:10:23 +00003659 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003660 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3661 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00003662 Results.EnterNewScope();
3663 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3664 EEnd = Enum->enumerator_end();
3665 E != EEnd; ++E) {
3666 if (EnumeratorsSeen.count(*E))
3667 continue;
3668
Douglas Gregor3a69eaf2011-02-18 23:30:37 +00003669 CodeCompletionResult R(*E, Qualifier);
3670 R.Priority = CCP_EnumInCase;
3671 Results.AddResult(R, CurContext, 0, false);
Douglas Gregord328d572009-09-21 18:10:23 +00003672 }
3673 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00003674
Douglas Gregor21325842011-07-07 16:03:39 +00003675 //We need to make sure we're setting the right context,
3676 //so only say we include macros if the code completer says we do
3677 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3678 if (CodeCompleter->includeMacros()) {
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003679 AddMacroResults(PP, Results);
Douglas Gregor21325842011-07-07 16:03:39 +00003680 kind = CodeCompletionContext::CCC_OtherWithMacros;
3681 }
3682
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003683 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00003684 kind,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003685 Results.data(),Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00003686}
3687
Douglas Gregorcabea402009-09-22 15:41:20 +00003688namespace {
3689 struct IsBetterOverloadCandidate {
3690 Sema &S;
John McCallbc077cf2010-02-08 23:07:23 +00003691 SourceLocation Loc;
Douglas Gregorcabea402009-09-22 15:41:20 +00003692
3693 public:
John McCallbc077cf2010-02-08 23:07:23 +00003694 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3695 : S(S), Loc(Loc) { }
Douglas Gregorcabea402009-09-22 15:41:20 +00003696
3697 bool
3698 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall5c32be02010-08-24 20:38:10 +00003699 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregorcabea402009-09-22 15:41:20 +00003700 }
3701 };
3702}
3703
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003704static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3705 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003706 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003707
3708 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003709 if (!Args[I])
3710 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003711
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003712 return false;
3713}
3714
Richard Trieu2bd04012011-09-09 02:00:50 +00003715void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003716 llvm::ArrayRef<Expr *> Args) {
Douglas Gregorcabea402009-09-22 15:41:20 +00003717 if (!CodeCompleter)
3718 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003719
3720 // When we're code-completing for a call, we fall back to ordinary
3721 // name code-completion whenever we can't produce specific
3722 // results. We may want to revisit this strategy in the future,
3723 // e.g., by merging the two kinds of results.
3724
Douglas Gregorcabea402009-09-22 15:41:20 +00003725 Expr *Fn = (Expr *)FnIn;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003726
Douglas Gregorcabea402009-09-22 15:41:20 +00003727 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003728 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3729 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003730 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregorcabea402009-09-22 15:41:20 +00003731 return;
Douglas Gregor3ef59522009-12-11 19:06:04 +00003732 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003733
John McCall57500772009-12-16 12:17:52 +00003734 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00003735 SourceLocation Loc = Fn->getExprLoc();
3736 OverloadCandidateSet CandidateSet(Loc);
John McCall57500772009-12-16 12:17:52 +00003737
Douglas Gregorcabea402009-09-22 15:41:20 +00003738 // FIXME: What if we're calling something that isn't a function declaration?
3739 // FIXME: What if we're calling a pseudo-destructor?
3740 // FIXME: What if we're calling a member function?
3741
Douglas Gregorff59f672010-01-21 15:46:19 +00003742 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003743 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00003744
John McCall57500772009-12-16 12:17:52 +00003745 Expr *NakedFn = Fn->IgnoreParenCasts();
3746 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003747 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall57500772009-12-16 12:17:52 +00003748 /*PartialOverloading=*/ true);
3749 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3750 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorff59f672010-01-21 15:46:19 +00003751 if (FDecl) {
David Blaikiebbafb8a2012-03-11 07:00:24 +00003752 if (!getLangOpts().CPlusPlus ||
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00003753 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorff59f672010-01-21 15:46:19 +00003754 Results.push_back(ResultCandidate(FDecl));
3755 else
John McCallb89836b2010-01-26 01:37:31 +00003756 // FIXME: access?
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003757 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3758 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorff59f672010-01-21 15:46:19 +00003759 }
John McCall57500772009-12-16 12:17:52 +00003760 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003761
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003762 QualType ParamType;
3763
Douglas Gregorff59f672010-01-21 15:46:19 +00003764 if (!CandidateSet.empty()) {
3765 // Sort the overload candidate set by placing the best overloads first.
3766 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCallbc077cf2010-02-08 23:07:23 +00003767 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregorcabea402009-09-22 15:41:20 +00003768
Douglas Gregorff59f672010-01-21 15:46:19 +00003769 // Add the remaining viable overload candidates as code-completion reslults.
3770 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3771 CandEnd = CandidateSet.end();
3772 Cand != CandEnd; ++Cand) {
3773 if (Cand->Viable)
3774 Results.push_back(ResultCandidate(Cand->Function));
3775 }
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003776
3777 // From the viable candidates, try to determine the type of this parameter.
3778 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3779 if (const FunctionType *FType = Results[I].getFunctionType())
3780 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003781 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003782 if (ParamType.isNull())
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003783 ParamType = Proto->getArgType(Args.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003784 else if (!Context.hasSameUnqualifiedType(
3785 ParamType.getNonReferenceType(),
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003786 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003787 ParamType = QualType();
3788 break;
3789 }
3790 }
3791 }
3792 } else {
3793 // Try to determine the parameter type from the type of the expression
3794 // being called.
3795 QualType FunctionType = Fn->getType();
3796 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3797 FunctionType = Ptr->getPointeeType();
3798 else if (const BlockPointerType *BlockPtr
3799 = FunctionType->getAs<BlockPointerType>())
3800 FunctionType = BlockPtr->getPointeeType();
3801 else if (const MemberPointerType *MemPtr
3802 = FunctionType->getAs<MemberPointerType>())
3803 FunctionType = MemPtr->getPointeeType();
3804
3805 if (const FunctionProtoType *Proto
3806 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003807 if (Args.size() < Proto->getNumArgs())
3808 ParamType = Proto->getArgType(Args.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003809 }
Douglas Gregorcabea402009-09-22 15:41:20 +00003810 }
Douglas Gregor3ef59522009-12-11 19:06:04 +00003811
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003812 if (ParamType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003813 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003814 else
3815 CodeCompleteExpression(S, ParamType);
3816
Douglas Gregorc01890e2010-04-06 20:19:47 +00003817 if (!Results.empty())
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00003818 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregor3ef59522009-12-11 19:06:04 +00003819 Results.size());
Douglas Gregorcabea402009-09-22 15:41:20 +00003820}
3821
John McCall48871652010-08-21 09:40:31 +00003822void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3823 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003824 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003825 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003826 return;
3827 }
3828
3829 CodeCompleteExpression(S, VD->getType());
3830}
3831
3832void Sema::CodeCompleteReturn(Scope *S) {
3833 QualType ResultType;
3834 if (isa<BlockDecl>(CurContext)) {
3835 if (BlockScopeInfo *BSI = getCurBlock())
3836 ResultType = BSI->ReturnType;
3837 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3838 ResultType = Function->getResultType();
3839 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3840 ResultType = Method->getResultType();
3841
3842 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003843 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003844 else
3845 CodeCompleteExpression(S, ResultType);
3846}
3847
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003848void Sema::CodeCompleteAfterIf(Scope *S) {
3849 typedef CodeCompletionResult Result;
3850 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3851 mapCodeCompletionContext(*this, PCC_Statement));
3852 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3853 Results.EnterNewScope();
3854
3855 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3856 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3857 CodeCompleter->includeGlobals());
3858
3859 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3860
3861 // "else" block
3862 CodeCompletionBuilder Builder(Results.getAllocator());
3863 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00003864 if (Results.includeCodePatterns()) {
3865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3866 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3867 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3868 Builder.AddPlaceholderChunk("statements");
3869 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3870 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3871 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003872 Results.AddResult(Builder.TakeString());
3873
3874 // "else if" block
3875 Builder.AddTypedTextChunk("else");
3876 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3877 Builder.AddTextChunk("if");
3878 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3879 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003880 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003881 Builder.AddPlaceholderChunk("condition");
3882 else
3883 Builder.AddPlaceholderChunk("expression");
3884 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00003885 if (Results.includeCodePatterns()) {
3886 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3887 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3888 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3889 Builder.AddPlaceholderChunk("statements");
3890 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3891 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3892 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003893 Results.AddResult(Builder.TakeString());
3894
3895 Results.ExitScope();
3896
3897 if (S->getFnParent())
David Blaikiebbafb8a2012-03-11 07:00:24 +00003898 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor4ecb7202011-07-30 08:36:53 +00003899
3900 if (CodeCompleter->includeMacros())
3901 AddMacroResults(PP, Results);
3902
3903 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3904 Results.data(),Results.size());
3905}
3906
Richard Trieu2bd04012011-09-09 02:00:50 +00003907void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003908 if (LHS)
3909 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3910 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003911 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003912}
3913
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00003914void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor2436e712009-09-17 21:32:03 +00003915 bool EnteringContext) {
3916 if (!SS.getScopeRep() || !CodeCompleter)
3917 return;
3918
Douglas Gregor3545ff42009-09-21 16:56:56 +00003919 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3920 if (!Ctx)
3921 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00003922
3923 // Try to instantiate any non-dependent declaration contexts before
3924 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00003925 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00003926 return;
3927
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003928 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3929 CodeCompletionContext::CCC_Name);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003930 Results.EnterNewScope();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003931
Douglas Gregor3545ff42009-09-21 16:56:56 +00003932 // The "template" keyword can follow "::" in the grammar, but only
3933 // put it into the grammar if the nested-name-specifier is dependent.
3934 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3935 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00003936 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00003937
3938 // Add calls to overridden virtual functions, if there are any.
3939 //
3940 // FIXME: This isn't wonderful, because we don't know whether we're actually
3941 // in a context that permits expressions. This is a general issue with
3942 // qualified-id completions.
3943 if (!EnteringContext)
3944 MaybeAddOverrideCalls(*this, Ctx, Results);
3945 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003946
Douglas Gregorac322ec2010-08-27 21:18:54 +00003947 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3948 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3949
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003950 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorc1679ec2011-07-25 17:48:11 +00003951 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003952 Results.data(),Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00003953}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00003954
3955void Sema::CodeCompleteUsing(Scope *S) {
3956 if (!CodeCompleter)
3957 return;
3958
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003959 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003960 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3961 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00003962 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003963
3964 // If we aren't in class scope, we could see the "namespace" keyword.
3965 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00003966 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00003967
3968 // After "using", we can see anything that would start a
3969 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00003970 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003971 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3972 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00003973 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003974
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003975 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003976 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003977 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00003978}
3979
3980void Sema::CodeCompleteUsingDirective(Scope *S) {
3981 if (!CodeCompleter)
3982 return;
3983
Douglas Gregor3545ff42009-09-21 16:56:56 +00003984 // After "using namespace", we expect to see a namespace name or namespace
3985 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003986 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3987 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00003988 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00003989 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00003990 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003991 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3992 CodeCompleter->includeGlobals());
Douglas Gregor64b12b52009-09-22 23:31:26 +00003993 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003994 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00003995 CodeCompletionContext::CCC_Namespace,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003996 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00003997}
3998
3999void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4000 if (!CodeCompleter)
4001 return;
4002
Douglas Gregor3545ff42009-09-21 16:56:56 +00004003 DeclContext *Ctx = (DeclContext *)S->getEntity();
4004 if (!S->getParent())
4005 Ctx = Context.getTranslationUnitDecl();
4006
Douglas Gregor0ac41382010-09-23 23:01:17 +00004007 bool SuppressedGlobalResults
4008 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4009
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004010 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004011 SuppressedGlobalResults
4012 ? CodeCompletionContext::CCC_Namespace
4013 : CodeCompletionContext::CCC_Other,
4014 &ResultBuilder::IsNamespace);
4015
4016 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00004017 // We only want to see those namespaces that have already been defined
4018 // within this scope, because its likely that the user is creating an
4019 // extended namespace declaration. Keep track of the most recent
4020 // definition of each namespace.
4021 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4022 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4023 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4024 NS != NSEnd; ++NS)
4025 OrigToLatest[NS->getOriginalNamespace()] = *NS;
4026
4027 // Add the most recent definition (or extended definition) of each
4028 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00004029 Results.EnterNewScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004030 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
4031 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
4032 NS != NSEnd; ++NS)
John McCall276321a2010-08-25 06:19:51 +00004033 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregorfc59ce12010-01-14 16:14:35 +00004034 CurContext, 0, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004035 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004036 }
4037
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004038 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004039 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004040 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004041}
4042
4043void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4044 if (!CodeCompleter)
4045 return;
4046
Douglas Gregor3545ff42009-09-21 16:56:56 +00004047 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004048 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4049 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004050 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004051 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004052 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4053 CodeCompleter->includeGlobals());
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004054 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004055 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004056 Results.data(),Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004057}
4058
Douglas Gregorc811ede2009-09-18 20:05:18 +00004059void Sema::CodeCompleteOperatorName(Scope *S) {
4060 if (!CodeCompleter)
4061 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004062
John McCall276321a2010-08-25 06:19:51 +00004063 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004064 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4065 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004066 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004067 Results.EnterNewScope();
Douglas Gregorc811ede2009-09-18 20:05:18 +00004068
Douglas Gregor3545ff42009-09-21 16:56:56 +00004069 // Add the names of overloadable operators.
4070#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4071 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00004072 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004073#include "clang/Basic/OperatorKinds.def"
4074
4075 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00004076 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004077 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004078 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4079 CodeCompleter->includeGlobals());
Douglas Gregor3545ff42009-09-21 16:56:56 +00004080
4081 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00004082 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004083 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004084
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004085 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor39982192010-08-15 06:18:01 +00004086 CodeCompletionContext::CCC_Type,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004087 Results.data(),Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00004088}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004089
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004090void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Alexis Hunt1d792652011-01-08 20:30:50 +00004091 CXXCtorInitializer** Initializers,
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004092 unsigned NumInitializers) {
Douglas Gregor75acd922011-09-27 23:30:47 +00004093 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004094 CXXConstructorDecl *Constructor
4095 = static_cast<CXXConstructorDecl *>(ConstructorD);
4096 if (!Constructor)
4097 return;
4098
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004099 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00004100 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004101 Results.EnterNewScope();
4102
4103 // Fill in any already-initialized fields or base classes.
4104 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4105 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4106 for (unsigned I = 0; I != NumInitializers; ++I) {
4107 if (Initializers[I]->isBaseInitializer())
4108 InitializedBases.insert(
4109 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4110 else
Francois Pichetd583da02010-12-04 09:14:42 +00004111 InitializedFields.insert(cast<FieldDecl>(
4112 Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004113 }
4114
4115 // Add completions for base classes.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004116 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor99129ef2010-08-29 19:27:27 +00004117 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004118 CXXRecordDecl *ClassDecl = Constructor->getParent();
4119 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4120 BaseEnd = ClassDecl->bases_end();
4121 Base != BaseEnd; ++Base) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004122 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4123 SawLastInitializer
4124 = NumInitializers > 0 &&
4125 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4126 Context.hasSameUnqualifiedType(Base->getType(),
4127 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004128 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004129 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004130
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004131 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004132 Results.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00004133 Base->getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004134 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4135 Builder.AddPlaceholderChunk("args");
4136 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4137 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004138 SawLastInitializer? CCP_NextInitializer
4139 : CCP_MemberDeclaration));
4140 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004141 }
4142
4143 // Add completions for virtual base classes.
4144 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4145 BaseEnd = ClassDecl->vbases_end();
4146 Base != BaseEnd; ++Base) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004147 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4148 SawLastInitializer
4149 = NumInitializers > 0 &&
4150 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4151 Context.hasSameUnqualifiedType(Base->getType(),
4152 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004153 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004154 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004155
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004156 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004157 Builder.getAllocator().CopyString(
John McCall31168b02011-06-15 23:02:42 +00004158 Base->getType().getAsString(Policy)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004159 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4160 Builder.AddPlaceholderChunk("args");
4161 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4162 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004163 SawLastInitializer? CCP_NextInitializer
4164 : CCP_MemberDeclaration));
4165 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004166 }
4167
4168 // Add completions for members.
4169 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4170 FieldEnd = ClassDecl->field_end();
4171 Field != FieldEnd; ++Field) {
Douglas Gregor99129ef2010-08-29 19:27:27 +00004172 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4173 SawLastInitializer
4174 = NumInitializers > 0 &&
Francois Pichetd583da02010-12-04 09:14:42 +00004175 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
4176 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004177 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00004178 }
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004179
4180 if (!Field->getDeclName())
4181 continue;
4182
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00004183 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004184 Field->getIdentifier()->getName()));
4185 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4186 Builder.AddPlaceholderChunk("args");
4187 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4188 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor99129ef2010-08-29 19:27:27 +00004189 SawLastInitializer? CCP_NextInitializer
Douglas Gregorf3af3112010-09-09 21:42:20 +00004190 : CCP_MemberDeclaration,
4191 CXCursor_MemberRef));
Douglas Gregor99129ef2010-08-29 19:27:27 +00004192 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004193 }
4194 Results.ExitScope();
4195
Douglas Gregor0ac41382010-09-23 23:01:17 +00004196 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00004197 Results.data(), Results.size());
4198}
4199
Douglas Gregord8c61782012-02-15 15:34:24 +00004200/// \brief Determine whether this scope denotes a namespace.
4201static bool isNamespaceScope(Scope *S) {
4202 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4203 if (!DC)
4204 return false;
4205
4206 return DC->isFileContext();
4207}
4208
4209void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4210 bool AfterAmpersand) {
4211 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4212 CodeCompletionContext::CCC_Other);
4213 Results.EnterNewScope();
4214
4215 // Note what has already been captured.
4216 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4217 bool IncludedThis = false;
4218 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4219 CEnd = Intro.Captures.end();
4220 C != CEnd; ++C) {
4221 if (C->Kind == LCK_This) {
4222 IncludedThis = true;
4223 continue;
4224 }
4225
4226 Known.insert(C->Id);
4227 }
4228
4229 // Look for other capturable variables.
4230 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4231 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4232 D != DEnd; ++D) {
4233 VarDecl *Var = dyn_cast<VarDecl>(*D);
4234 if (!Var ||
4235 !Var->hasLocalStorage() ||
4236 Var->hasAttr<BlocksAttr>())
4237 continue;
4238
4239 if (Known.insert(Var->getIdentifier()))
4240 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4241 }
4242 }
4243
4244 // Add 'this', if it would be valid.
4245 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4246 addThisCompletion(*this, Results);
4247
4248 Results.ExitScope();
4249
4250 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4251 Results.data(), Results.size());
4252}
4253
Douglas Gregorf1934162010-01-13 21:24:21 +00004254// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
4255// true or false.
4256#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004257static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004258 ResultBuilder &Results,
4259 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004260 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004261 // Since we have an implementation, we can end it.
Douglas Gregor78a21012010-01-14 16:01:26 +00004262 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004263
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004264 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf1934162010-01-13 21:24:21 +00004265 if (LangOpts.ObjC2) {
4266 // @dynamic
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004267 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
4268 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4269 Builder.AddPlaceholderChunk("property");
4270 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004271
4272 // @synthesize
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004273 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
4274 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4275 Builder.AddPlaceholderChunk("property");
4276 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004277 }
4278}
4279
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004280static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorf1934162010-01-13 21:24:21 +00004281 ResultBuilder &Results,
4282 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004283 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00004284
4285 // Since we have an interface or protocol, we can end it.
Douglas Gregor78a21012010-01-14 16:01:26 +00004286 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004287
4288 if (LangOpts.ObjC2) {
4289 // @property
Douglas Gregor78a21012010-01-14 16:01:26 +00004290 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004291
4292 // @required
Douglas Gregor78a21012010-01-14 16:01:26 +00004293 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004294
4295 // @optional
Douglas Gregor78a21012010-01-14 16:01:26 +00004296 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorf1934162010-01-13 21:24:21 +00004297 }
4298}
4299
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004300static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004301 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004302 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf1934162010-01-13 21:24:21 +00004303
4304 // @class name ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004305 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
4306 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4307 Builder.AddPlaceholderChunk("name");
4308 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004309
Douglas Gregorf4c33342010-05-28 00:22:41 +00004310 if (Results.includeCodePatterns()) {
4311 // @interface name
4312 // FIXME: Could introduce the whole pattern, including superclasses and
4313 // such.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004314 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
4315 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4316 Builder.AddPlaceholderChunk("class");
4317 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004318
Douglas Gregorf4c33342010-05-28 00:22:41 +00004319 // @protocol name
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004320 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4321 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4322 Builder.AddPlaceholderChunk("protocol");
4323 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004324
4325 // @implementation name
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004326 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
4327 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4328 Builder.AddPlaceholderChunk("class");
4329 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004330 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004331
4332 // @compatibility_alias name
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004333 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
4334 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4335 Builder.AddPlaceholderChunk("alias");
4336 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4337 Builder.AddPlaceholderChunk("class");
4338 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004339}
4340
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004341void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00004342 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004343 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4344 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00004345 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004346 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00004347 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004348 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00004349 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00004350 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004351 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00004352 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004353 HandleCodeCompleteResults(this, CodeCompleter,
4354 CodeCompletionContext::CCC_Other,
4355 Results.data(),Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00004356}
4357
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004358static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004359 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004360 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004361
4362 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004363 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00004364 if (Results.getSema().getLangOpts().CPlusPlus ||
4365 Results.getSema().getLangOpts().ConstStrings)
Douglas Gregore5c79d52011-10-18 21:20:17 +00004366 EncodeType = " const char[]";
4367 Builder.AddResultTypeChunk(EncodeType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004368 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
4369 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4370 Builder.AddPlaceholderChunk("type-name");
4371 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4372 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004373
4374 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004375 Builder.AddResultTypeChunk("Protocol *");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004376 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
4377 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4378 Builder.AddPlaceholderChunk("protocol-name");
4379 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4380 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004381
4382 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00004383 Builder.AddResultTypeChunk("SEL");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004384 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
4385 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4386 Builder.AddPlaceholderChunk("selector");
4387 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4388 Results.AddResult(Result(Builder.TakeString()));
Ted Kremeneke65b0862012-03-06 20:05:56 +00004389
4390 // @[ objects, ... ]
4391 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,[));
4392 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4393 Builder.AddPlaceholderChunk("objects, ...");
4394 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4395 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4396 Results.AddResult(Result(Builder.TakeString()));
4397
4398 // @{ key : object, ... }
4399 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,{));
4400 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4401 Builder.AddPlaceholderChunk("key");
4402 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4403 Builder.AddChunk(CodeCompletionString::CK_Colon);
4404 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4405 Builder.AddPlaceholderChunk("object, ...");
4406 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4407 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4408 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004409}
4410
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004411static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004412 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004413 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf1934162010-01-13 21:24:21 +00004414
Douglas Gregorf4c33342010-05-28 00:22:41 +00004415 if (Results.includeCodePatterns()) {
4416 // @try { statements } @catch ( declaration ) { statements } @finally
4417 // { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004418 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
4419 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4420 Builder.AddPlaceholderChunk("statements");
4421 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4422 Builder.AddTextChunk("@catch");
4423 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4424 Builder.AddPlaceholderChunk("parameter");
4425 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4426 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4427 Builder.AddPlaceholderChunk("statements");
4428 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4429 Builder.AddTextChunk("@finally");
4430 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4431 Builder.AddPlaceholderChunk("statements");
4432 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4433 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004434 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004435
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004436 // @throw
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004437 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
4438 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4439 Builder.AddPlaceholderChunk("expression");
4440 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf1934162010-01-13 21:24:21 +00004441
Douglas Gregorf4c33342010-05-28 00:22:41 +00004442 if (Results.includeCodePatterns()) {
4443 // @synchronized ( expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004444 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
4445 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4446 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4447 Builder.AddPlaceholderChunk("expression");
4448 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4449 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4450 Builder.AddPlaceholderChunk("statements");
4451 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4452 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00004453 }
Douglas Gregorf1934162010-01-13 21:24:21 +00004454}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004455
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004456static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregor48d46252010-01-13 21:54:15 +00004457 ResultBuilder &Results,
4458 bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00004459 typedef CodeCompletionResult Result;
Douglas Gregor78a21012010-01-14 16:01:26 +00004460 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
4461 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
4462 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregor48d46252010-01-13 21:54:15 +00004463 if (LangOpts.ObjC2)
Douglas Gregor78a21012010-01-14 16:01:26 +00004464 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregor48d46252010-01-13 21:54:15 +00004465}
4466
4467void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004468 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4469 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00004470 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00004471 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00004472 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004473 HandleCodeCompleteResults(this, CodeCompleter,
4474 CodeCompletionContext::CCC_Other,
4475 Results.data(),Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00004476}
4477
4478void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004479 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4480 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00004481 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004482 AddObjCStatementResults(Results, false);
4483 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004484 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004485 HandleCodeCompleteResults(this, CodeCompleter,
4486 CodeCompletionContext::CCC_Other,
4487 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004488}
4489
4490void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004491 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4492 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004493 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00004494 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004495 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004496 HandleCodeCompleteResults(this, CodeCompleter,
4497 CodeCompletionContext::CCC_Other,
4498 Results.data(),Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00004499}
4500
Douglas Gregore6078da2009-11-19 00:14:45 +00004501/// \brief Determine whether the addition of the given flag to an Objective-C
4502/// property's attributes will cause a conflict.
4503static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4504 // Check if we've already added this flag.
4505 if (Attributes & NewFlag)
4506 return true;
4507
4508 Attributes |= NewFlag;
4509
4510 // Check for collisions with "readonly".
4511 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4512 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4513 ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00004514 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00004515 ObjCDeclSpec::DQ_PR_copy |
John McCall31168b02011-06-15 23:02:42 +00004516 ObjCDeclSpec::DQ_PR_retain |
4517 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregore6078da2009-11-19 00:14:45 +00004518 return true;
4519
John McCall31168b02011-06-15 23:02:42 +00004520 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregore6078da2009-11-19 00:14:45 +00004521 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCall31168b02011-06-15 23:02:42 +00004522 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregore6078da2009-11-19 00:14:45 +00004523 ObjCDeclSpec::DQ_PR_copy |
John McCall31168b02011-06-15 23:02:42 +00004524 ObjCDeclSpec::DQ_PR_retain|
4525 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregore6078da2009-11-19 00:14:45 +00004526 if (AssignCopyRetMask &&
4527 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00004528 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00004529 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00004530 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4531 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregore6078da2009-11-19 00:14:45 +00004532 return true;
4533
4534 return false;
4535}
4536
Douglas Gregor36029f42009-11-18 23:08:07 +00004537void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00004538 if (!CodeCompleter)
4539 return;
Douglas Gregor1b605f72009-11-19 01:08:35 +00004540
Steve Naroff936354c2009-10-08 21:55:05 +00004541 unsigned Attributes = ODS.getPropertyAttributes();
4542
John McCall276321a2010-08-25 06:19:51 +00004543 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004544 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4545 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00004546 Results.EnterNewScope();
Douglas Gregore6078da2009-11-19 00:14:45 +00004547 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00004548 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004549 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00004550 Results.AddResult(CodeCompletionResult("assign"));
John McCall31168b02011-06-15 23:02:42 +00004551 if (!ObjCPropertyFlagConflicts(Attributes,
4552 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4553 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004554 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00004555 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004556 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00004557 Results.AddResult(CodeCompletionResult("retain"));
John McCall31168b02011-06-15 23:02:42 +00004558 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4559 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004560 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00004561 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004562 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00004563 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00004564 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4565 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregore6078da2009-11-19 00:14:45 +00004566 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004567 CodeCompletionBuilder Setter(Results.getAllocator());
4568 Setter.AddTypedTextChunk("setter");
4569 Setter.AddTextChunk(" = ");
4570 Setter.AddPlaceholderChunk("method");
4571 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00004572 }
Douglas Gregore6078da2009-11-19 00:14:45 +00004573 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004574 CodeCompletionBuilder Getter(Results.getAllocator());
4575 Getter.AddTypedTextChunk("getter");
4576 Getter.AddTextChunk(" = ");
4577 Getter.AddPlaceholderChunk("method");
4578 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00004579 }
Steve Naroff936354c2009-10-08 21:55:05 +00004580 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004581 HandleCodeCompleteResults(this, CodeCompleter,
4582 CodeCompletionContext::CCC_Other,
4583 Results.data(),Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00004584}
Steve Naroffeae65032009-11-07 02:08:14 +00004585
Douglas Gregorc8537c52009-11-19 07:41:15 +00004586/// \brief Descripts the kind of Objective-C method that we want to find
4587/// via code completion.
4588enum ObjCMethodKind {
4589 MK_Any, //< Any kind of method, provided it means other specified criteria.
4590 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4591 MK_OneArgSelector //< One-argument selector.
4592};
4593
Douglas Gregor67c692c2010-08-26 15:07:07 +00004594static bool isAcceptableObjCSelector(Selector Sel,
4595 ObjCMethodKind WantKind,
4596 IdentifierInfo **SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004597 unsigned NumSelIdents,
4598 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00004599 if (NumSelIdents > Sel.getNumArgs())
4600 return false;
4601
4602 switch (WantKind) {
4603 case MK_Any: break;
4604 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4605 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4606 }
4607
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004608 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4609 return false;
4610
Douglas Gregor67c692c2010-08-26 15:07:07 +00004611 for (unsigned I = 0; I != NumSelIdents; ++I)
4612 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4613 return false;
4614
4615 return true;
4616}
4617
Douglas Gregorc8537c52009-11-19 07:41:15 +00004618static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4619 ObjCMethodKind WantKind,
4620 IdentifierInfo **SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004621 unsigned NumSelIdents,
4622 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00004623 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004624 NumSelIdents, AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004625}
Douglas Gregor1154e272010-09-16 16:06:31 +00004626
4627namespace {
4628 /// \brief A set of selectors, which is used to avoid introducing multiple
4629 /// completions with the same selector into the result set.
4630 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4631}
4632
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004633/// \brief Add all of the Objective-C methods in the given Objective-C
4634/// container to the set of results.
4635///
4636/// The container will be a class, protocol, category, or implementation of
4637/// any of the above. This mether will recurse to include methods from
4638/// the superclasses of classes along with their categories, protocols, and
4639/// implementations.
4640///
4641/// \param Container the container in which we'll look to find methods.
4642///
4643/// \param WantInstance whether to add instance methods (only); if false, this
4644/// routine will add factory methods (only).
4645///
4646/// \param CurContext the context in which we're performing the lookup that
4647/// finds methods.
4648///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004649/// \param AllowSameLength Whether we allow a method to be added to the list
4650/// when it has the same number of parameters as we have selector identifiers.
4651///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004652/// \param Results the structure into which we'll add results.
4653static void AddObjCMethods(ObjCContainerDecl *Container,
4654 bool WantInstanceMethods,
Douglas Gregorc8537c52009-11-19 07:41:15 +00004655 ObjCMethodKind WantKind,
Douglas Gregor1b605f72009-11-19 01:08:35 +00004656 IdentifierInfo **SelIdents,
4657 unsigned NumSelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004658 DeclContext *CurContext,
Douglas Gregor1154e272010-09-16 16:06:31 +00004659 VisitedSelectorSet &Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004660 bool AllowSameLength,
Douglas Gregor416b5752010-08-25 01:08:01 +00004661 ResultBuilder &Results,
4662 bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00004663 typedef CodeCompletionResult Result;
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004664 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4665 MEnd = Container->meth_end();
4666 M != MEnd; ++M) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00004667 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4668 // Check whether the selector identifiers we've been given are a
4669 // subset of the identifiers for this particular method.
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004670 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4671 AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00004672 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004673
Douglas Gregor1154e272010-09-16 16:06:31 +00004674 if (!Selectors.insert((*M)->getSelector()))
4675 continue;
4676
Douglas Gregor1b605f72009-11-19 01:08:35 +00004677 Result R = Result(*M, 0);
4678 R.StartParameter = NumSelIdents;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004679 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00004680 if (!InOriginalClass)
4681 R.Priority += CCD_InBaseClass;
Douglas Gregor1b605f72009-11-19 01:08:35 +00004682 Results.MaybeAddResult(R, CurContext);
4683 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004684 }
4685
Douglas Gregorf37c9492010-09-16 15:34:59 +00004686 // Visit the protocols of protocols.
4687 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00004688 if (Protocol->hasDefinition()) {
4689 const ObjCList<ObjCProtocolDecl> &Protocols
4690 = Protocol->getReferencedProtocols();
4691 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4692 E = Protocols.end();
4693 I != E; ++I)
4694 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4695 NumSelIdents, CurContext, Selectors, AllowSameLength,
4696 Results, false);
4697 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00004698 }
4699
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004700 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00004701 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004702 return;
4703
4704 // Add methods in protocols.
Argyrios Kyrtzidise7f3ef32012-03-13 01:09:41 +00004705 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4706 E = IFace->protocol_end();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004707 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00004708 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004709 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004710
4711 // Add methods in categories.
4712 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4713 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00004714 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004715 NumSelIdents, CurContext, Selectors, AllowSameLength,
4716 Results, InOriginalClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004717
4718 // Add a categories protocol methods.
4719 const ObjCList<ObjCProtocolDecl> &Protocols
4720 = CatDecl->getReferencedProtocols();
4721 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4722 E = Protocols.end();
4723 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00004724 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004725 NumSelIdents, CurContext, Selectors, AllowSameLength,
4726 Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004727
4728 // Add methods in category implementations.
4729 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004730 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004731 NumSelIdents, CurContext, Selectors, AllowSameLength,
4732 Results, InOriginalClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004733 }
4734
4735 // Add methods in superclass.
4736 if (IFace->getSuperClass())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004737 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004738 SelIdents, NumSelIdents, CurContext, Selectors,
4739 AllowSameLength, Results, false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004740
4741 // Add methods in our implementation, if any.
4742 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregorc8537c52009-11-19 07:41:15 +00004743 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004744 NumSelIdents, CurContext, Selectors, AllowSameLength,
4745 Results, InOriginalClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004746}
4747
4748
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004749void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00004750 typedef CodeCompletionResult Result;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004751
4752 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004753 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004754 if (!Class) {
4755 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004756 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00004757 Class = Category->getClassInterface();
4758
4759 if (!Class)
4760 return;
4761 }
4762
4763 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004764 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4765 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004766 Results.EnterNewScope();
4767
Douglas Gregor1154e272010-09-16 16:06:31 +00004768 VisitedSelectorSet Selectors;
4769 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004770 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004771 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004772 HandleCodeCompleteResults(this, CodeCompleter,
4773 CodeCompletionContext::CCC_Other,
4774 Results.data(),Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00004775}
4776
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004777void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00004778 typedef CodeCompletionResult Result;
Douglas Gregorc8537c52009-11-19 07:41:15 +00004779
4780 // Try to find the interface where setters might live.
4781 ObjCInterfaceDecl *Class
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004782 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004783 if (!Class) {
4784 if (ObjCCategoryDecl *Category
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00004785 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00004786 Class = Category->getClassInterface();
4787
4788 if (!Class)
4789 return;
4790 }
4791
4792 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004793 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4794 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004795 Results.EnterNewScope();
4796
Douglas Gregor1154e272010-09-16 16:06:31 +00004797 VisitedSelectorSet Selectors;
4798 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00004799 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00004800
4801 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004802 HandleCodeCompleteResults(this, CodeCompleter,
4803 CodeCompletionContext::CCC_Other,
4804 Results.data(),Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00004805}
4806
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004807void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4808 bool IsParameter) {
John McCall276321a2010-08-25 06:19:51 +00004809 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004810 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4811 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00004812 Results.EnterNewScope();
4813
4814 // Add context-sensitive, Objective-C parameter-passing keywords.
4815 bool AddedInOut = false;
4816 if ((DS.getObjCDeclQualifier() &
4817 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4818 Results.AddResult("in");
4819 Results.AddResult("inout");
4820 AddedInOut = true;
4821 }
4822 if ((DS.getObjCDeclQualifier() &
4823 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4824 Results.AddResult("out");
4825 if (!AddedInOut)
4826 Results.AddResult("inout");
4827 }
4828 if ((DS.getObjCDeclQualifier() &
4829 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4830 ObjCDeclSpec::DQ_Oneway)) == 0) {
4831 Results.AddResult("bycopy");
4832 Results.AddResult("byref");
4833 Results.AddResult("oneway");
4834 }
4835
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004836 // If we're completing the return type of an Objective-C method and the
4837 // identifier IBAction refers to a macro, provide a completion item for
4838 // an action, e.g.,
4839 // IBAction)<#selector#>:(id)sender
4840 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4841 Context.Idents.get("IBAction").hasMacroDefinition()) {
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004842 CodeCompletionBuilder Builder(Results.getAllocator(), CCP_CodePattern,
4843 CXAvailability_Available);
4844 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00004845 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004846 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00004847 Builder.AddChunk(CodeCompletionString::CK_Colon);
4848 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004849 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00004850 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00004851 Builder.AddTextChunk("sender");
4852 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4853 }
4854
Douglas Gregor99fa2642010-08-24 01:06:58 +00004855 // Add various builtin type names and specifiers.
4856 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4857 Results.ExitScope();
4858
4859 // Add the various type names
4860 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4861 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4862 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4863 CodeCompleter->includeGlobals());
4864
4865 if (CodeCompleter->includeMacros())
4866 AddMacroResults(PP, Results);
4867
4868 HandleCodeCompleteResults(this, CodeCompleter,
4869 CodeCompletionContext::CCC_Type,
4870 Results.data(), Results.size());
4871}
4872
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004873/// \brief When we have an expression with type "id", we may assume
4874/// that it has some more-specific class type based on knowledge of
4875/// common uses of Objective-C. This routine returns that class type,
4876/// or NULL if no better result could be determined.
4877static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregored0b69d2010-09-15 16:23:04 +00004878 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004879 if (!Msg)
4880 return 0;
4881
4882 Selector Sel = Msg->getSelector();
4883 if (Sel.isNull())
4884 return 0;
4885
4886 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4887 if (!Id)
4888 return 0;
4889
4890 ObjCMethodDecl *Method = Msg->getMethodDecl();
4891 if (!Method)
4892 return 0;
4893
4894 // Determine the class that we're sending the message to.
Douglas Gregor9a129192010-04-21 00:45:42 +00004895 ObjCInterfaceDecl *IFace = 0;
4896 switch (Msg->getReceiverKind()) {
4897 case ObjCMessageExpr::Class:
John McCall8b07ec22010-05-15 11:32:37 +00004898 if (const ObjCObjectType *ObjType
4899 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4900 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00004901 break;
4902
4903 case ObjCMessageExpr::Instance: {
4904 QualType T = Msg->getInstanceReceiver()->getType();
4905 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4906 IFace = Ptr->getInterfaceDecl();
4907 break;
4908 }
4909
4910 case ObjCMessageExpr::SuperInstance:
4911 case ObjCMessageExpr::SuperClass:
4912 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004913 }
4914
4915 if (!IFace)
4916 return 0;
4917
4918 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4919 if (Method->isInstanceMethod())
4920 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4921 .Case("retain", IFace)
John McCall31168b02011-06-15 23:02:42 +00004922 .Case("strong", IFace)
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00004923 .Case("autorelease", IFace)
4924 .Case("copy", IFace)
4925 .Case("copyWithZone", IFace)
4926 .Case("mutableCopy", IFace)
4927 .Case("mutableCopyWithZone", IFace)
4928 .Case("awakeFromCoder", IFace)
4929 .Case("replacementObjectFromCoder", IFace)
4930 .Case("class", IFace)
4931 .Case("classForCoder", IFace)
4932 .Case("superclass", Super)
4933 .Default(0);
4934
4935 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4936 .Case("new", IFace)
4937 .Case("alloc", IFace)
4938 .Case("allocWithZone", IFace)
4939 .Case("class", IFace)
4940 .Case("superclass", Super)
4941 .Default(0);
4942}
4943
Douglas Gregor6fc04132010-08-27 15:10:57 +00004944// Add a special completion for a message send to "super", which fills in the
4945// most likely case of forwarding all of our arguments to the superclass
4946// function.
4947///
4948/// \param S The semantic analysis object.
4949///
4950/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4951/// the "super" keyword. Otherwise, we just need to provide the arguments.
4952///
4953/// \param SelIdents The identifiers in the selector that have already been
4954/// provided as arguments for a send to "super".
4955///
4956/// \param NumSelIdents The number of identifiers in \p SelIdents.
4957///
4958/// \param Results The set of results to augment.
4959///
4960/// \returns the Objective-C method declaration that would be invoked by
4961/// this "super" completion. If NULL, no completion was added.
4962static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4963 IdentifierInfo **SelIdents,
4964 unsigned NumSelIdents,
4965 ResultBuilder &Results) {
4966 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4967 if (!CurMethod)
4968 return 0;
4969
4970 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4971 if (!Class)
4972 return 0;
4973
4974 // Try to find a superclass method with the same selector.
4975 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00004976 while ((Class = Class->getSuperClass()) && !SuperMethod) {
4977 // Check in the class
Douglas Gregor6fc04132010-08-27 15:10:57 +00004978 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4979 CurMethod->isInstanceMethod());
4980
Douglas Gregorb5f1e462011-02-16 00:51:18 +00004981 // Check in categories or class extensions.
4982 if (!SuperMethod) {
4983 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
4984 Category = Category->getNextClassCategory())
4985 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
4986 CurMethod->isInstanceMethod())))
4987 break;
4988 }
4989 }
4990
Douglas Gregor6fc04132010-08-27 15:10:57 +00004991 if (!SuperMethod)
4992 return 0;
4993
4994 // Check whether the superclass method has the same signature.
4995 if (CurMethod->param_size() != SuperMethod->param_size() ||
4996 CurMethod->isVariadic() != SuperMethod->isVariadic())
4997 return 0;
4998
4999 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5000 CurPEnd = CurMethod->param_end(),
5001 SuperP = SuperMethod->param_begin();
5002 CurP != CurPEnd; ++CurP, ++SuperP) {
5003 // Make sure the parameter types are compatible.
5004 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5005 (*SuperP)->getType()))
5006 return 0;
5007
5008 // Make sure we have a parameter name to forward!
5009 if (!(*CurP)->getIdentifier())
5010 return 0;
5011 }
5012
5013 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005014 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor6fc04132010-08-27 15:10:57 +00005015
5016 // Give this completion a return type.
Douglas Gregor75acd922011-09-27 23:30:47 +00005017 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5018 Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005019
5020 // If we need the "super" keyword, add it (plus some spacing).
5021 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005022 Builder.AddTypedTextChunk("super");
5023 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005024 }
5025
5026 Selector Sel = CurMethod->getSelector();
5027 if (Sel.isUnarySelector()) {
5028 if (NeedSuperKeyword)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005029 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005030 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005031 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005032 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005033 Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005034 } else {
5035 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5036 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5037 if (I > NumSelIdents)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005038 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00005039
5040 if (I < NumSelIdents)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005041 Builder.AddInformativeChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005042 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005043 Sel.getNameForSlot(I) + ":"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005044 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005045 Builder.AddTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005046 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005047 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005048 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005049 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005050 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005051 Builder.AddTypedTextChunk(
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005052 Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005053 Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005054 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005055 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005056 }
5057 }
5058 }
5059
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005060 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor6fc04132010-08-27 15:10:57 +00005061 SuperMethod->isInstanceMethod()
5062 ? CXCursor_ObjCInstanceMethodDecl
5063 : CXCursor_ObjCClassMethodDecl));
5064 return SuperMethod;
5065}
5066
Douglas Gregora817a192010-05-27 23:06:34 +00005067void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005068 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005069 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5070 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikiebbafb8a2012-03-11 07:00:24 +00005071 getLangOpts().CPlusPlus0x
Douglas Gregord8c61782012-02-15 15:34:24 +00005072 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5073 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregora817a192010-05-27 23:06:34 +00005074
Douglas Gregora817a192010-05-27 23:06:34 +00005075 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5076 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00005077 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5078 CodeCompleter->includeGlobals());
Douglas Gregora817a192010-05-27 23:06:34 +00005079
5080 // If we are in an Objective-C method inside a class that has a superclass,
5081 // add "super" as an option.
5082 if (ObjCMethodDecl *Method = getCurMethodDecl())
5083 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00005084 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00005085 Results.AddResult(Result("super"));
Douglas Gregor6fc04132010-08-27 15:10:57 +00005086
5087 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5088 }
Douglas Gregora817a192010-05-27 23:06:34 +00005089
David Blaikiebbafb8a2012-03-11 07:00:24 +00005090 if (getLangOpts().CPlusPlus0x)
Douglas Gregord8c61782012-02-15 15:34:24 +00005091 addThisCompletion(*this, Results);
5092
Douglas Gregora817a192010-05-27 23:06:34 +00005093 Results.ExitScope();
5094
5095 if (CodeCompleter->includeMacros())
5096 AddMacroResults(PP, Results);
Douglas Gregor50832e02010-09-20 22:39:41 +00005097 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005098 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00005099
5100}
5101
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005102void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5103 IdentifierInfo **SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005104 unsigned NumSelIdents,
5105 bool AtArgumentExpression) {
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005106 ObjCInterfaceDecl *CDecl = 0;
5107 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5108 // Figure out which interface we're in.
5109 CDecl = CurMethod->getClassInterface();
5110 if (!CDecl)
5111 return;
5112
5113 // Find the superclass of this class.
5114 CDecl = CDecl->getSuperClass();
5115 if (!CDecl)
5116 return;
5117
5118 if (CurMethod->isInstanceMethod()) {
5119 // We are inside an instance method, which means that the message
5120 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00005121 // current object.
5122 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor6fc04132010-08-27 15:10:57 +00005123 SelIdents, NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005124 AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005125 CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005126 }
5127
5128 // Fall through to send to the superclass in CDecl.
5129 } else {
5130 // "super" may be the name of a type or variable. Figure out which
5131 // it is.
5132 IdentifierInfo *Super = &Context.Idents.get("super");
5133 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5134 LookupOrdinaryName);
5135 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5136 // "super" names an interface. Use it.
5137 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCall8b07ec22010-05-15 11:32:37 +00005138 if (const ObjCObjectType *Iface
5139 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5140 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005141 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5142 // "super" names an unresolved type; we can't be more specific.
5143 } else {
5144 // Assume that "super" names some kind of value and parse that way.
5145 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00005146 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005147 UnqualifiedId id;
5148 id.setIdentifier(Super, SuperLoc);
Abramo Bagnara7945c982012-01-27 09:46:47 +00005149 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5150 false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005151 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005152 SelIdents, NumSelIdents,
5153 AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005154 }
5155
5156 // Fall through
5157 }
5158
John McCallba7bf592010-08-24 05:47:05 +00005159 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005160 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00005161 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005162 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005163 NumSelIdents, AtArgumentExpression,
5164 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005165}
5166
Douglas Gregor74661272010-09-21 00:03:25 +00005167/// \brief Given a set of code-completion results for the argument of a message
5168/// send, determine the preferred type (if any) for that argument expression.
5169static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5170 unsigned NumSelIdents) {
5171 typedef CodeCompletionResult Result;
5172 ASTContext &Context = Results.getSema().Context;
5173
5174 QualType PreferredType;
5175 unsigned BestPriority = CCP_Unlikely * 2;
5176 Result *ResultsData = Results.data();
5177 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5178 Result &R = ResultsData[I];
5179 if (R.Kind == Result::RK_Declaration &&
5180 isa<ObjCMethodDecl>(R.Declaration)) {
5181 if (R.Priority <= BestPriority) {
5182 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5183 if (NumSelIdents <= Method->param_size()) {
5184 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5185 ->getType();
5186 if (R.Priority < BestPriority || PreferredType.isNull()) {
5187 BestPriority = R.Priority;
5188 PreferredType = MyPreferredType;
5189 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5190 MyPreferredType)) {
5191 PreferredType = QualType();
5192 }
5193 }
5194 }
5195 }
5196 }
5197
5198 return PreferredType;
5199}
5200
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005201static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5202 ParsedType Receiver,
5203 IdentifierInfo **SelIdents,
5204 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005205 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005206 bool IsSuper,
5207 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005208 typedef CodeCompletionResult Result;
Douglas Gregor8ce33212009-11-17 17:59:40 +00005209 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005210
Douglas Gregor8ce33212009-11-17 17:59:40 +00005211 // If the given name refers to an interface type, retrieve the
5212 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005213 if (Receiver) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005214 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005215 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00005216 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5217 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00005218 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005219
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005220 // Add all of the factory methods in this Objective-C class, its protocols,
5221 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00005222 Results.EnterNewScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005223
Douglas Gregor6fc04132010-08-27 15:10:57 +00005224 // If this is a send-to-super, try to add the special "super" send
5225 // completion.
5226 if (IsSuper) {
5227 if (ObjCMethodDecl *SuperMethod
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005228 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5229 Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00005230 Results.Ignore(SuperMethod);
5231 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005232
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005233 // If we're inside an Objective-C method definition, prefer its selector to
5234 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005235 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005236 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005237
Douglas Gregor1154e272010-09-16 16:06:31 +00005238 VisitedSelectorSet Selectors;
Douglas Gregor6285f752010-04-06 16:40:00 +00005239 if (CDecl)
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005240 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005241 SemaRef.CurContext, Selectors, AtArgumentExpression,
5242 Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00005243 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00005244 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005245
Douglas Gregord720daf2010-04-06 17:30:22 +00005246 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005247 // pool from the AST file.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005248 if (SemaRef.ExternalSource) {
5249 for (uint32_t I = 0,
5250 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00005251 I != N; ++I) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005252 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5253 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005254 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005255
5256 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00005257 }
5258 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005259
5260 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5261 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00005262 M != MEnd; ++M) {
5263 for (ObjCMethodList *MethList = &M->second.second;
5264 MethList && MethList->Method;
Douglas Gregor6285f752010-04-06 16:40:00 +00005265 MethList = MethList->Next) {
5266 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5267 NumSelIdents))
5268 continue;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005269
Douglas Gregor6285f752010-04-06 16:40:00 +00005270 Result R(MethList->Method, 0);
5271 R.StartParameter = NumSelIdents;
5272 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005273 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00005274 }
5275 }
5276 }
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005277
5278 Results.ExitScope();
5279}
Douglas Gregor6285f752010-04-06 16:40:00 +00005280
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005281void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5282 IdentifierInfo **SelIdents,
5283 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005284 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00005285 bool IsSuper) {
Douglas Gregor63745d52011-07-21 01:05:26 +00005286
5287 QualType T = this->GetTypeFromParser(Receiver);
5288
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005289 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor63745d52011-07-21 01:05:26 +00005290 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregorea777402011-07-26 15:24:30 +00005291 T, SelIdents, NumSelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00005292
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005293 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5294 AtArgumentExpression, IsSuper, Results);
Douglas Gregor74661272010-09-21 00:03:25 +00005295
5296 // If we're actually at the argument expression (rather than prior to the
5297 // selector), we're actually performing code completion for an expression.
5298 // Determine whether we have a single, best method. If so, we can
5299 // code-complete the expression using the corresponding parameter type as
5300 // our preferred type, improving completion results.
5301 if (AtArgumentExpression) {
5302 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregor63745d52011-07-21 01:05:26 +00005303 NumSelIdents);
Douglas Gregor74661272010-09-21 00:03:25 +00005304 if (PreferredType.isNull())
5305 CodeCompleteOrdinaryName(S, PCC_Expression);
5306 else
5307 CodeCompleteExpression(S, PreferredType);
5308 return;
5309 }
5310
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005311 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00005312 Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00005313 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00005314}
5315
Richard Trieu2bd04012011-09-09 02:00:50 +00005316void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregor1b605f72009-11-19 01:08:35 +00005317 IdentifierInfo **SelIdents,
Douglas Gregor6fc04132010-08-27 15:10:57 +00005318 unsigned NumSelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00005319 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00005320 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00005321 typedef CodeCompletionResult Result;
Steve Naroffeae65032009-11-07 02:08:14 +00005322
5323 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffeae65032009-11-07 02:08:14 +00005324
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005325 // If necessary, apply function/array conversion to the receiver.
5326 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00005327 if (RecExpr) {
5328 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5329 if (Conv.isInvalid()) // conversion failed. bail.
5330 return;
5331 RecExpr = Conv.take();
5332 }
Douglas Gregor392a84b2010-10-13 21:24:53 +00005333 QualType ReceiverType = RecExpr? RecExpr->getType()
5334 : Super? Context.getObjCObjectPointerType(
5335 Context.getObjCInterfaceType(Super))
5336 : Context.getObjCIdType();
Steve Naroffeae65032009-11-07 02:08:14 +00005337
Douglas Gregordc520b02010-11-08 21:12:30 +00005338 // If we're messaging an expression with type "id" or "Class", check
5339 // whether we know something special about the receiver that allows
5340 // us to assume a more-specific receiver type.
5341 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5342 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5343 if (ReceiverType->isObjCClassType())
5344 return CodeCompleteObjCClassMessage(S,
5345 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5346 SelIdents, NumSelIdents,
5347 AtArgumentExpression, Super);
5348
5349 ReceiverType = Context.getObjCObjectPointerType(
5350 Context.getObjCInterfaceType(IFace));
5351 }
5352
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005353 // Build the set of methods we can see.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005354 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor63745d52011-07-21 01:05:26 +00005355 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregorea777402011-07-26 15:24:30 +00005356 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregor63745d52011-07-21 01:05:26 +00005357
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005358 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005359
Douglas Gregor6fc04132010-08-27 15:10:57 +00005360 // If this is a send-to-super, try to add the special "super" send
5361 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00005362 if (Super) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00005363 if (ObjCMethodDecl *SuperMethod
5364 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5365 Results))
5366 Results.Ignore(SuperMethod);
5367 }
5368
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00005369 // If we're inside an Objective-C method definition, prefer its selector to
5370 // others.
5371 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5372 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005373
Douglas Gregor1154e272010-09-16 16:06:31 +00005374 // Keep track of the selectors we've already added.
5375 VisitedSelectorSet Selectors;
5376
Douglas Gregora3329fa2009-11-18 00:06:18 +00005377 // Handle messages to Class. This really isn't a message to an instance
5378 // method, so we treat it the same way we would treat a message send to a
5379 // class method.
5380 if (ReceiverType->isObjCClassType() ||
5381 ReceiverType->isObjCQualifiedClassType()) {
5382 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5383 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregorc8537c52009-11-19 07:41:15 +00005384 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005385 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005386 }
5387 }
5388 // Handle messages to a qualified ID ("id<foo>").
5389 else if (const ObjCObjectPointerType *QualID
5390 = ReceiverType->getAsObjCQualifiedIdType()) {
5391 // Search protocols for instance methods.
5392 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5393 E = QualID->qual_end();
5394 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00005395 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005396 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005397 }
5398 // Handle messages to a pointer to interface type.
5399 else if (const ObjCObjectPointerType *IFacePtr
5400 = ReceiverType->getAsObjCInterfacePointerType()) {
5401 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005402 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005403 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5404 Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005405
5406 // Search protocols for instance methods.
5407 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5408 E = IFacePtr->qual_end();
5409 I != E; ++I)
Douglas Gregorc8537c52009-11-19 07:41:15 +00005410 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005411 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00005412 }
Douglas Gregor6285f752010-04-06 16:40:00 +00005413 // Handle messages to "id".
5414 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00005415 // We're messaging "id", so provide all instance methods we know
5416 // about as code-completion results.
5417
5418 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00005419 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00005420 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00005421 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5422 I != N; ++I) {
5423 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00005424 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00005425 continue;
5426
Sebastian Redl75d8a322010-08-02 23:18:59 +00005427 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00005428 }
5429 }
5430
Sebastian Redl75d8a322010-08-02 23:18:59 +00005431 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5432 MEnd = MethodPool.end();
5433 M != MEnd; ++M) {
5434 for (ObjCMethodList *MethList = &M->second.first;
5435 MethList && MethList->Method;
Douglas Gregor6285f752010-04-06 16:40:00 +00005436 MethList = MethList->Next) {
5437 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5438 NumSelIdents))
5439 continue;
Douglas Gregor1154e272010-09-16 16:06:31 +00005440
5441 if (!Selectors.insert(MethList->Method->getSelector()))
5442 continue;
5443
Douglas Gregor6285f752010-04-06 16:40:00 +00005444 Result R(MethList->Method, 0);
5445 R.StartParameter = NumSelIdents;
5446 R.AllParametersAreInformative = false;
5447 Results.MaybeAddResult(R, CurContext);
5448 }
5449 }
5450 }
Steve Naroffeae65032009-11-07 02:08:14 +00005451 Results.ExitScope();
Douglas Gregor74661272010-09-21 00:03:25 +00005452
5453
5454 // If we're actually at the argument expression (rather than prior to the
5455 // selector), we're actually performing code completion for an expression.
5456 // Determine whether we have a single, best method. If so, we can
5457 // code-complete the expression using the corresponding parameter type as
5458 // our preferred type, improving completion results.
5459 if (AtArgumentExpression) {
5460 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5461 NumSelIdents);
5462 if (PreferredType.isNull())
5463 CodeCompleteOrdinaryName(S, PCC_Expression);
5464 else
5465 CodeCompleteExpression(S, PreferredType);
5466 return;
5467 }
5468
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005469 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor63745d52011-07-21 01:05:26 +00005470 Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005471 Results.data(),Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00005472}
Douglas Gregorbaf69612009-11-18 04:19:12 +00005473
Douglas Gregor68762e72010-08-23 21:17:50 +00005474void Sema::CodeCompleteObjCForCollection(Scope *S,
5475 DeclGroupPtrTy IterationVar) {
5476 CodeCompleteExpressionData Data;
5477 Data.ObjCCollection = true;
5478
5479 if (IterationVar.getAsOpaquePtr()) {
5480 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5481 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5482 if (*I)
5483 Data.IgnoreDecls.push_back(*I);
5484 }
5485 }
5486
5487 CodeCompleteExpression(S, Data);
5488}
5489
Douglas Gregor67c692c2010-08-26 15:07:07 +00005490void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5491 unsigned NumSelIdents) {
5492 // If we have an external source, load the entire class method
5493 // pool from the AST file.
5494 if (ExternalSource) {
5495 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5496 I != N; ++I) {
5497 Selector Sel = ExternalSource->GetExternalSelector(I);
5498 if (Sel.isNull() || MethodPool.count(Sel))
5499 continue;
5500
5501 ReadMethodPool(Sel);
5502 }
5503 }
5504
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005505 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5506 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00005507 Results.EnterNewScope();
5508 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5509 MEnd = MethodPool.end();
5510 M != MEnd; ++M) {
5511
5512 Selector Sel = M->first;
5513 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5514 continue;
5515
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005516 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005517 if (Sel.isUnarySelector()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005518 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00005519 Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005520 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005521 continue;
5522 }
5523
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005524 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005525 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005526 if (I == NumSelIdents) {
5527 if (!Accumulator.empty()) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005528 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005529 Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005530 Accumulator.clear();
5531 }
5532 }
5533
Benjamin Kramer632500c2011-07-26 16:59:25 +00005534 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00005535 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00005536 }
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00005537 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005538 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00005539 }
5540 Results.ExitScope();
5541
5542 HandleCodeCompleteResults(this, CodeCompleter,
5543 CodeCompletionContext::CCC_SelectorName,
5544 Results.data(), Results.size());
5545}
5546
Douglas Gregorbaf69612009-11-18 04:19:12 +00005547/// \brief Add all of the protocol declarations that we find in the given
5548/// (translation unit) context.
5549static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005550 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00005551 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005552 typedef CodeCompletionResult Result;
Douglas Gregorbaf69612009-11-18 04:19:12 +00005553
5554 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5555 DEnd = Ctx->decls_end();
5556 D != DEnd; ++D) {
5557 // Record any protocols we find.
5558 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00005559 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregorfc59ce12010-01-14 16:14:35 +00005560 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005561 }
5562}
5563
5564void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5565 unsigned NumProtocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005566 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5567 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005568
Douglas Gregora3b23b02010-12-09 21:44:02 +00005569 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5570 Results.EnterNewScope();
5571
5572 // Tell the result set to ignore all of the protocols we have
5573 // already seen.
5574 // FIXME: This doesn't work when caching code-completion results.
5575 for (unsigned I = 0; I != NumProtocols; ++I)
5576 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5577 Protocols[I].second))
5578 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005579
Douglas Gregora3b23b02010-12-09 21:44:02 +00005580 // Add all protocols.
5581 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5582 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005583
Douglas Gregora3b23b02010-12-09 21:44:02 +00005584 Results.ExitScope();
5585 }
5586
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005587 HandleCodeCompleteResults(this, CodeCompleter,
5588 CodeCompletionContext::CCC_ObjCProtocolName,
5589 Results.data(),Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005590}
5591
5592void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005593 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5594 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00005595
Douglas Gregora3b23b02010-12-09 21:44:02 +00005596 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5597 Results.EnterNewScope();
5598
5599 // Add all protocols.
5600 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5601 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00005602
Douglas Gregora3b23b02010-12-09 21:44:02 +00005603 Results.ExitScope();
5604 }
5605
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005606 HandleCodeCompleteResults(this, CodeCompleter,
5607 CodeCompletionContext::CCC_ObjCProtocolName,
5608 Results.data(),Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00005609}
Douglas Gregor49c22a72009-11-18 16:26:39 +00005610
5611/// \brief Add all of the Objective-C interface declarations that we find in
5612/// the given (translation unit) context.
5613static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5614 bool OnlyForwardDeclarations,
5615 bool OnlyUnimplemented,
5616 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00005617 typedef CodeCompletionResult Result;
Douglas Gregor49c22a72009-11-18 16:26:39 +00005618
5619 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5620 DEnd = Ctx->decls_end();
5621 D != DEnd; ++D) {
Douglas Gregor1c283312010-08-11 12:19:30 +00005622 // Record any interfaces we find.
5623 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00005624 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00005625 (!OnlyUnimplemented || !Class->getImplementation()))
5626 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005627 }
5628}
5629
5630void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005631 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5632 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005633 Results.EnterNewScope();
5634
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005635 if (CodeCompleter->includeGlobals()) {
5636 // Add all classes.
5637 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5638 false, Results);
5639 }
5640
Douglas Gregor49c22a72009-11-18 16:26:39 +00005641 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005642
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005643 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005644 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005645 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005646}
5647
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005648void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5649 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005650 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005651 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005652 Results.EnterNewScope();
5653
5654 // Make sure that we ignore the class we're currently defining.
5655 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005656 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005657 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00005658 Results.Ignore(CurClass);
5659
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005660 if (CodeCompleter->includeGlobals()) {
5661 // Add all classes.
5662 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5663 false, Results);
5664 }
5665
Douglas Gregor49c22a72009-11-18 16:26:39 +00005666 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005667
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005668 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005669 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005670 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005671}
5672
5673void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005674 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5675 CodeCompletionContext::CCC_Other);
Douglas Gregor49c22a72009-11-18 16:26:39 +00005676 Results.EnterNewScope();
5677
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005678 if (CodeCompleter->includeGlobals()) {
5679 // Add all unimplemented classes.
5680 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5681 true, Results);
5682 }
5683
Douglas Gregor49c22a72009-11-18 16:26:39 +00005684 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005685
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005686 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor2c595ad2011-07-30 06:55:39 +00005687 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005688 Results.data(),Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00005689}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005690
5691void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005692 IdentifierInfo *ClassName,
5693 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00005694 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005695
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005696 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor21325842011-07-07 16:03:39 +00005697 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005698
5699 // Ignore any categories we find that have already been implemented by this
5700 // interface.
5701 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5702 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005703 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005704 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5705 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5706 Category = Category->getNextClassCategory())
5707 CategoryNames.insert(Category->getIdentifier());
5708
5709 // Add all of the categories we know about.
5710 Results.EnterNewScope();
5711 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5712 for (DeclContext::decl_iterator D = TU->decls_begin(),
5713 DEnd = TU->decls_end();
5714 D != DEnd; ++D)
5715 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5716 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregorfc59ce12010-01-14 16:14:35 +00005717 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005718 Results.ExitScope();
5719
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005720 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00005721 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005722 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005723}
5724
5725void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005726 IdentifierInfo *ClassName,
5727 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00005728 typedef CodeCompletionResult Result;
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005729
5730 // Find the corresponding interface. If we couldn't find the interface, the
5731 // program itself is ill-formed. However, we'll try to be helpful still by
5732 // providing the list of all of the categories we know about.
5733 NamedDecl *CurClass
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005734 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005735 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5736 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00005737 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005738
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005739 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor21325842011-07-07 16:03:39 +00005740 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005741
5742 // Add all of the categories that have have corresponding interface
5743 // declarations in this class and any of its superclasses, except for
5744 // already-implemented categories in the class itself.
5745 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5746 Results.EnterNewScope();
5747 bool IgnoreImplemented = true;
5748 while (Class) {
5749 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5750 Category = Category->getNextClassCategory())
5751 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5752 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregorfc59ce12010-01-14 16:14:35 +00005753 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005754
5755 Class = Class->getSuperClass();
5756 IgnoreImplemented = false;
5757 }
5758 Results.ExitScope();
5759
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005760 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor21325842011-07-07 16:03:39 +00005761 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005762 Results.data(),Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00005763}
Douglas Gregor5d649882009-11-18 22:32:06 +00005764
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005765void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00005766 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005767 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5768 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00005769
5770 // Figure out where this @synthesize lives.
5771 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005772 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00005773 if (!Container ||
5774 (!isa<ObjCImplementationDecl>(Container) &&
5775 !isa<ObjCCategoryImplDecl>(Container)))
5776 return;
5777
5778 // Ignore any properties that have already been implemented.
5779 for (DeclContext::decl_iterator D = Container->decls_begin(),
5780 DEnd = Container->decls_end();
5781 D != DEnd; ++D)
5782 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5783 Results.Ignore(PropertyImpl->getPropertyDecl());
5784
5785 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00005786 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00005787 Results.EnterNewScope();
5788 if (ObjCImplementationDecl *ClassImpl
5789 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor95147142011-05-05 15:50:42 +00005790 AddObjCProperties(ClassImpl->getClassInterface(), false,
5791 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00005792 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00005793 else
5794 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor95147142011-05-05 15:50:42 +00005795 false, /*AllowNullaryMethods=*/false, CurContext,
5796 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00005797 Results.ExitScope();
5798
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005799 HandleCodeCompleteResults(this, CodeCompleter,
5800 CodeCompletionContext::CCC_Other,
5801 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00005802}
5803
5804void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005805 IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00005806 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005807 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5808 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00005809
5810 // Figure out where this @synthesize lives.
5811 ObjCContainerDecl *Container
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005812 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00005813 if (!Container ||
5814 (!isa<ObjCImplementationDecl>(Container) &&
5815 !isa<ObjCCategoryImplDecl>(Container)))
5816 return;
5817
5818 // Figure out which interface we're looking into.
5819 ObjCInterfaceDecl *Class = 0;
5820 if (ObjCImplementationDecl *ClassImpl
5821 = dyn_cast<ObjCImplementationDecl>(Container))
5822 Class = ClassImpl->getClassInterface();
5823 else
5824 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5825 ->getClassInterface();
5826
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005827 // Determine the type of the property we're synthesizing.
5828 QualType PropertyType = Context.getObjCIdType();
5829 if (Class) {
5830 if (ObjCPropertyDecl *Property
5831 = Class->FindPropertyDeclaration(PropertyName)) {
5832 PropertyType
5833 = Property->getType().getNonReferenceType().getUnqualifiedType();
5834
5835 // Give preference to ivars
5836 Results.setPreferredType(PropertyType);
5837 }
5838 }
5839
Douglas Gregor5d649882009-11-18 22:32:06 +00005840 // Add all of the instance variables in this class and its superclasses.
5841 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00005842 bool SawSimilarlyNamedIvar = false;
5843 std::string NameWithPrefix;
5844 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00005845 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00005846 std::string NameWithSuffix = PropertyName->getName().str();
5847 NameWithSuffix += '_';
Douglas Gregor5d649882009-11-18 22:32:06 +00005848 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregor331faa02011-04-18 14:13:53 +00005849 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5850 Ivar = Ivar->getNextIvar()) {
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005851 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5852
Douglas Gregor331faa02011-04-18 14:13:53 +00005853 // Determine whether we've seen an ivar with a name similar to the
5854 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005855 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00005856 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005857 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00005858 SawSimilarlyNamedIvar = true;
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005859
5860 // Reduce the priority of this result by one, to give it a slight
5861 // advantage over other results whose names don't match so closely.
5862 if (Results.size() &&
5863 Results.data()[Results.size() - 1].Kind
5864 == CodeCompletionResult::RK_Declaration &&
5865 Results.data()[Results.size() - 1].Declaration == Ivar)
5866 Results.data()[Results.size() - 1].Priority--;
5867 }
Douglas Gregor331faa02011-04-18 14:13:53 +00005868 }
Douglas Gregor5d649882009-11-18 22:32:06 +00005869 }
Douglas Gregor331faa02011-04-18 14:13:53 +00005870
5871 if (!SawSimilarlyNamedIvar) {
5872 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005873 // an ivar of the appropriate type.
5874 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00005875 typedef CodeCompletionResult Result;
5876 CodeCompletionAllocator &Allocator = Results.getAllocator();
5877 CodeCompletionBuilder Builder(Allocator, Priority,CXAvailability_Available);
5878
Douglas Gregor75acd922011-09-27 23:30:47 +00005879 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00005880 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00005881 Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00005882 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5883 Results.AddResult(Result(Builder.TakeString(), Priority,
5884 CXCursor_ObjCIvarDecl));
5885 }
5886
Douglas Gregor5d649882009-11-18 22:32:06 +00005887 Results.ExitScope();
5888
Douglas Gregor00c37ef2010-08-11 21:23:17 +00005889 HandleCodeCompleteResults(this, CodeCompleter,
5890 CodeCompletionContext::CCC_Other,
5891 Results.data(),Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00005892}
Douglas Gregor636a61e2010-04-07 00:21:17 +00005893
Douglas Gregor416b5752010-08-25 01:08:01 +00005894// Mapping from selectors to the methods that implement that selector, along
5895// with the "in original class" flag.
5896typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5897 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00005898
5899/// \brief Find all of the methods that reside in the given container
5900/// (and its superclasses, protocols, etc.) that meet the given
5901/// criteria. Insert those methods into the map of known methods,
5902/// indexed by selector so they can be easily found.
5903static void FindImplementableMethods(ASTContext &Context,
5904 ObjCContainerDecl *Container,
5905 bool WantInstanceMethods,
5906 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00005907 KnownMethodsMap &KnownMethods,
5908 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00005909 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5910 // Recurse into protocols.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005911 if (!IFace->hasDefinition())
5912 return;
5913
Douglas Gregor636a61e2010-04-07 00:21:17 +00005914 const ObjCList<ObjCProtocolDecl> &Protocols
5915 = IFace->getReferencedProtocols();
5916 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005917 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00005918 I != E; ++I)
5919 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005920 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00005921
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005922 // Add methods from any class extensions and categories.
5923 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5924 Cat = Cat->getNextClassCategory())
Fariborz Jahanian3bf0ded2010-06-22 23:20:40 +00005925 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5926 WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005927 KnownMethods, false);
5928
5929 // Visit the superclass.
5930 if (IFace->getSuperClass())
5931 FindImplementableMethods(Context, IFace->getSuperClass(),
5932 WantInstanceMethods, ReturnType,
5933 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00005934 }
5935
5936 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5937 // Recurse into protocols.
5938 const ObjCList<ObjCProtocolDecl> &Protocols
5939 = Category->getReferencedProtocols();
5940 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005941 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00005942 I != E; ++I)
5943 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00005944 KnownMethods, InOriginalClass);
5945
5946 // If this category is the original class, jump to the interface.
5947 if (InOriginalClass && Category->getClassInterface())
5948 FindImplementableMethods(Context, Category->getClassInterface(),
5949 WantInstanceMethods, ReturnType, KnownMethods,
5950 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00005951 }
5952
5953 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005954 if (Protocol->hasDefinition()) {
5955 // Recurse into protocols.
5956 const ObjCList<ObjCProtocolDecl> &Protocols
5957 = Protocol->getReferencedProtocols();
5958 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5959 E = Protocols.end();
5960 I != E; ++I)
5961 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
5962 KnownMethods, false);
5963 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00005964 }
5965
5966 // Add methods in this container. This operation occurs last because
5967 // we want the methods from this container to override any methods
5968 // we've previously seen with the same selector.
5969 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5970 MEnd = Container->meth_end();
5971 M != MEnd; ++M) {
5972 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5973 if (!ReturnType.isNull() &&
5974 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5975 continue;
5976
Douglas Gregor416b5752010-08-25 01:08:01 +00005977 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00005978 }
5979 }
5980}
5981
Douglas Gregor669a25a2011-02-17 00:22:45 +00005982/// \brief Add the parenthesized return or parameter type chunk to a code
5983/// completion string.
5984static void AddObjCPassingTypeChunk(QualType Type,
5985 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00005986 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00005987 CodeCompletionBuilder &Builder) {
5988 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor75acd922011-09-27 23:30:47 +00005989 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00005990 Builder.getAllocator()));
5991 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5992}
5993
5994/// \brief Determine whether the given class is or inherits from a class by
5995/// the given name.
5996static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00005997 StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00005998 if (!Class)
5999 return false;
6000
6001 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6002 return true;
6003
6004 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6005}
6006
6007/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6008/// Key-Value Observing (KVO).
6009static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6010 bool IsInstanceMethod,
6011 QualType ReturnType,
6012 ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006013 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006014 ResultBuilder &Results) {
6015 IdentifierInfo *PropName = Property->getIdentifier();
6016 if (!PropName || PropName->getLength() == 0)
6017 return;
6018
Douglas Gregor75acd922011-09-27 23:30:47 +00006019 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6020
Douglas Gregor669a25a2011-02-17 00:22:45 +00006021 // Builder that will create each code completion.
6022 typedef CodeCompletionResult Result;
6023 CodeCompletionAllocator &Allocator = Results.getAllocator();
6024 CodeCompletionBuilder Builder(Allocator);
6025
6026 // The selector table.
6027 SelectorTable &Selectors = Context.Selectors;
6028
6029 // The property name, copied into the code completion allocation region
6030 // on demand.
6031 struct KeyHolder {
6032 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006033 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006034 const char *CopiedKey;
6035
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006036 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006037 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6038
6039 operator const char *() {
6040 if (CopiedKey)
6041 return CopiedKey;
6042
6043 return CopiedKey = Allocator.CopyString(Key);
6044 }
6045 } Key(Allocator, PropName->getName());
6046
6047 // The uppercased name of the property name.
6048 std::string UpperKey = PropName->getName();
6049 if (!UpperKey.empty())
6050 UpperKey[0] = toupper(UpperKey[0]);
6051
6052 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6053 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6054 Property->getType());
6055 bool ReturnTypeMatchesVoid
6056 = ReturnType.isNull() || ReturnType->isVoidType();
6057
6058 // Add the normal accessor -(type)key.
6059 if (IsInstanceMethod &&
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006060 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00006061 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6062 if (ReturnType.isNull())
Douglas Gregor75acd922011-09-27 23:30:47 +00006063 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006064
6065 Builder.AddTypedTextChunk(Key);
6066 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6067 CXCursor_ObjCInstanceMethodDecl));
6068 }
6069
6070 // If we have an integral or boolean property (or the user has provided
6071 // an integral or boolean return type), add the accessor -(type)isKey.
6072 if (IsInstanceMethod &&
6073 ((!ReturnType.isNull() &&
6074 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6075 (ReturnType.isNull() &&
6076 (Property->getType()->isIntegerType() ||
6077 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006078 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006079 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006080 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006081 if (ReturnType.isNull()) {
6082 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6083 Builder.AddTextChunk("BOOL");
6084 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6085 }
6086
6087 Builder.AddTypedTextChunk(
6088 Allocator.CopyString(SelectorId->getName()));
6089 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6090 CXCursor_ObjCInstanceMethodDecl));
6091 }
6092 }
6093
6094 // Add the normal mutator.
6095 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6096 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006097 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006098 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006099 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006100 if (ReturnType.isNull()) {
6101 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6102 Builder.AddTextChunk("void");
6103 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6104 }
6105
6106 Builder.AddTypedTextChunk(
6107 Allocator.CopyString(SelectorId->getName()));
6108 Builder.AddTypedTextChunk(":");
Douglas Gregor75acd922011-09-27 23:30:47 +00006109 AddObjCPassingTypeChunk(Property->getType(), Context, Policy, Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006110 Builder.AddTextChunk(Key);
6111 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6112 CXCursor_ObjCInstanceMethodDecl));
6113 }
6114 }
6115
6116 // Indexed and unordered accessors
6117 unsigned IndexedGetterPriority = CCP_CodePattern;
6118 unsigned IndexedSetterPriority = CCP_CodePattern;
6119 unsigned UnorderedGetterPriority = CCP_CodePattern;
6120 unsigned UnorderedSetterPriority = CCP_CodePattern;
6121 if (const ObjCObjectPointerType *ObjCPointer
6122 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6123 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6124 // If this interface type is not provably derived from a known
6125 // collection, penalize the corresponding completions.
6126 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6127 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6128 if (!InheritsFromClassNamed(IFace, "NSArray"))
6129 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6130 }
6131
6132 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6133 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6134 if (!InheritsFromClassNamed(IFace, "NSSet"))
6135 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6136 }
6137 }
6138 } else {
6139 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6140 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6141 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6142 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6143 }
6144
6145 // Add -(NSUInteger)countOf<key>
6146 if (IsInstanceMethod &&
6147 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006148 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006149 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006150 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006151 if (ReturnType.isNull()) {
6152 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6153 Builder.AddTextChunk("NSUInteger");
6154 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6155 }
6156
6157 Builder.AddTypedTextChunk(
6158 Allocator.CopyString(SelectorId->getName()));
6159 Results.AddResult(Result(Builder.TakeString(),
6160 std::min(IndexedGetterPriority,
6161 UnorderedGetterPriority),
6162 CXCursor_ObjCInstanceMethodDecl));
6163 }
6164 }
6165
6166 // Indexed getters
6167 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6168 if (IsInstanceMethod &&
6169 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006170 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006171 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006172 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006173 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006174 if (ReturnType.isNull()) {
6175 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6176 Builder.AddTextChunk("id");
6177 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6178 }
6179
6180 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6181 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6182 Builder.AddTextChunk("NSUInteger");
6183 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6184 Builder.AddTextChunk("index");
6185 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6186 CXCursor_ObjCInstanceMethodDecl));
6187 }
6188 }
6189
6190 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6191 if (IsInstanceMethod &&
6192 (ReturnType.isNull() ||
6193 (ReturnType->isObjCObjectPointerType() &&
6194 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6195 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6196 ->getName() == "NSArray"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006197 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006198 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006199 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006200 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006201 if (ReturnType.isNull()) {
6202 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6203 Builder.AddTextChunk("NSArray *");
6204 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6205 }
6206
6207 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6208 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6209 Builder.AddTextChunk("NSIndexSet *");
6210 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6211 Builder.AddTextChunk("indexes");
6212 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6213 CXCursor_ObjCInstanceMethodDecl));
6214 }
6215 }
6216
6217 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6218 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006219 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006220 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006221 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006222 &Context.Idents.get("range")
6223 };
6224
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006225 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006226 if (ReturnType.isNull()) {
6227 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6228 Builder.AddTextChunk("void");
6229 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6230 }
6231
6232 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6233 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6234 Builder.AddPlaceholderChunk("object-type");
6235 Builder.AddTextChunk(" **");
6236 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6237 Builder.AddTextChunk("buffer");
6238 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6239 Builder.AddTypedTextChunk("range:");
6240 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6241 Builder.AddTextChunk("NSRange");
6242 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6243 Builder.AddTextChunk("inRange");
6244 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6245 CXCursor_ObjCInstanceMethodDecl));
6246 }
6247 }
6248
6249 // Mutable indexed accessors
6250
6251 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6252 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006253 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006254 IdentifierInfo *SelectorIds[2] = {
6255 &Context.Idents.get("insertObject"),
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006256 &Context.Idents.get(SelectorName)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006257 };
6258
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006259 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006260 if (ReturnType.isNull()) {
6261 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6262 Builder.AddTextChunk("void");
6263 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6264 }
6265
6266 Builder.AddTypedTextChunk("insertObject:");
6267 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6268 Builder.AddPlaceholderChunk("object-type");
6269 Builder.AddTextChunk(" *");
6270 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6271 Builder.AddTextChunk("object");
6272 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6273 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6274 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6275 Builder.AddPlaceholderChunk("NSUInteger");
6276 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6277 Builder.AddTextChunk("index");
6278 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6279 CXCursor_ObjCInstanceMethodDecl));
6280 }
6281 }
6282
6283 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6284 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006285 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006286 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006287 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006288 &Context.Idents.get("atIndexes")
6289 };
6290
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006291 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006292 if (ReturnType.isNull()) {
6293 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6294 Builder.AddTextChunk("void");
6295 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6296 }
6297
6298 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6299 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6300 Builder.AddTextChunk("NSArray *");
6301 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6302 Builder.AddTextChunk("array");
6303 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6304 Builder.AddTypedTextChunk("atIndexes:");
6305 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6306 Builder.AddPlaceholderChunk("NSIndexSet *");
6307 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6308 Builder.AddTextChunk("indexes");
6309 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6310 CXCursor_ObjCInstanceMethodDecl));
6311 }
6312 }
6313
6314 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6315 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006316 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006317 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006318 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006319 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006320 if (ReturnType.isNull()) {
6321 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6322 Builder.AddTextChunk("void");
6323 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6324 }
6325
6326 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6327 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6328 Builder.AddTextChunk("NSUInteger");
6329 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6330 Builder.AddTextChunk("index");
6331 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6332 CXCursor_ObjCInstanceMethodDecl));
6333 }
6334 }
6335
6336 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6337 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006338 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006339 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006340 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006341 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006342 if (ReturnType.isNull()) {
6343 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6344 Builder.AddTextChunk("void");
6345 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6346 }
6347
6348 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6349 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6350 Builder.AddTextChunk("NSIndexSet *");
6351 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6352 Builder.AddTextChunk("indexes");
6353 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6354 CXCursor_ObjCInstanceMethodDecl));
6355 }
6356 }
6357
6358 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6359 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006360 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006361 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006362 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006363 &Context.Idents.get(SelectorName),
Douglas Gregor669a25a2011-02-17 00:22:45 +00006364 &Context.Idents.get("withObject")
6365 };
6366
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006367 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006368 if (ReturnType.isNull()) {
6369 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6370 Builder.AddTextChunk("void");
6371 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6372 }
6373
6374 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6375 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6376 Builder.AddPlaceholderChunk("NSUInteger");
6377 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6378 Builder.AddTextChunk("index");
6379 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6380 Builder.AddTypedTextChunk("withObject:");
6381 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6382 Builder.AddTextChunk("id");
6383 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6384 Builder.AddTextChunk("object");
6385 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6386 CXCursor_ObjCInstanceMethodDecl));
6387 }
6388 }
6389
6390 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6391 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006392 std::string SelectorName1
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006393 = (Twine("replace") + UpperKey + "AtIndexes").str();
6394 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor669a25a2011-02-17 00:22:45 +00006395 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006396 &Context.Idents.get(SelectorName1),
6397 &Context.Idents.get(SelectorName2)
Douglas Gregor669a25a2011-02-17 00:22:45 +00006398 };
6399
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006400 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006401 if (ReturnType.isNull()) {
6402 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6403 Builder.AddTextChunk("void");
6404 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6405 }
6406
6407 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6408 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6409 Builder.AddPlaceholderChunk("NSIndexSet *");
6410 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6411 Builder.AddTextChunk("indexes");
6412 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6413 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6414 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6415 Builder.AddTextChunk("NSArray *");
6416 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6417 Builder.AddTextChunk("array");
6418 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6419 CXCursor_ObjCInstanceMethodDecl));
6420 }
6421 }
6422
6423 // Unordered getters
6424 // - (NSEnumerator *)enumeratorOfKey
6425 if (IsInstanceMethod &&
6426 (ReturnType.isNull() ||
6427 (ReturnType->isObjCObjectPointerType() &&
6428 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6429 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6430 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006431 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006432 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006433 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006434 if (ReturnType.isNull()) {
6435 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6436 Builder.AddTextChunk("NSEnumerator *");
6437 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6438 }
6439
6440 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6441 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6442 CXCursor_ObjCInstanceMethodDecl));
6443 }
6444 }
6445
6446 // - (type *)memberOfKey:(type *)object
6447 if (IsInstanceMethod &&
6448 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006449 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006450 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006451 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006452 if (ReturnType.isNull()) {
6453 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6454 Builder.AddPlaceholderChunk("object-type");
6455 Builder.AddTextChunk(" *");
6456 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6457 }
6458
6459 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6460 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6461 if (ReturnType.isNull()) {
6462 Builder.AddPlaceholderChunk("object-type");
6463 Builder.AddTextChunk(" *");
6464 } else {
6465 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00006466 Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00006467 Builder.getAllocator()));
6468 }
6469 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6470 Builder.AddTextChunk("object");
6471 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6472 CXCursor_ObjCInstanceMethodDecl));
6473 }
6474 }
6475
6476 // Mutable unordered accessors
6477 // - (void)addKeyObject:(type *)object
6478 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006479 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006480 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006481 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006482 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006483 if (ReturnType.isNull()) {
6484 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6485 Builder.AddTextChunk("void");
6486 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6487 }
6488
6489 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6490 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6491 Builder.AddPlaceholderChunk("object-type");
6492 Builder.AddTextChunk(" *");
6493 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6494 Builder.AddTextChunk("object");
6495 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6496 CXCursor_ObjCInstanceMethodDecl));
6497 }
6498 }
6499
6500 // - (void)addKey:(NSSet *)objects
6501 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006502 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006503 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006504 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006505 if (ReturnType.isNull()) {
6506 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6507 Builder.AddTextChunk("void");
6508 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6509 }
6510
6511 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6512 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6513 Builder.AddTextChunk("NSSet *");
6514 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6515 Builder.AddTextChunk("objects");
6516 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6517 CXCursor_ObjCInstanceMethodDecl));
6518 }
6519 }
6520
6521 // - (void)removeKeyObject:(type *)object
6522 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006523 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006524 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006525 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006526 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006527 if (ReturnType.isNull()) {
6528 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6529 Builder.AddTextChunk("void");
6530 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6531 }
6532
6533 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6534 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6535 Builder.AddPlaceholderChunk("object-type");
6536 Builder.AddTextChunk(" *");
6537 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6538 Builder.AddTextChunk("object");
6539 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6540 CXCursor_ObjCInstanceMethodDecl));
6541 }
6542 }
6543
6544 // - (void)removeKey:(NSSet *)objects
6545 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006546 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006547 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006548 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006549 if (ReturnType.isNull()) {
6550 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6551 Builder.AddTextChunk("void");
6552 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6553 }
6554
6555 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6556 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6557 Builder.AddTextChunk("NSSet *");
6558 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6559 Builder.AddTextChunk("objects");
6560 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6561 CXCursor_ObjCInstanceMethodDecl));
6562 }
6563 }
6564
6565 // - (void)intersectKey:(NSSet *)objects
6566 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006567 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006568 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006569 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006570 if (ReturnType.isNull()) {
6571 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6572 Builder.AddTextChunk("void");
6573 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6574 }
6575
6576 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6577 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6578 Builder.AddTextChunk("NSSet *");
6579 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6580 Builder.AddTextChunk("objects");
6581 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6582 CXCursor_ObjCInstanceMethodDecl));
6583 }
6584 }
6585
6586 // Key-Value Observing
6587 // + (NSSet *)keyPathsForValuesAffectingKey
6588 if (!IsInstanceMethod &&
6589 (ReturnType.isNull() ||
6590 (ReturnType->isObjCObjectPointerType() &&
6591 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6592 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6593 ->getName() == "NSSet"))) {
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006594 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006595 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00006596 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006597 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00006598 if (ReturnType.isNull()) {
6599 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6600 Builder.AddTextChunk("NSSet *");
6601 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6602 }
6603
6604 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6605 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor857bcda2011-06-02 04:02:27 +00006606 CXCursor_ObjCClassMethodDecl));
6607 }
6608 }
6609
6610 // + (BOOL)automaticallyNotifiesObserversForKey
6611 if (!IsInstanceMethod &&
6612 (ReturnType.isNull() ||
6613 ReturnType->isIntegerType() ||
6614 ReturnType->isBooleanType())) {
6615 std::string SelectorName
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006616 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00006617 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6618 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6619 if (ReturnType.isNull()) {
6620 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6621 Builder.AddTextChunk("BOOL");
6622 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6623 }
6624
6625 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6626 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6627 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00006628 }
6629 }
6630}
6631
Douglas Gregor636a61e2010-04-07 00:21:17 +00006632void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6633 bool IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006634 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006635 // Determine the return type of the method we're declaring, if
6636 // provided.
6637 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006638 Decl *IDecl = 0;
6639 if (CurContext->isObjCContainer()) {
6640 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6641 IDecl = cast<Decl>(OCD);
6642 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006643 // Determine where we should start searching for methods.
6644 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006645 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00006646 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006647 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6648 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006649 IsInImplementation = true;
6650 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006651 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006652 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006653 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006654 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00006655 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006656 }
6657
6658 if (!SearchDecl && S) {
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006659 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00006660 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006661 }
6662
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006663 if (!SearchDecl) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006664 HandleCodeCompleteResults(this, CodeCompleter,
6665 CodeCompletionContext::CCC_Other,
6666 0, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006667 return;
6668 }
6669
6670 // Find all of the methods that we could declare/implement here.
6671 KnownMethodsMap KnownMethods;
6672 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006673 ReturnType, KnownMethods);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006674
Douglas Gregor636a61e2010-04-07 00:21:17 +00006675 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00006676 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006677 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6678 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006679 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00006680 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006681 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6682 MEnd = KnownMethods.end();
6683 M != MEnd; ++M) {
Douglas Gregor416b5752010-08-25 01:08:01 +00006684 ObjCMethodDecl *Method = M->second.first;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006685 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor636a61e2010-04-07 00:21:17 +00006686
6687 // If the result type was not already provided, add it to the
6688 // pattern as (type).
Douglas Gregor669a25a2011-02-17 00:22:45 +00006689 if (ReturnType.isNull())
Douglas Gregor75acd922011-09-27 23:30:47 +00006690 AddObjCPassingTypeChunk(Method->getResultType(), Context, Policy,
6691 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006692
6693 Selector Sel = Method->getSelector();
6694
6695 // Add the first part of the selector to the pattern.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006696 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006697 Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006698
6699 // Add parameters to the pattern.
6700 unsigned I = 0;
6701 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6702 PEnd = Method->param_end();
6703 P != PEnd; (void)++P, ++I) {
6704 // Add the part of the selector name.
6705 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006706 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00006707 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006708 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6709 Builder.AddTypedTextChunk(
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00006710 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006711 } else
6712 break;
6713
6714 // Add the parameter type.
Douglas Gregor75acd922011-09-27 23:30:47 +00006715 AddObjCPassingTypeChunk((*P)->getOriginalType(), Context, Policy,
6716 Builder);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006717
6718 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006719 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006720 }
6721
6722 if (Method->isVariadic()) {
6723 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006724 Builder.AddChunk(CodeCompletionString::CK_Comma);
6725 Builder.AddTextChunk("...");
Douglas Gregor400f5972010-08-31 05:13:43 +00006726 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00006727
Douglas Gregord37c59d2010-05-28 00:57:46 +00006728 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006729 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006730 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6731 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6732 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006733 if (!Method->getResultType()->isVoidType()) {
6734 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006735 Builder.AddTextChunk("return");
6736 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6737 Builder.AddPlaceholderChunk("expression");
6738 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006739 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006740 Builder.AddPlaceholderChunk("statements");
Douglas Gregor636a61e2010-04-07 00:21:17 +00006741
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006742 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6743 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006744 }
6745
Douglas Gregor416b5752010-08-25 01:08:01 +00006746 unsigned Priority = CCP_CodePattern;
6747 if (!M->second.second)
6748 Priority += CCD_InBaseClass;
6749
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006750 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor7116a8c2010-08-17 16:06:07 +00006751 Method->isInstanceMethod()
6752 ? CXCursor_ObjCInstanceMethodDecl
6753 : CXCursor_ObjCClassMethodDecl));
Douglas Gregor636a61e2010-04-07 00:21:17 +00006754 }
6755
Douglas Gregor669a25a2011-02-17 00:22:45 +00006756 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6757 // the properties in this class and its categories.
David Blaikiebbafb8a2012-03-11 07:00:24 +00006758 if (Context.getLangOpts().ObjC2) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00006759 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00006760 Containers.push_back(SearchDecl);
6761
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006762 VisitedSelectorSet KnownSelectors;
6763 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6764 MEnd = KnownMethods.end();
6765 M != MEnd; ++M)
6766 KnownSelectors.insert(M->first);
6767
6768
Douglas Gregor669a25a2011-02-17 00:22:45 +00006769 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6770 if (!IFace)
6771 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6772 IFace = Category->getClassInterface();
6773
6774 if (IFace) {
6775 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6776 Category = Category->getNextClassCategory())
6777 Containers.push_back(Category);
6778 }
6779
6780 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6781 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6782 PEnd = Containers[I]->prop_end();
6783 P != PEnd; ++P) {
6784 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00006785 KnownSelectors, Results);
Douglas Gregor669a25a2011-02-17 00:22:45 +00006786 }
6787 }
6788 }
6789
Douglas Gregor636a61e2010-04-07 00:21:17 +00006790 Results.ExitScope();
6791
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006792 HandleCodeCompleteResults(this, CodeCompleter,
6793 CodeCompletionContext::CCC_Other,
6794 Results.data(),Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00006795}
Douglas Gregor95887f92010-07-08 23:20:03 +00006796
6797void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6798 bool IsInstanceMethod,
Douglas Gregor45879692010-07-08 23:37:41 +00006799 bool AtParameterName,
John McCallba7bf592010-08-24 05:47:05 +00006800 ParsedType ReturnTy,
Douglas Gregor95887f92010-07-08 23:20:03 +00006801 IdentifierInfo **SelIdents,
6802 unsigned NumSelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00006803 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006804 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00006805 if (ExternalSource) {
6806 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6807 I != N; ++I) {
6808 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006809 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00006810 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00006811
6812 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00006813 }
6814 }
6815
6816 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00006817 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006818 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
6819 CodeCompletionContext::CCC_Other);
Douglas Gregor95887f92010-07-08 23:20:03 +00006820
6821 if (ReturnTy)
6822 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00006823
Douglas Gregor95887f92010-07-08 23:20:03 +00006824 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006825 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6826 MEnd = MethodPool.end();
6827 M != MEnd; ++M) {
6828 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6829 &M->second.second;
6830 MethList && MethList->Method;
Douglas Gregor95887f92010-07-08 23:20:03 +00006831 MethList = MethList->Next) {
6832 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6833 NumSelIdents))
6834 continue;
6835
Douglas Gregor45879692010-07-08 23:37:41 +00006836 if (AtParameterName) {
6837 // Suggest parameter names we've seen before.
6838 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6839 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6840 if (Param->getIdentifier()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006841 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006842 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006843 Param->getIdentifier()->getName()));
6844 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00006845 }
6846 }
6847
6848 continue;
6849 }
6850
Douglas Gregor95887f92010-07-08 23:20:03 +00006851 Result R(MethList->Method, 0);
6852 R.StartParameter = NumSelIdents;
6853 R.AllParametersAreInformative = false;
6854 R.DeclaringEntity = true;
6855 Results.MaybeAddResult(R, CurContext);
6856 }
6857 }
6858
6859 Results.ExitScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006860 HandleCodeCompleteResults(this, CodeCompleter,
6861 CodeCompletionContext::CCC_Other,
6862 Results.data(),Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00006863}
Douglas Gregorb14904c2010-08-13 22:48:40 +00006864
Douglas Gregorec00a262010-08-24 22:20:20 +00006865void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006866 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00006867 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006868 Results.EnterNewScope();
6869
6870 // #if <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006871 CodeCompletionBuilder Builder(Results.getAllocator());
6872 Builder.AddTypedTextChunk("if");
6873 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6874 Builder.AddPlaceholderChunk("condition");
6875 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006876
6877 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006878 Builder.AddTypedTextChunk("ifdef");
6879 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6880 Builder.AddPlaceholderChunk("macro");
6881 Results.AddResult(Builder.TakeString());
6882
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006883 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006884 Builder.AddTypedTextChunk("ifndef");
6885 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6886 Builder.AddPlaceholderChunk("macro");
6887 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006888
6889 if (InConditional) {
6890 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006891 Builder.AddTypedTextChunk("elif");
6892 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6893 Builder.AddPlaceholderChunk("condition");
6894 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006895
6896 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006897 Builder.AddTypedTextChunk("else");
6898 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006899
6900 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006901 Builder.AddTypedTextChunk("endif");
6902 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006903 }
6904
6905 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006906 Builder.AddTypedTextChunk("include");
6907 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6908 Builder.AddTextChunk("\"");
6909 Builder.AddPlaceholderChunk("header");
6910 Builder.AddTextChunk("\"");
6911 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006912
6913 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006914 Builder.AddTypedTextChunk("include");
6915 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6916 Builder.AddTextChunk("<");
6917 Builder.AddPlaceholderChunk("header");
6918 Builder.AddTextChunk(">");
6919 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006920
6921 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006922 Builder.AddTypedTextChunk("define");
6923 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6924 Builder.AddPlaceholderChunk("macro");
6925 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006926
6927 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006928 Builder.AddTypedTextChunk("define");
6929 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6930 Builder.AddPlaceholderChunk("macro");
6931 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6932 Builder.AddPlaceholderChunk("args");
6933 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6934 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006935
6936 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006937 Builder.AddTypedTextChunk("undef");
6938 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6939 Builder.AddPlaceholderChunk("macro");
6940 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006941
6942 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006943 Builder.AddTypedTextChunk("line");
6944 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6945 Builder.AddPlaceholderChunk("number");
6946 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006947
6948 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006949 Builder.AddTypedTextChunk("line");
6950 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6951 Builder.AddPlaceholderChunk("number");
6952 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6953 Builder.AddTextChunk("\"");
6954 Builder.AddPlaceholderChunk("filename");
6955 Builder.AddTextChunk("\"");
6956 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006957
6958 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006959 Builder.AddTypedTextChunk("error");
6960 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6961 Builder.AddPlaceholderChunk("message");
6962 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006963
6964 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006965 Builder.AddTypedTextChunk("pragma");
6966 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6967 Builder.AddPlaceholderChunk("arguments");
6968 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006969
David Blaikiebbafb8a2012-03-11 07:00:24 +00006970 if (getLangOpts().ObjC1) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006971 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006972 Builder.AddTypedTextChunk("import");
6973 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6974 Builder.AddTextChunk("\"");
6975 Builder.AddPlaceholderChunk("header");
6976 Builder.AddTextChunk("\"");
6977 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006978
6979 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006980 Builder.AddTypedTextChunk("import");
6981 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6982 Builder.AddTextChunk("<");
6983 Builder.AddPlaceholderChunk("header");
6984 Builder.AddTextChunk(">");
6985 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006986 }
6987
6988 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006989 Builder.AddTypedTextChunk("include_next");
6990 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6991 Builder.AddTextChunk("\"");
6992 Builder.AddPlaceholderChunk("header");
6993 Builder.AddTextChunk("\"");
6994 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00006995
6996 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006997 Builder.AddTypedTextChunk("include_next");
6998 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6999 Builder.AddTextChunk("<");
7000 Builder.AddPlaceholderChunk("header");
7001 Builder.AddTextChunk(">");
7002 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007003
7004 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007005 Builder.AddTypedTextChunk("warning");
7006 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7007 Builder.AddPlaceholderChunk("message");
7008 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007009
7010 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7011 // completions for them. And __include_macros is a Clang-internal extension
7012 // that we don't want to encourage anyone to use.
7013
7014 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7015 Results.ExitScope();
7016
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007017 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0de55ce2010-08-25 18:41:16 +00007018 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007019 Results.data(), Results.size());
7020}
7021
7022void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorec00a262010-08-24 22:20:20 +00007023 CodeCompleteOrdinaryName(S,
John McCallfaf5fb42010-08-26 23:41:50 +00007024 S->getFnParent()? Sema::PCC_RecoveryInFunction
7025 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007026}
7027
Douglas Gregorec00a262010-08-24 22:20:20 +00007028void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007029 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007030 IsDefinition? CodeCompletionContext::CCC_MacroName
7031 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00007032 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7033 // Add just the names of macros, not their arguments.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007034 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor12785102010-08-24 20:21:13 +00007035 Results.EnterNewScope();
7036 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7037 MEnd = PP.macro_end();
7038 M != MEnd; ++M) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007039 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007040 M->first->getName()));
7041 Results.AddResult(Builder.TakeString());
Douglas Gregor12785102010-08-24 20:21:13 +00007042 }
7043 Results.ExitScope();
7044 } else if (IsDefinition) {
7045 // FIXME: Can we detect when the user just wrote an include guard above?
7046 }
7047
Douglas Gregor0ac41382010-09-23 23:01:17 +00007048 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor12785102010-08-24 20:21:13 +00007049 Results.data(), Results.size());
7050}
7051
Douglas Gregorec00a262010-08-24 22:20:20 +00007052void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007053 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007054 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorec00a262010-08-24 22:20:20 +00007055
7056 if (!CodeCompleter || CodeCompleter->includeMacros())
7057 AddMacroResults(PP, Results);
7058
7059 // defined (<macro>)
7060 Results.EnterNewScope();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007061 CodeCompletionBuilder Builder(Results.getAllocator());
7062 Builder.AddTypedTextChunk("defined");
7063 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7064 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7065 Builder.AddPlaceholderChunk("macro");
7066 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7067 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00007068 Results.ExitScope();
7069
7070 HandleCodeCompleteResults(this, CodeCompleter,
7071 CodeCompletionContext::CCC_PreprocessorExpression,
7072 Results.data(), Results.size());
7073}
7074
7075void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7076 IdentifierInfo *Macro,
7077 MacroInfo *MacroInfo,
7078 unsigned Argument) {
7079 // FIXME: In the future, we could provide "overload" results, much like we
7080 // do for function calls.
7081
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00007082 // Now just ignore this. There will be another code-completion callback
7083 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00007084}
7085
Douglas Gregor11583702010-08-25 17:04:25 +00007086void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00007087 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorea736372010-08-25 17:10:00 +00007088 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor11583702010-08-25 17:04:25 +00007089 0, 0);
7090}
7091
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007092void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007093 SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007094 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00007095 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7096 CodeCompletionDeclConsumer Consumer(Builder,
7097 Context.getTranslationUnitDecl());
7098 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7099 Consumer);
7100 }
Douglas Gregorb14904c2010-08-13 22:48:40 +00007101
7102 if (!CodeCompleter || CodeCompleter->includeMacros())
7103 AddMacroResults(PP, Builder);
7104
7105 Results.clear();
7106 Results.insert(Results.end(),
7107 Builder.data(), Builder.data() + Builder.size());
7108}