blob: 05b22fa5371ef8bd7adc802781cbfc2df15e7cfc [file] [log] [blame]
Douglas Gregor81b747b2009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
John McCall2d887082010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.h"
Douglas Gregore737f502010-08-12 20:07:10 +000014#include "clang/Sema/Lookup.h"
John McCall120d63c2010-08-24 20:38:10 +000015#include "clang/Sema/Overload.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000016#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregor719770d2010-04-06 17:30:22 +000017#include "clang/Sema/ExternalSemaSource.h"
John McCall5f1e0942010-08-24 08:50:51 +000018#include "clang/Sema/Scope.h"
John McCall781472f2010-08-25 08:40:02 +000019#include "clang/Sema/ScopeInfo.h"
John McCall7cd088e2010-08-24 07:21:54 +000020#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000021#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000022#include "clang/AST/ExprObjC.h"
Douglas Gregorc5b2e582012-01-29 18:15:03 +000023#include "clang/Lex/HeaderSearch.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000024#include "clang/Lex/MacroInfo.h"
25#include "clang/Lex/Preprocessor.h"
Douglas Gregord36adf52010-09-16 16:06:31 +000026#include "llvm/ADT/DenseSet.h"
Benjamin Kramer013b3662012-01-30 16:17:39 +000027#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000028#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer8fe83e12012-02-04 13:45:25 +000029#include "llvm/ADT/SmallString.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000030#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000031#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000032#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000033#include <list>
34#include <map>
35#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000036
37using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000038using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000039
Douglas Gregor86d9a522009-09-21 16:56:56 +000040namespace {
41 /// \brief A container of code-completion results.
42 class ResultBuilder {
43 public:
44 /// \brief The type of a name-lookup filter, which can be provided to the
45 /// name-lookup routines to specify which declarations should be included in
46 /// the result set (when it returns true) and which declarations should be
47 /// filtered out (returns false).
48 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
49
John McCall0a2c5e22010-08-25 06:19:51 +000050 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000051
52 private:
53 /// \brief The actual results we have found.
54 std::vector<Result> Results;
55
56 /// \brief A record of all of the declarations we have found and placed
57 /// into the result set, used to ensure that no declaration ever gets into
58 /// the result set twice.
59 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
60
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000061 typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
62
63 /// \brief An entry in the shadow map, which is optimized to store
64 /// a single (declaration, index) mapping (the common case) but
65 /// can also store a list of (declaration, index) mappings.
66 class ShadowMapEntry {
Chris Lattner5f9e2722011-07-23 10:55:15 +000067 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000068
69 /// \brief Contains either the solitary NamedDecl * or a vector
70 /// of (declaration, index) pairs.
71 llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
72
73 /// \brief When the entry contains a single declaration, this is
74 /// the index associated with that entry.
75 unsigned SingleDeclIndex;
76
77 public:
78 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
79
80 void Add(NamedDecl *ND, unsigned Index) {
81 if (DeclOrVector.isNull()) {
82 // 0 - > 1 elements: just set the single element information.
83 DeclOrVector = ND;
84 SingleDeclIndex = Index;
85 return;
86 }
87
88 if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
89 // 1 -> 2 elements: create the vector of results and push in the
90 // existing declaration.
91 DeclIndexPairVector *Vec = new DeclIndexPairVector;
92 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
93 DeclOrVector = Vec;
94 }
95
96 // Add the new element to the end of the vector.
97 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
98 DeclIndexPair(ND, Index));
99 }
100
101 void Destroy() {
102 if (DeclIndexPairVector *Vec
103 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
104 delete Vec;
105 DeclOrVector = ((NamedDecl *)0);
106 }
107 }
108
109 // Iteration.
110 class iterator;
111 iterator begin() const;
112 iterator end() const;
113 };
114
Douglas Gregor86d9a522009-09-21 16:56:56 +0000115 /// \brief A mapping from declaration names to the declarations that have
116 /// this name within a particular scope and their index within the list of
117 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000118 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000119
120 /// \brief The semantic analysis object for which results are being
121 /// produced.
122 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000123
124 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000125 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000126
127 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000128
129 /// \brief If non-NULL, a filter function used to remove any code-completion
130 /// results that are not desirable.
131 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000132
133 /// \brief Whether we should allow declarations as
134 /// nested-name-specifiers that would otherwise be filtered out.
135 bool AllowNestedNameSpecifiers;
136
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000137 /// \brief If set, the type that we would prefer our resulting value
138 /// declarations to have.
139 ///
140 /// Closely matching the preferred type gives a boost to a result's
141 /// priority.
142 CanQualType PreferredType;
143
Douglas Gregor86d9a522009-09-21 16:56:56 +0000144 /// \brief A list of shadow maps, which is used to model name hiding at
145 /// different levels of, e.g., the inheritance hierarchy.
146 std::list<ShadowMap> ShadowMaps;
147
Douglas Gregor3cdee122010-08-26 16:36:48 +0000148 /// \brief If we're potentially referring to a C++ member function, the set
149 /// of qualifiers applied to the object type.
150 Qualifiers ObjectTypeQualifiers;
151
152 /// \brief Whether the \p ObjectTypeQualifiers field is active.
153 bool HasObjectTypeQualifiers;
154
Douglas Gregor265f7492010-08-27 15:29:55 +0000155 /// \brief The selector that we prefer.
156 Selector PreferredSelector;
157
Douglas Gregorca45da02010-11-02 20:36:02 +0000158 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000159 CodeCompletionContext CompletionContext;
160
James Dennetta40f7922012-06-14 03:11:41 +0000161 /// \brief If we are in an instance method definition, the \@implementation
Douglas Gregorca45da02010-11-02 20:36:02 +0000162 /// object.
163 ObjCImplementationDecl *ObjCImplementation;
164
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000165 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000166
Douglas Gregor6f942b22010-09-21 16:06:22 +0000167 void MaybeAddConstructorResults(Result R);
168
Douglas Gregor86d9a522009-09-21 16:56:56 +0000169 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000170 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000171 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000172 const CodeCompletionContext &CompletionContext,
173 LookupFilter Filter = 0)
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000174 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
175 Filter(Filter),
Douglas Gregor218937c2011-02-01 19:23:04 +0000176 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000177 CompletionContext(CompletionContext),
178 ObjCImplementation(0)
179 {
180 // If this is an Objective-C instance method definition, dig out the
181 // corresponding implementation.
182 switch (CompletionContext.getKind()) {
183 case CodeCompletionContext::CCC_Expression:
184 case CodeCompletionContext::CCC_ObjCMessageReceiver:
185 case CodeCompletionContext::CCC_ParenthesizedExpression:
186 case CodeCompletionContext::CCC_Statement:
187 case CodeCompletionContext::CCC_Recovery:
188 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
189 if (Method->isInstanceMethod())
190 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
191 ObjCImplementation = Interface->getImplementation();
192 break;
193
194 default:
195 break;
196 }
197 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000198
Douglas Gregord8e8a582010-05-25 21:41:55 +0000199 /// \brief Whether we should include code patterns in the completion
200 /// results.
201 bool includeCodePatterns() const {
202 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000203 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000204 }
205
Douglas Gregor86d9a522009-09-21 16:56:56 +0000206 /// \brief Set the filter used for code-completion results.
207 void setFilter(LookupFilter Filter) {
208 this->Filter = Filter;
209 }
210
Douglas Gregor86d9a522009-09-21 16:56:56 +0000211 Result *data() { return Results.empty()? 0 : &Results.front(); }
212 unsigned size() const { return Results.size(); }
213 bool empty() const { return Results.empty(); }
214
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000215 /// \brief Specify the preferred type.
216 void setPreferredType(QualType T) {
217 PreferredType = SemaRef.Context.getCanonicalType(T);
218 }
219
Douglas Gregor3cdee122010-08-26 16:36:48 +0000220 /// \brief Set the cv-qualifiers on the object type, for us in filtering
221 /// calls to member functions.
222 ///
223 /// When there are qualifiers in this set, they will be used to filter
224 /// out member functions that aren't available (because there will be a
225 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
226 /// match.
227 void setObjectTypeQualifiers(Qualifiers Quals) {
228 ObjectTypeQualifiers = Quals;
229 HasObjectTypeQualifiers = true;
230 }
231
Douglas Gregor265f7492010-08-27 15:29:55 +0000232 /// \brief Set the preferred selector.
233 ///
234 /// When an Objective-C method declaration result is added, and that
235 /// method's selector matches this preferred selector, we give that method
236 /// a slight priority boost.
237 void setPreferredSelector(Selector Sel) {
238 PreferredSelector = Sel;
239 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000240
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000241 /// \brief Retrieve the code-completion context for which results are
242 /// being collected.
243 const CodeCompletionContext &getCompletionContext() const {
244 return CompletionContext;
245 }
246
Douglas Gregor45bcd432010-01-14 03:21:49 +0000247 /// \brief Specify whether nested-name-specifiers are allowed.
248 void allowNestedNameSpecifiers(bool Allow = true) {
249 AllowNestedNameSpecifiers = Allow;
250 }
251
Douglas Gregorb9d77572010-09-21 00:03:25 +0000252 /// \brief Return the semantic analysis object for which we are collecting
253 /// code completion results.
254 Sema &getSema() const { return SemaRef; }
255
Douglas Gregor218937c2011-02-01 19:23:04 +0000256 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000257 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000258
259 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000260
Douglas Gregore495b7f2010-01-14 00:20:49 +0000261 /// \brief Determine whether the given declaration is at all interesting
262 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000263 ///
264 /// \param ND the declaration that we are inspecting.
265 ///
266 /// \param AsNestedNameSpecifier will be set true if this declaration is
267 /// only interesting when it is a nested-name-specifier.
268 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000269
270 /// \brief Check whether the result is hidden by the Hiding declaration.
271 ///
272 /// \returns true if the result is hidden and cannot be found, false if
273 /// the hidden result could still be found. When false, \p R may be
274 /// modified to describe how the result can be found (e.g., via extra
275 /// qualification).
276 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
277 NamedDecl *Hiding);
278
Douglas Gregor86d9a522009-09-21 16:56:56 +0000279 /// \brief Add a new result to this result set (if it isn't already in one
280 /// of the shadow maps), or replace an existing result (for, e.g., a
281 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000282 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000283 /// \param R the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000284 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000285 /// \param CurContext the context in which this result will be named.
Douglas Gregor456c4a12009-09-21 20:12:40 +0000286 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000287
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000288 /// \brief Add a new result to this result set, where we already know
289 /// the hiding declation (if any).
290 ///
291 /// \param R the result to add (if it is unique).
292 ///
293 /// \param CurContext the context in which this result will be named.
294 ///
295 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000296 ///
297 /// \param InBaseClass whether the result was found in a base
298 /// class of the searched context.
299 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
300 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000301
Douglas Gregora4477812010-01-14 16:01:26 +0000302 /// \brief Add a new non-declaration result to this result set.
303 void AddResult(Result R);
304
Douglas Gregor86d9a522009-09-21 16:56:56 +0000305 /// \brief Enter into a new scope.
306 void EnterNewScope();
307
308 /// \brief Exit from the current scope.
309 void ExitScope();
310
Douglas Gregor55385fe2009-11-18 04:19:12 +0000311 /// \brief Ignore this declaration, if it is seen again.
312 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
313
Douglas Gregor86d9a522009-09-21 16:56:56 +0000314 /// \name Name lookup predicates
315 ///
316 /// These predicates can be passed to the name lookup functions to filter the
317 /// results of name lookup. All of the predicates have the same type, so that
318 ///
319 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000320 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000321 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000322 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000323 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000324 bool IsNestedNameSpecifier(NamedDecl *ND) const;
325 bool IsEnum(NamedDecl *ND) const;
326 bool IsClassOrStruct(NamedDecl *ND) const;
327 bool IsUnion(NamedDecl *ND) const;
328 bool IsNamespace(NamedDecl *ND) const;
329 bool IsNamespaceOrAlias(NamedDecl *ND) const;
330 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000331 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000332 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000333 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000334 bool IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000335 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000336 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000337 //@}
338 };
339}
340
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000341class ResultBuilder::ShadowMapEntry::iterator {
342 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
343 unsigned SingleDeclIndex;
344
345public:
346 typedef DeclIndexPair value_type;
347 typedef value_type reference;
348 typedef std::ptrdiff_t difference_type;
349 typedef std::input_iterator_tag iterator_category;
350
351 class pointer {
352 DeclIndexPair Value;
353
354 public:
355 pointer(const DeclIndexPair &Value) : Value(Value) { }
356
357 const DeclIndexPair *operator->() const {
358 return &Value;
359 }
360 };
361
362 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
363
364 iterator(NamedDecl *SingleDecl, unsigned Index)
365 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
366
367 iterator(const DeclIndexPair *Iterator)
368 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
369
370 iterator &operator++() {
371 if (DeclOrIterator.is<NamedDecl *>()) {
372 DeclOrIterator = (NamedDecl *)0;
373 SingleDeclIndex = 0;
374 return *this;
375 }
376
377 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
378 ++I;
379 DeclOrIterator = I;
380 return *this;
381 }
382
Chris Lattner66392d42010-09-04 18:12:20 +0000383 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000384 iterator tmp(*this);
385 ++(*this);
386 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000387 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000388
389 reference operator*() const {
390 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
391 return reference(ND, SingleDeclIndex);
392
Douglas Gregord490f952009-12-06 21:27:58 +0000393 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000394 }
395
396 pointer operator->() const {
397 return pointer(**this);
398 }
399
400 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000401 return X.DeclOrIterator.getOpaqueValue()
402 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000403 X.SingleDeclIndex == Y.SingleDeclIndex;
404 }
405
406 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000407 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000408 }
409};
410
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000411ResultBuilder::ShadowMapEntry::iterator
412ResultBuilder::ShadowMapEntry::begin() const {
413 if (DeclOrVector.isNull())
414 return iterator();
415
416 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
417 return iterator(ND, SingleDeclIndex);
418
419 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
420}
421
422ResultBuilder::ShadowMapEntry::iterator
423ResultBuilder::ShadowMapEntry::end() const {
424 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
425 return iterator();
426
427 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
428}
429
Douglas Gregor456c4a12009-09-21 20:12:40 +0000430/// \brief Compute the qualification required to get from the current context
431/// (\p CurContext) to the target context (\p TargetContext).
432///
433/// \param Context the AST context in which the qualification will be used.
434///
435/// \param CurContext the context where an entity is being named, which is
436/// typically based on the current scope.
437///
438/// \param TargetContext the context in which the named entity actually
439/// resides.
440///
441/// \returns a nested name specifier that refers into the target context, or
442/// NULL if no qualification is needed.
443static NestedNameSpecifier *
444getRequiredQualification(ASTContext &Context,
445 DeclContext *CurContext,
446 DeclContext *TargetContext) {
Chris Lattner5f9e2722011-07-23 10:55:15 +0000447 SmallVector<DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000448
449 for (DeclContext *CommonAncestor = TargetContext;
450 CommonAncestor && !CommonAncestor->Encloses(CurContext);
451 CommonAncestor = CommonAncestor->getLookupParent()) {
452 if (CommonAncestor->isTransparentContext() ||
453 CommonAncestor->isFunctionOrMethod())
454 continue;
455
456 TargetParents.push_back(CommonAncestor);
457 }
458
459 NestedNameSpecifier *Result = 0;
460 while (!TargetParents.empty()) {
461 DeclContext *Parent = TargetParents.back();
462 TargetParents.pop_back();
463
Douglas Gregorfb629412010-08-23 21:17:50 +0000464 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
465 if (!Namespace->getIdentifier())
466 continue;
467
Douglas Gregor456c4a12009-09-21 20:12:40 +0000468 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000469 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000470 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
471 Result = NestedNameSpecifier::Create(Context, Result,
472 false,
473 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000474 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000475 return Result;
476}
477
Douglas Gregor45bcd432010-01-14 03:21:49 +0000478bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
479 bool &AsNestedNameSpecifier) const {
480 AsNestedNameSpecifier = false;
481
Douglas Gregore495b7f2010-01-14 00:20:49 +0000482 ND = ND->getUnderlyingDecl();
483 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000484
485 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000486 if (!ND->getDeclName())
487 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000488
489 // Friend declarations and declarations introduced due to friends are never
490 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000491 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000492 return false;
493
Douglas Gregor76282942009-12-11 17:31:05 +0000494 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000495 if (isa<ClassTemplateSpecializationDecl>(ND) ||
496 isa<ClassTemplatePartialSpecializationDecl>(ND))
497 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000498
Douglas Gregor76282942009-12-11 17:31:05 +0000499 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000500 if (isa<UsingDecl>(ND))
501 return false;
502
503 // Some declarations have reserved names that we don't want to ever show.
504 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000505 // __va_list_tag is a freak of nature. Find it and skip it.
506 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000507 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000508
Douglas Gregorf52cede2009-10-09 22:16:47 +0000509 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000510 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000511 //
512 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000513 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000514 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000515 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000516 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
517 (ND->getLocation().isInvalid() ||
518 SemaRef.SourceMgr.isInSystemHeader(
519 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000520 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000521 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000522 }
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000523
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000524 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
525 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
526 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000527 Filter != &ResultBuilder::IsNamespaceOrAlias &&
528 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000529 AsNestedNameSpecifier = true;
530
Douglas Gregor86d9a522009-09-21 16:56:56 +0000531 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000532 if (Filter && !(this->*Filter)(ND)) {
533 // Check whether it is interesting as a nested-name-specifier.
David Blaikie4e4d0842012-03-11 07:00:24 +0000534 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor45bcd432010-01-14 03:21:49 +0000535 IsNestedNameSpecifier(ND) &&
536 (Filter != &ResultBuilder::IsMember ||
537 (isa<CXXRecordDecl>(ND) &&
538 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
539 AsNestedNameSpecifier = true;
540 return true;
541 }
542
Douglas Gregore495b7f2010-01-14 00:20:49 +0000543 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000544 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000545 // ... then it must be interesting!
546 return true;
547}
548
Douglas Gregor6660d842010-01-14 00:41:07 +0000549bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
550 NamedDecl *Hiding) {
551 // In C, there is no way to refer to a hidden name.
552 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
553 // name if we introduce the tag type.
David Blaikie4e4d0842012-03-11 07:00:24 +0000554 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor6660d842010-01-14 00:41:07 +0000555 return true;
556
Sebastian Redl7a126a42010-08-31 00:36:30 +0000557 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000558
559 // There is no way to qualify a name declared in a function or method.
560 if (HiddenCtx->isFunctionOrMethod())
561 return true;
562
Sebastian Redl7a126a42010-08-31 00:36:30 +0000563 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000564 return true;
565
566 // We can refer to the result with the appropriate qualification. Do it.
567 R.Hidden = true;
568 R.QualifierIsInformative = false;
569
570 if (!R.Qualifier)
571 R.Qualifier = getRequiredQualification(SemaRef.Context,
572 CurContext,
573 R.Declaration->getDeclContext());
574 return false;
575}
576
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000577/// \brief A simplified classification of types used to determine whether two
578/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000579SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000580 switch (T->getTypeClass()) {
581 case Type::Builtin:
582 switch (cast<BuiltinType>(T)->getKind()) {
583 case BuiltinType::Void:
584 return STC_Void;
585
586 case BuiltinType::NullPtr:
587 return STC_Pointer;
588
589 case BuiltinType::Overload:
590 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000591 return STC_Other;
592
593 case BuiltinType::ObjCId:
594 case BuiltinType::ObjCClass:
595 case BuiltinType::ObjCSel:
596 return STC_ObjectiveC;
597
598 default:
599 return STC_Arithmetic;
600 }
David Blaikie7530c032012-01-17 06:56:22 +0000601
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000602 case Type::Complex:
603 return STC_Arithmetic;
604
605 case Type::Pointer:
606 return STC_Pointer;
607
608 case Type::BlockPointer:
609 return STC_Block;
610
611 case Type::LValueReference:
612 case Type::RValueReference:
613 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
614
615 case Type::ConstantArray:
616 case Type::IncompleteArray:
617 case Type::VariableArray:
618 case Type::DependentSizedArray:
619 return STC_Array;
620
621 case Type::DependentSizedExtVector:
622 case Type::Vector:
623 case Type::ExtVector:
624 return STC_Arithmetic;
625
626 case Type::FunctionProto:
627 case Type::FunctionNoProto:
628 return STC_Function;
629
630 case Type::Record:
631 return STC_Record;
632
633 case Type::Enum:
634 return STC_Arithmetic;
635
636 case Type::ObjCObject:
637 case Type::ObjCInterface:
638 case Type::ObjCObjectPointer:
639 return STC_ObjectiveC;
640
641 default:
642 return STC_Other;
643 }
644}
645
646/// \brief Get the type that a given expression will have if this declaration
647/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000648QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000649 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
650
651 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
652 return C.getTypeDeclType(Type);
653 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
654 return C.getObjCInterfaceType(Iface);
655
656 QualType T;
657 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000658 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000659 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000660 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000661 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000662 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000663 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
664 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
665 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
666 T = Property->getType();
667 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
668 T = Value->getType();
669 else
670 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000671
672 // Dig through references, function pointers, and block pointers to
673 // get down to the likely type of an expression when the entity is
674 // used.
675 do {
676 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
677 T = Ref->getPointeeType();
678 continue;
679 }
680
681 if (const PointerType *Pointer = T->getAs<PointerType>()) {
682 if (Pointer->getPointeeType()->isFunctionType()) {
683 T = Pointer->getPointeeType();
684 continue;
685 }
686
687 break;
688 }
689
690 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
691 T = Block->getPointeeType();
692 continue;
693 }
694
695 if (const FunctionType *Function = T->getAs<FunctionType>()) {
696 T = Function->getResultType();
697 continue;
698 }
699
700 break;
701 } while (true);
702
703 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000704}
705
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000706void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
707 // If this is an Objective-C method declaration whose selector matches our
708 // preferred selector, give it a priority boost.
709 if (!PreferredSelector.isNull())
710 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
711 if (PreferredSelector == Method->getSelector())
712 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000713
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000714 // If we have a preferred type, adjust the priority for results with exactly-
715 // matching or nearly-matching types.
716 if (!PreferredType.isNull()) {
717 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
718 if (!T.isNull()) {
719 CanQualType TC = SemaRef.Context.getCanonicalType(T);
720 // Check for exactly-matching types (modulo qualifiers).
721 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
722 R.Priority /= CCF_ExactTypeMatch;
723 // Check for nearly-matching types, based on classification of each.
724 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000725 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000726 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
727 R.Priority /= CCF_SimilarTypeMatch;
728 }
729 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000730}
731
Douglas Gregor6f942b22010-09-21 16:06:22 +0000732void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000733 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor6f942b22010-09-21 16:06:22 +0000734 !CompletionContext.wantConstructorResults())
735 return;
736
737 ASTContext &Context = SemaRef.Context;
738 NamedDecl *D = R.Declaration;
739 CXXRecordDecl *Record = 0;
740 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
741 Record = ClassTemplate->getTemplatedDecl();
742 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
743 // Skip specializations and partial specializations.
744 if (isa<ClassTemplateSpecializationDecl>(Record))
745 return;
746 } else {
747 // There are no constructors here.
748 return;
749 }
750
751 Record = Record->getDefinition();
752 if (!Record)
753 return;
754
755
756 QualType RecordTy = Context.getTypeDeclType(Record);
757 DeclarationName ConstructorName
758 = Context.DeclarationNames.getCXXConstructorName(
759 Context.getCanonicalType(RecordTy));
760 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
761 Ctors.first != Ctors.second; ++Ctors.first) {
762 R.Declaration = *Ctors.first;
763 R.CursorKind = getCursorKindForDecl(R.Declaration);
764 Results.push_back(R);
765 }
766}
767
Douglas Gregore495b7f2010-01-14 00:20:49 +0000768void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
769 assert(!ShadowMaps.empty() && "Must enter into a results scope");
770
771 if (R.Kind != Result::RK_Declaration) {
772 // For non-declaration results, just add the result.
773 Results.push_back(R);
774 return;
775 }
776
777 // Look through using declarations.
778 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
779 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
780 return;
781 }
782
783 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
784 unsigned IDNS = CanonDecl->getIdentifierNamespace();
785
Douglas Gregor45bcd432010-01-14 03:21:49 +0000786 bool AsNestedNameSpecifier = false;
787 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000788 return;
789
Douglas Gregor6f942b22010-09-21 16:06:22 +0000790 // C++ constructors are never found by name lookup.
791 if (isa<CXXConstructorDecl>(R.Declaration))
792 return;
793
Douglas Gregor86d9a522009-09-21 16:56:56 +0000794 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000795 ShadowMapEntry::iterator I, IEnd;
796 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
797 if (NamePos != SMap.end()) {
798 I = NamePos->second.begin();
799 IEnd = NamePos->second.end();
800 }
801
802 for (; I != IEnd; ++I) {
803 NamedDecl *ND = I->first;
804 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000805 if (ND->getCanonicalDecl() == CanonDecl) {
806 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000807 Results[Index].Declaration = R.Declaration;
808
Douglas Gregor86d9a522009-09-21 16:56:56 +0000809 // We're done.
810 return;
811 }
812 }
813
814 // This is a new declaration in this scope. However, check whether this
815 // declaration name is hidden by a similarly-named declaration in an outer
816 // scope.
817 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
818 --SMEnd;
819 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000820 ShadowMapEntry::iterator I, IEnd;
821 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
822 if (NamePos != SM->end()) {
823 I = NamePos->second.begin();
824 IEnd = NamePos->second.end();
825 }
826 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000827 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000828 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000829 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
830 Decl::IDNS_ObjCProtocol)))
831 continue;
832
833 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000834 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000835 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000836 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000837 continue;
838
839 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000840 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000841 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000842
843 break;
844 }
845 }
846
847 // Make sure that any given declaration only shows up in the result set once.
848 if (!AllDeclsFound.insert(CanonDecl))
849 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000850
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000851 // If the filter is for nested-name-specifiers, then this result starts a
852 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000853 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000854 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000855 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000856 } else
857 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000858
Douglas Gregor0563c262009-09-22 23:15:58 +0000859 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000860 if (R.QualifierIsInformative && !R.Qualifier &&
861 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000862 DeclContext *Ctx = R.Declaration->getDeclContext();
863 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
864 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
865 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
866 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
867 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
868 else
869 R.QualifierIsInformative = false;
870 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000871
Douglas Gregor86d9a522009-09-21 16:56:56 +0000872 // Insert this result into the set of results and into the current shadow
873 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000874 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000875 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000876
877 if (!AsNestedNameSpecifier)
878 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000879}
880
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000881void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000882 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000883 if (R.Kind != Result::RK_Declaration) {
884 // For non-declaration results, just add the result.
885 Results.push_back(R);
886 return;
887 }
888
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000889 // Look through using declarations.
890 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
891 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
892 return;
893 }
894
Douglas Gregor45bcd432010-01-14 03:21:49 +0000895 bool AsNestedNameSpecifier = false;
896 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000897 return;
898
Douglas Gregor6f942b22010-09-21 16:06:22 +0000899 // C++ constructors are never found by name lookup.
900 if (isa<CXXConstructorDecl>(R.Declaration))
901 return;
902
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000903 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
904 return;
Nick Lewycky173a37a2012-04-03 21:44:08 +0000905
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000906 // Make sure that any given declaration only shows up in the result set once.
907 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
908 return;
909
910 // If the filter is for nested-name-specifiers, then this result starts a
911 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000912 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000913 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000914 R.Priority = CCP_NestedNameSpecifier;
915 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000916 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
917 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000918 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000919 R.QualifierIsInformative = true;
920
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000921 // If this result is supposed to have an informative qualifier, add one.
922 if (R.QualifierIsInformative && !R.Qualifier &&
923 !R.StartsNestedNameSpecifier) {
924 DeclContext *Ctx = R.Declaration->getDeclContext();
925 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
926 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
927 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
928 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000929 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000930 else
931 R.QualifierIsInformative = false;
932 }
933
Douglas Gregor12e13132010-05-26 22:00:08 +0000934 // Adjust the priority if this result comes from a base class.
935 if (InBaseClass)
936 R.Priority += CCD_InBaseClass;
937
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000938 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000939
Douglas Gregor3cdee122010-08-26 16:36:48 +0000940 if (HasObjectTypeQualifiers)
941 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
942 if (Method->isInstance()) {
943 Qualifiers MethodQuals
944 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
945 if (ObjectTypeQualifiers == MethodQuals)
946 R.Priority += CCD_ObjectQualifierMatch;
947 else if (ObjectTypeQualifiers - MethodQuals) {
948 // The method cannot be invoked, because doing so would drop
949 // qualifiers.
950 return;
951 }
952 }
953
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000954 // Insert this result into the set of results.
955 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000956
957 if (!AsNestedNameSpecifier)
958 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000959}
960
Douglas Gregora4477812010-01-14 16:01:26 +0000961void ResultBuilder::AddResult(Result R) {
962 assert(R.Kind != Result::RK_Declaration &&
963 "Declaration results need more context");
964 Results.push_back(R);
965}
966
Douglas Gregor86d9a522009-09-21 16:56:56 +0000967/// \brief Enter into a new scope.
968void ResultBuilder::EnterNewScope() {
969 ShadowMaps.push_back(ShadowMap());
970}
971
972/// \brief Exit from the current scope.
973void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000974 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
975 EEnd = ShadowMaps.back().end();
976 E != EEnd;
977 ++E)
978 E->second.Destroy();
979
Douglas Gregor86d9a522009-09-21 16:56:56 +0000980 ShadowMaps.pop_back();
981}
982
Douglas Gregor791215b2009-09-21 20:51:25 +0000983/// \brief Determines whether this given declaration will be found by
984/// ordinary name lookup.
985bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000986 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
987
Douglas Gregor791215b2009-09-21 20:51:25 +0000988 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +0000989 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000990 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +0000991 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +0000992 if (isa<ObjCIvarDecl>(ND))
993 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +0000994 }
995
Douglas Gregor791215b2009-09-21 20:51:25 +0000996 return ND->getIdentifierNamespace() & IDNS;
997}
998
Douglas Gregor01dfea02010-01-10 23:08:15 +0000999/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001000/// ordinary name lookup but is not a type name.
1001bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
1002 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1003 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1004 return false;
1005
1006 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001007 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001008 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001009 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001010 if (isa<ObjCIvarDecl>(ND))
1011 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001012 }
1013
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001014 return ND->getIdentifierNamespace() & IDNS;
1015}
1016
Douglas Gregorf9578432010-07-28 21:50:18 +00001017bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
1018 if (!IsOrdinaryNonTypeName(ND))
1019 return 0;
1020
1021 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
1022 if (VD->getType()->isIntegralOrEnumerationType())
1023 return true;
1024
1025 return false;
1026}
1027
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001028/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001029/// ordinary name lookup.
1030bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001031 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1032
Douglas Gregor01dfea02010-01-10 23:08:15 +00001033 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001034 if (SemaRef.getLangOpts().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001035 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001036
1037 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001038 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1039 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001040}
1041
Douglas Gregor86d9a522009-09-21 16:56:56 +00001042/// \brief Determines whether the given declaration is suitable as the
1043/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1044bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1045 // Allow us to find class templates, too.
1046 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1047 ND = ClassTemplate->getTemplatedDecl();
1048
1049 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1050}
1051
1052/// \brief Determines whether the given declaration is an enumeration.
1053bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1054 return isa<EnumDecl>(ND);
1055}
1056
1057/// \brief Determines whether the given declaration is a class or struct.
1058bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1059 // Allow us to find class templates, too.
1060 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1061 ND = ClassTemplate->getTemplatedDecl();
1062
1063 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001064 return RD->getTagKind() == TTK_Class ||
1065 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001066
1067 return false;
1068}
1069
1070/// \brief Determines whether the given declaration is a union.
1071bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1072 // Allow us to find class templates, too.
1073 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1074 ND = ClassTemplate->getTemplatedDecl();
1075
1076 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001077 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001078
1079 return false;
1080}
1081
1082/// \brief Determines whether the given declaration is a namespace.
1083bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1084 return isa<NamespaceDecl>(ND);
1085}
1086
1087/// \brief Determines whether the given declaration is a namespace or
1088/// namespace alias.
1089bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1090 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1091}
1092
Douglas Gregor76282942009-12-11 17:31:05 +00001093/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001094bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001095 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1096 ND = Using->getTargetDecl();
1097
1098 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001099}
1100
Douglas Gregor76282942009-12-11 17:31:05 +00001101/// \brief Determines which members of a class should be visible via
1102/// "." or "->". Only value declarations, nested name specifiers, and
1103/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001104bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001105 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1106 ND = Using->getTargetDecl();
1107
Douglas Gregorce821962009-12-11 18:14:22 +00001108 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1109 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001110}
1111
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001112static bool isObjCReceiverType(ASTContext &C, QualType T) {
1113 T = C.getCanonicalType(T);
1114 switch (T->getTypeClass()) {
1115 case Type::ObjCObject:
1116 case Type::ObjCInterface:
1117 case Type::ObjCObjectPointer:
1118 return true;
1119
1120 case Type::Builtin:
1121 switch (cast<BuiltinType>(T)->getKind()) {
1122 case BuiltinType::ObjCId:
1123 case BuiltinType::ObjCClass:
1124 case BuiltinType::ObjCSel:
1125 return true;
1126
1127 default:
1128 break;
1129 }
1130 return false;
1131
1132 default:
1133 break;
1134 }
1135
David Blaikie4e4d0842012-03-11 07:00:24 +00001136 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001137 return false;
1138
1139 // FIXME: We could perform more analysis here to determine whether a
1140 // particular class type has any conversions to Objective-C types. For now,
1141 // just accept all class types.
1142 return T->isDependentType() || T->isRecordType();
1143}
1144
1145bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1146 QualType T = getDeclUsageType(SemaRef.Context, ND);
1147 if (T.isNull())
1148 return false;
1149
1150 T = SemaRef.Context.getBaseElementType(T);
1151 return isObjCReceiverType(SemaRef.Context, T);
1152}
1153
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001154bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(NamedDecl *ND) const {
1155 if (IsObjCMessageReceiver(ND))
1156 return true;
1157
1158 VarDecl *Var = dyn_cast<VarDecl>(ND);
1159 if (!Var)
1160 return false;
1161
1162 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1163}
1164
Douglas Gregorfb629412010-08-23 21:17:50 +00001165bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001166 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1167 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001168 return false;
1169
1170 QualType T = getDeclUsageType(SemaRef.Context, ND);
1171 if (T.isNull())
1172 return false;
1173
1174 T = SemaRef.Context.getBaseElementType(T);
1175 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1176 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001177 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001178}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001179
Douglas Gregor52779fb2010-09-23 23:01:17 +00001180bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1181 return false;
1182}
1183
James Dennettde23c7e2012-06-17 05:33:25 +00001184/// \brief Determines whether the given declaration is an Objective-C
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001185/// instance variable.
1186bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1187 return isa<ObjCIvarDecl>(ND);
1188}
1189
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001190namespace {
1191 /// \brief Visible declaration consumer that adds a code-completion result
1192 /// for each visible declaration.
1193 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1194 ResultBuilder &Results;
1195 DeclContext *CurContext;
1196
1197 public:
1198 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1199 : Results(Results), CurContext(CurContext) { }
1200
Erik Verbruggend1205962011-10-06 07:27:49 +00001201 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1202 bool InBaseClass) {
1203 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001204 if (Ctx)
1205 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1206
Erik Verbruggend1205962011-10-06 07:27:49 +00001207 ResultBuilder::Result Result(ND, 0, false, Accessible);
1208 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001209 }
1210 };
1211}
1212
Douglas Gregor86d9a522009-09-21 16:56:56 +00001213/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001214static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001215 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001216 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001217 Results.AddResult(Result("short", CCP_Type));
1218 Results.AddResult(Result("long", CCP_Type));
1219 Results.AddResult(Result("signed", CCP_Type));
1220 Results.AddResult(Result("unsigned", CCP_Type));
1221 Results.AddResult(Result("void", CCP_Type));
1222 Results.AddResult(Result("char", CCP_Type));
1223 Results.AddResult(Result("int", CCP_Type));
1224 Results.AddResult(Result("float", CCP_Type));
1225 Results.AddResult(Result("double", CCP_Type));
1226 Results.AddResult(Result("enum", CCP_Type));
1227 Results.AddResult(Result("struct", CCP_Type));
1228 Results.AddResult(Result("union", CCP_Type));
1229 Results.AddResult(Result("const", CCP_Type));
1230 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001231
Douglas Gregor86d9a522009-09-21 16:56:56 +00001232 if (LangOpts.C99) {
1233 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001234 Results.AddResult(Result("_Complex", CCP_Type));
1235 Results.AddResult(Result("_Imaginary", CCP_Type));
1236 Results.AddResult(Result("_Bool", CCP_Type));
1237 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001238 }
1239
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001240 CodeCompletionBuilder Builder(Results.getAllocator(),
1241 Results.getCodeCompletionTUInfo());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001242 if (LangOpts.CPlusPlus) {
1243 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001244 Results.AddResult(Result("bool", CCP_Type +
1245 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001246 Results.AddResult(Result("class", CCP_Type));
1247 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001248
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001249 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001250 Builder.AddTypedTextChunk("typename");
1251 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1252 Builder.AddPlaceholderChunk("qualifier");
1253 Builder.AddTextChunk("::");
1254 Builder.AddPlaceholderChunk("name");
1255 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001256
Douglas Gregor86d9a522009-09-21 16:56:56 +00001257 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001258 Results.AddResult(Result("auto", CCP_Type));
1259 Results.AddResult(Result("char16_t", CCP_Type));
1260 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001261
Douglas Gregor218937c2011-02-01 19:23:04 +00001262 Builder.AddTypedTextChunk("decltype");
1263 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1264 Builder.AddPlaceholderChunk("expression");
1265 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1266 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001267 }
1268 }
1269
1270 // GNU extensions
1271 if (LangOpts.GNUMode) {
1272 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001273 // Results.AddResult(Result("_Decimal32"));
1274 // Results.AddResult(Result("_Decimal64"));
1275 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001276
Douglas Gregor218937c2011-02-01 19:23:04 +00001277 Builder.AddTypedTextChunk("typeof");
1278 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1279 Builder.AddPlaceholderChunk("expression");
1280 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001281
Douglas Gregor218937c2011-02-01 19:23:04 +00001282 Builder.AddTypedTextChunk("typeof");
1283 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1284 Builder.AddPlaceholderChunk("type");
1285 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1286 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001287 }
1288}
1289
John McCallf312b1e2010-08-26 23:41:50 +00001290static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001291 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001292 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001293 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001294 // Note: we don't suggest either "auto" or "register", because both
1295 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1296 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001297 Results.AddResult(Result("extern"));
1298 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001299}
1300
John McCallf312b1e2010-08-26 23:41:50 +00001301static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001302 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001303 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001304 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001305 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001306 case Sema::PCC_Class:
1307 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001308 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001309 Results.AddResult(Result("explicit"));
1310 Results.AddResult(Result("friend"));
1311 Results.AddResult(Result("mutable"));
1312 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001313 }
1314 // Fall through
1315
John McCallf312b1e2010-08-26 23:41:50 +00001316 case Sema::PCC_ObjCInterface:
1317 case Sema::PCC_ObjCImplementation:
1318 case Sema::PCC_Namespace:
1319 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001320 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001321 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001322 break;
1323
John McCallf312b1e2010-08-26 23:41:50 +00001324 case Sema::PCC_ObjCInstanceVariableList:
1325 case Sema::PCC_Expression:
1326 case Sema::PCC_Statement:
1327 case Sema::PCC_ForInit:
1328 case Sema::PCC_Condition:
1329 case Sema::PCC_RecoveryInFunction:
1330 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001331 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001332 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001333 break;
1334 }
1335}
1336
Douglas Gregorbca403c2010-01-13 23:51:12 +00001337static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1338static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1339static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001340 ResultBuilder &Results,
1341 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001342static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001343 ResultBuilder &Results,
1344 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001345static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001346 ResultBuilder &Results,
1347 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001348static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001349
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001350static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001351 CodeCompletionBuilder Builder(Results.getAllocator(),
1352 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00001353 Builder.AddTypedTextChunk("typedef");
1354 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1355 Builder.AddPlaceholderChunk("type");
1356 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1357 Builder.AddPlaceholderChunk("name");
1358 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001359}
1360
John McCallf312b1e2010-08-26 23:41:50 +00001361static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001362 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001363 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001364 case Sema::PCC_Namespace:
1365 case Sema::PCC_Class:
1366 case Sema::PCC_ObjCInstanceVariableList:
1367 case Sema::PCC_Template:
1368 case Sema::PCC_MemberTemplate:
1369 case Sema::PCC_Statement:
1370 case Sema::PCC_RecoveryInFunction:
1371 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001372 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001373 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001374 return true;
1375
John McCallf312b1e2010-08-26 23:41:50 +00001376 case Sema::PCC_Expression:
1377 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001378 return LangOpts.CPlusPlus;
1379
1380 case Sema::PCC_ObjCInterface:
1381 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001382 return false;
1383
John McCallf312b1e2010-08-26 23:41:50 +00001384 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001385 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001386 }
David Blaikie7530c032012-01-17 06:56:22 +00001387
1388 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001389}
1390
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001391static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1392 const Preprocessor &PP) {
1393 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001394 Policy.AnonymousTagLocations = false;
1395 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001396 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001397 return Policy;
1398}
1399
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001400/// \brief Retrieve a printing policy suitable for code completion.
1401static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1402 return getCompletionPrintingPolicy(S.Context, S.PP);
1403}
1404
Douglas Gregor8ca72082011-10-18 21:20:17 +00001405/// \brief Retrieve the string representation of the given type as a string
1406/// that has the appropriate lifetime for code completion.
1407///
1408/// This routine provides a fast path where we provide constant strings for
1409/// common type names.
1410static const char *GetCompletionTypeString(QualType T,
1411 ASTContext &Context,
1412 const PrintingPolicy &Policy,
1413 CodeCompletionAllocator &Allocator) {
1414 if (!T.getLocalQualifiers()) {
1415 // Built-in type names are constant strings.
1416 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidis27a00972012-05-05 04:20:28 +00001417 return BT->getNameAsCString(Policy);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001418
1419 // Anonymous tag types are constant strings.
1420 if (const TagType *TagT = dyn_cast<TagType>(T))
1421 if (TagDecl *Tag = TagT->getDecl())
1422 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1423 switch (Tag->getTagKind()) {
1424 case TTK_Struct: return "struct <anonymous>";
1425 case TTK_Class: return "class <anonymous>";
1426 case TTK_Union: return "union <anonymous>";
1427 case TTK_Enum: return "enum <anonymous>";
1428 }
1429 }
1430 }
1431
1432 // Slow path: format the type as a string.
1433 std::string Result;
1434 T.getAsStringInternal(Result, Policy);
1435 return Allocator.CopyString(Result);
1436}
1437
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001438/// \brief Add a completion for "this", if we're in a member function.
1439static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1440 QualType ThisTy = S.getCurrentThisType();
1441 if (ThisTy.isNull())
1442 return;
1443
1444 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001445 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001446 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1447 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1448 S.Context,
1449 Policy,
1450 Allocator));
1451 Builder.AddTypedTextChunk("this");
1452 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1453}
1454
Douglas Gregor01dfea02010-01-10 23:08:15 +00001455/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001456static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001457 Scope *S,
1458 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001459 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001460 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001461 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor8ca72082011-10-18 21:20:17 +00001462 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001463
John McCall0a2c5e22010-08-25 06:19:51 +00001464 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001465 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001466 case Sema::PCC_Namespace:
David Blaikie4e4d0842012-03-11 07:00:24 +00001467 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001468 if (Results.includeCodePatterns()) {
1469 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001470 Builder.AddTypedTextChunk("namespace");
1471 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1472 Builder.AddPlaceholderChunk("identifier");
1473 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1474 Builder.AddPlaceholderChunk("declarations");
1475 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1476 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1477 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001478 }
1479
Douglas Gregor01dfea02010-01-10 23:08:15 +00001480 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001481 Builder.AddTypedTextChunk("namespace");
1482 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1483 Builder.AddPlaceholderChunk("name");
1484 Builder.AddChunk(CodeCompletionString::CK_Equal);
1485 Builder.AddPlaceholderChunk("namespace");
1486 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001487
1488 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001489 Builder.AddTypedTextChunk("using");
1490 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1491 Builder.AddTextChunk("namespace");
1492 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1493 Builder.AddPlaceholderChunk("identifier");
1494 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001495
1496 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001497 Builder.AddTypedTextChunk("asm");
1498 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1499 Builder.AddPlaceholderChunk("string-literal");
1500 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1501 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001502
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001503 if (Results.includeCodePatterns()) {
1504 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001505 Builder.AddTypedTextChunk("template");
1506 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1507 Builder.AddPlaceholderChunk("declaration");
1508 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001509 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001510 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001511
David Blaikie4e4d0842012-03-11 07:00:24 +00001512 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001513 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001514
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001515 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001516 // Fall through
1517
John McCallf312b1e2010-08-26 23:41:50 +00001518 case Sema::PCC_Class:
David Blaikie4e4d0842012-03-11 07:00:24 +00001519 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001520 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001521 Builder.AddTypedTextChunk("using");
1522 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1523 Builder.AddPlaceholderChunk("qualifier");
1524 Builder.AddTextChunk("::");
1525 Builder.AddPlaceholderChunk("name");
1526 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001527
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001528 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001529 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001530 Builder.AddTypedTextChunk("using");
1531 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1532 Builder.AddTextChunk("typename");
1533 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1534 Builder.AddPlaceholderChunk("qualifier");
1535 Builder.AddTextChunk("::");
1536 Builder.AddPlaceholderChunk("name");
1537 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001538 }
1539
John McCallf312b1e2010-08-26 23:41:50 +00001540 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001541 AddTypedefResult(Results);
1542
Douglas Gregor01dfea02010-01-10 23:08:15 +00001543 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001544 Builder.AddTypedTextChunk("public");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001545 if (Results.includeCodePatterns())
1546 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001547 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001548
1549 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001550 Builder.AddTypedTextChunk("protected");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001551 if (Results.includeCodePatterns())
1552 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001553 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001554
1555 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001556 Builder.AddTypedTextChunk("private");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001557 if (Results.includeCodePatterns())
1558 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001559 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001560 }
1561 }
1562 // Fall through
1563
John McCallf312b1e2010-08-26 23:41:50 +00001564 case Sema::PCC_Template:
1565 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001566 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001567 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001568 Builder.AddTypedTextChunk("template");
1569 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1570 Builder.AddPlaceholderChunk("parameters");
1571 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1572 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001573 }
1574
David Blaikie4e4d0842012-03-11 07:00:24 +00001575 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1576 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001577 break;
1578
John McCallf312b1e2010-08-26 23:41:50 +00001579 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001580 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1581 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1582 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001583 break;
1584
John McCallf312b1e2010-08-26 23:41:50 +00001585 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001586 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1587 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1588 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001589 break;
1590
John McCallf312b1e2010-08-26 23:41:50 +00001591 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001592 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001593 break;
1594
John McCallf312b1e2010-08-26 23:41:50 +00001595 case Sema::PCC_RecoveryInFunction:
1596 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001597 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001598
David Blaikie4e4d0842012-03-11 07:00:24 +00001599 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1600 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001601 Builder.AddTypedTextChunk("try");
1602 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1603 Builder.AddPlaceholderChunk("statements");
1604 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1605 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1606 Builder.AddTextChunk("catch");
1607 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1608 Builder.AddPlaceholderChunk("declaration");
1609 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1610 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1611 Builder.AddPlaceholderChunk("statements");
1612 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1613 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1614 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001615 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001616 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001617 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001618
Douglas Gregord8e8a582010-05-25 21:41:55 +00001619 if (Results.includeCodePatterns()) {
1620 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001621 Builder.AddTypedTextChunk("if");
1622 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001623 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001624 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001625 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001626 Builder.AddPlaceholderChunk("expression");
1627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1628 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1629 Builder.AddPlaceholderChunk("statements");
1630 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1631 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1632 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001633
Douglas Gregord8e8a582010-05-25 21:41:55 +00001634 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001635 Builder.AddTypedTextChunk("switch");
1636 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001637 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001638 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001639 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001640 Builder.AddPlaceholderChunk("expression");
1641 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1642 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1643 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1644 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1645 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001646 }
1647
Douglas Gregor01dfea02010-01-10 23:08:15 +00001648 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001649 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001650 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001651 Builder.AddTypedTextChunk("case");
1652 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1653 Builder.AddPlaceholderChunk("expression");
1654 Builder.AddChunk(CodeCompletionString::CK_Colon);
1655 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001656
1657 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001658 Builder.AddTypedTextChunk("default");
1659 Builder.AddChunk(CodeCompletionString::CK_Colon);
1660 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001661 }
1662
Douglas Gregord8e8a582010-05-25 21:41:55 +00001663 if (Results.includeCodePatterns()) {
1664 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001665 Builder.AddTypedTextChunk("while");
1666 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001667 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001668 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001669 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001670 Builder.AddPlaceholderChunk("expression");
1671 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1672 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1673 Builder.AddPlaceholderChunk("statements");
1674 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1675 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1676 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001677
1678 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001679 Builder.AddTypedTextChunk("do");
1680 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1681 Builder.AddPlaceholderChunk("statements");
1682 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1683 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1684 Builder.AddTextChunk("while");
1685 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1686 Builder.AddPlaceholderChunk("expression");
1687 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1688 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001689
Douglas Gregord8e8a582010-05-25 21:41:55 +00001690 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001691 Builder.AddTypedTextChunk("for");
1692 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001693 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001694 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001695 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001696 Builder.AddPlaceholderChunk("init-expression");
1697 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1698 Builder.AddPlaceholderChunk("condition");
1699 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1700 Builder.AddPlaceholderChunk("inc-expression");
1701 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1702 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1703 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1704 Builder.AddPlaceholderChunk("statements");
1705 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1706 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1707 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001708 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001709
1710 if (S->getContinueParent()) {
1711 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001712 Builder.AddTypedTextChunk("continue");
1713 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001714 }
1715
1716 if (S->getBreakParent()) {
1717 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001718 Builder.AddTypedTextChunk("break");
1719 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001720 }
1721
1722 // "return expression ;" or "return ;", depending on whether we
1723 // know the function is void or not.
1724 bool isVoid = false;
1725 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1726 isVoid = Function->getResultType()->isVoidType();
1727 else if (ObjCMethodDecl *Method
1728 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1729 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001730 else if (SemaRef.getCurBlock() &&
1731 !SemaRef.getCurBlock()->ReturnType.isNull())
1732 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001733 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001734 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001735 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1736 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001737 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001738 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001739
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001740 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001741 Builder.AddTypedTextChunk("goto");
1742 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1743 Builder.AddPlaceholderChunk("label");
1744 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001745
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001746 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001747 Builder.AddTypedTextChunk("using");
1748 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1749 Builder.AddTextChunk("namespace");
1750 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1751 Builder.AddPlaceholderChunk("identifier");
1752 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001753 }
1754
1755 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001756 case Sema::PCC_ForInit:
1757 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001758 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001759 // Fall through: conditions and statements can have expressions.
1760
Douglas Gregor02688102010-09-14 23:59:36 +00001761 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001762 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001763 CCC == Sema::PCC_ParenthesizedExpression) {
1764 // (__bridge <type>)<expression>
1765 Builder.AddTypedTextChunk("__bridge");
1766 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1767 Builder.AddPlaceholderChunk("type");
1768 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1769 Builder.AddPlaceholderChunk("expression");
1770 Results.AddResult(Result(Builder.TakeString()));
1771
1772 // (__bridge_transfer <Objective-C type>)<expression>
1773 Builder.AddTypedTextChunk("__bridge_transfer");
1774 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1775 Builder.AddPlaceholderChunk("Objective-C type");
1776 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1777 Builder.AddPlaceholderChunk("expression");
1778 Results.AddResult(Result(Builder.TakeString()));
1779
1780 // (__bridge_retained <CF type>)<expression>
1781 Builder.AddTypedTextChunk("__bridge_retained");
1782 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1783 Builder.AddPlaceholderChunk("CF type");
1784 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1785 Builder.AddPlaceholderChunk("expression");
1786 Results.AddResult(Result(Builder.TakeString()));
1787 }
1788 // Fall through
1789
John McCallf312b1e2010-08-26 23:41:50 +00001790 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001791 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001792 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001793 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001794
Douglas Gregor8ca72082011-10-18 21:20:17 +00001795 // true
1796 Builder.AddResultTypeChunk("bool");
1797 Builder.AddTypedTextChunk("true");
1798 Results.AddResult(Result(Builder.TakeString()));
1799
1800 // false
1801 Builder.AddResultTypeChunk("bool");
1802 Builder.AddTypedTextChunk("false");
1803 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001804
David Blaikie4e4d0842012-03-11 07:00:24 +00001805 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001806 // dynamic_cast < type-id > ( expression )
1807 Builder.AddTypedTextChunk("dynamic_cast");
1808 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1809 Builder.AddPlaceholderChunk("type");
1810 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1811 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1812 Builder.AddPlaceholderChunk("expression");
1813 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1814 Results.AddResult(Result(Builder.TakeString()));
1815 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001816
1817 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001818 Builder.AddTypedTextChunk("static_cast");
1819 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1820 Builder.AddPlaceholderChunk("type");
1821 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1822 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1823 Builder.AddPlaceholderChunk("expression");
1824 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1825 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001826
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001827 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001828 Builder.AddTypedTextChunk("reinterpret_cast");
1829 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1830 Builder.AddPlaceholderChunk("type");
1831 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1832 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1833 Builder.AddPlaceholderChunk("expression");
1834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1835 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001836
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001837 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001838 Builder.AddTypedTextChunk("const_cast");
1839 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1840 Builder.AddPlaceholderChunk("type");
1841 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1842 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1843 Builder.AddPlaceholderChunk("expression");
1844 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1845 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001846
David Blaikie4e4d0842012-03-11 07:00:24 +00001847 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001848 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001849 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001850 Builder.AddTypedTextChunk("typeid");
1851 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1852 Builder.AddPlaceholderChunk("expression-or-type");
1853 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1854 Results.AddResult(Result(Builder.TakeString()));
1855 }
1856
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001857 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001858 Builder.AddTypedTextChunk("new");
1859 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1860 Builder.AddPlaceholderChunk("type");
1861 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1862 Builder.AddPlaceholderChunk("expressions");
1863 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1864 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001865
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001866 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001867 Builder.AddTypedTextChunk("new");
1868 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1869 Builder.AddPlaceholderChunk("type");
1870 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1871 Builder.AddPlaceholderChunk("size");
1872 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1873 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1874 Builder.AddPlaceholderChunk("expressions");
1875 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1876 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001877
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001878 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001879 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001880 Builder.AddTypedTextChunk("delete");
1881 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1882 Builder.AddPlaceholderChunk("expression");
1883 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001884
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001885 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001886 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001887 Builder.AddTypedTextChunk("delete");
1888 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1889 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1890 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1891 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1892 Builder.AddPlaceholderChunk("expression");
1893 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001894
David Blaikie4e4d0842012-03-11 07:00:24 +00001895 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001896 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001897 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001898 Builder.AddTypedTextChunk("throw");
1899 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1900 Builder.AddPlaceholderChunk("expression");
1901 Results.AddResult(Result(Builder.TakeString()));
1902 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001903
Douglas Gregor12e13132010-05-26 22:00:08 +00001904 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001905
David Blaikie4e4d0842012-03-11 07:00:24 +00001906 if (SemaRef.getLangOpts().CPlusPlus0x) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001907 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001908 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001909 Builder.AddTypedTextChunk("nullptr");
1910 Results.AddResult(Result(Builder.TakeString()));
1911
1912 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001913 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001914 Builder.AddTypedTextChunk("alignof");
1915 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1916 Builder.AddPlaceholderChunk("type");
1917 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1918 Results.AddResult(Result(Builder.TakeString()));
1919
1920 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001921 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001922 Builder.AddTypedTextChunk("noexcept");
1923 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1924 Builder.AddPlaceholderChunk("expression");
1925 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1926 Results.AddResult(Result(Builder.TakeString()));
1927
1928 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001929 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001930 Builder.AddTypedTextChunk("sizeof...");
1931 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1932 Builder.AddPlaceholderChunk("parameter-pack");
1933 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1934 Results.AddResult(Result(Builder.TakeString()));
1935 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001936 }
1937
David Blaikie4e4d0842012-03-11 07:00:24 +00001938 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001939 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001940 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1941 // The interface can be NULL.
1942 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001943 if (ID->getSuperClass()) {
1944 std::string SuperType;
1945 SuperType = ID->getSuperClass()->getNameAsString();
1946 if (Method->isInstanceMethod())
1947 SuperType += " *";
1948
1949 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1950 Builder.AddTypedTextChunk("super");
1951 Results.AddResult(Result(Builder.TakeString()));
1952 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001953 }
1954
Douglas Gregorbca403c2010-01-13 23:51:12 +00001955 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001956 }
1957
Jordan Rosef70a8862012-06-30 21:33:57 +00001958 if (SemaRef.getLangOpts().C11) {
1959 // _Alignof
1960 Builder.AddResultTypeChunk("size_t");
1961 if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition())
1962 Builder.AddTypedTextChunk("alignof");
1963 else
1964 Builder.AddTypedTextChunk("_Alignof");
1965 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1966 Builder.AddPlaceholderChunk("type");
1967 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1968 Results.AddResult(Result(Builder.TakeString()));
1969 }
1970
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001971 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001972 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001973 Builder.AddTypedTextChunk("sizeof");
1974 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1975 Builder.AddPlaceholderChunk("expression-or-type");
1976 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1977 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001978 break;
1979 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001980
John McCallf312b1e2010-08-26 23:41:50 +00001981 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001982 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001983 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001984 }
1985
David Blaikie4e4d0842012-03-11 07:00:24 +00001986 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1987 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001988
David Blaikie4e4d0842012-03-11 07:00:24 +00001989 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001990 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001991}
1992
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001993/// \brief If the given declaration has an associated type, add it as a result
1994/// type chunk.
1995static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00001996 const PrintingPolicy &Policy,
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001997 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001998 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001999 if (!ND)
2000 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00002001
2002 // Skip constructors and conversion functions, which have their return types
2003 // built into their names.
2004 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
2005 return;
2006
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002007 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00002008 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002009 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
2010 T = Function->getResultType();
2011 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
2012 T = Method->getResultType();
2013 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
2014 T = FunTmpl->getTemplatedDecl()->getResultType();
2015 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
2016 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2017 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2018 /* Do nothing: ignore unresolved using declarations*/
John McCallf85e1932011-06-15 23:02:42 +00002019 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002020 T = Value->getType();
John McCallf85e1932011-06-15 23:02:42 +00002021 } else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002022 T = Property->getType();
2023
2024 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2025 return;
2026
Douglas Gregor8987b232011-09-27 23:30:47 +00002027 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002028 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002029}
2030
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002031static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002032 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002033 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2034 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002035 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002036 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002037 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002038 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002039 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002040 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002041 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002042 }
2043}
2044
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002045static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2046 std::string Result;
2047 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002048 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002049 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002050 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002051 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002052 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002053 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002054 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002055 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002056 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002057 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002058 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002059 return Result;
2060}
2061
Douglas Gregor83482d12010-08-24 16:15:59 +00002062static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002063 const PrintingPolicy &Policy,
Douglas Gregoraba48082010-08-29 19:47:46 +00002064 ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002065 bool SuppressName = false,
2066 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002067 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2068 if (Param->getType()->isDependentType() ||
2069 !Param->getType()->isBlockPointerType()) {
2070 // The argument for a dependent or non-block parameter is a placeholder
2071 // containing that parameter's type.
2072 std::string Result;
2073
Douglas Gregoraba48082010-08-29 19:47:46 +00002074 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002075 Result = Param->getIdentifier()->getName();
2076
John McCallf85e1932011-06-15 23:02:42 +00002077 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002078
2079 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002080 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2081 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002082 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002083 Result += Param->getIdentifier()->getName();
2084 }
2085 return Result;
2086 }
2087
2088 // The argument for a block pointer parameter is a block literal with
2089 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002090 FunctionTypeLoc *Block = 0;
2091 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002092 TypeLoc TL;
2093 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2094 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2095 while (true) {
2096 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002097 if (!SuppressBlock) {
2098 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2099 if (TypeSourceInfo *InnerTSInfo
2100 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2101 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2102 continue;
2103 }
2104 }
2105
2106 // Look through qualified types
2107 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2108 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002109 continue;
2110 }
2111 }
2112
Douglas Gregor83482d12010-08-24 16:15:59 +00002113 // Try to get the function prototype behind the block pointer type,
2114 // then we're done.
2115 if (BlockPointerTypeLoc *BlockPtr
2116 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002117 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002118 Block = dyn_cast<FunctionTypeLoc>(&TL);
2119 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002120 }
2121 break;
2122 }
2123 }
2124
2125 if (!Block) {
2126 // We were unable to find a FunctionProtoTypeLoc with parameter names
2127 // for the block; just use the parameter type as a placeholder.
2128 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002129 if (!ObjCMethodParam && Param->getIdentifier())
2130 Result = Param->getIdentifier()->getName();
2131
John McCallf85e1932011-06-15 23:02:42 +00002132 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002133
2134 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002135 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2136 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002137 if (Param->getIdentifier())
2138 Result += Param->getIdentifier()->getName();
2139 }
2140
2141 return Result;
2142 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002143
Douglas Gregor83482d12010-08-24 16:15:59 +00002144 // We have the function prototype behind the block pointer type, as it was
2145 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002146 std::string Result;
2147 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002148 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002149 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002150
2151 // Format the parameter list.
2152 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002153 if (!BlockProto || Block->getNumArgs() == 0) {
2154 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002155 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002156 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002157 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002158 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002159 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002160 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2161 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002162 Params += ", ";
2163 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2164 /*SuppressName=*/false,
2165 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002166
Douglas Gregor830072c2011-02-15 22:37:09 +00002167 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002168 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002169 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002170 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002171 }
Douglas Gregor38276252010-09-08 22:47:51 +00002172
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002173 if (SuppressBlock) {
2174 // Format as a parameter.
2175 Result = Result + " (^";
2176 if (Param->getIdentifier())
2177 Result += Param->getIdentifier()->getName();
2178 Result += ")";
2179 Result += Params;
2180 } else {
2181 // Format as a block literal argument.
2182 Result = '^' + Result;
2183 Result += Params;
2184
2185 if (Param->getIdentifier())
2186 Result += Param->getIdentifier()->getName();
2187 }
2188
Douglas Gregor83482d12010-08-24 16:15:59 +00002189 return Result;
2190}
2191
Douglas Gregor86d9a522009-09-21 16:56:56 +00002192/// \brief Add function parameter chunks to the given code completion string.
2193static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002194 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002195 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002196 CodeCompletionBuilder &Result,
2197 unsigned Start = 0,
2198 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002199 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002200
Douglas Gregor218937c2011-02-01 19:23:04 +00002201 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002202 ParmVarDecl *Param = Function->getParamDecl(P);
2203
Douglas Gregor218937c2011-02-01 19:23:04 +00002204 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002205 // When we see an optional default argument, put that argument and
2206 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002207 CodeCompletionBuilder Opt(Result.getAllocator(),
2208 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002209 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002210 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002211 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002212 Result.AddOptionalChunk(Opt.TakeString());
2213 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002214 }
2215
Douglas Gregor218937c2011-02-01 19:23:04 +00002216 if (FirstParameter)
2217 FirstParameter = false;
2218 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002219 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002220
2221 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002222
2223 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002224 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2225 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002226
Douglas Gregore17794f2010-08-31 05:13:43 +00002227 if (Function->isVariadic() && P == N - 1)
2228 PlaceholderStr += ", ...";
2229
Douglas Gregor86d9a522009-09-21 16:56:56 +00002230 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002231 Result.AddPlaceholderChunk(
2232 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002233 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002234
2235 if (const FunctionProtoType *Proto
2236 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002237 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002238 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002239 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002240
Douglas Gregor218937c2011-02-01 19:23:04 +00002241 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002242 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002243}
2244
2245/// \brief Add template parameter chunks to the given code completion string.
2246static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002247 const PrintingPolicy &Policy,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002248 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002249 CodeCompletionBuilder &Result,
2250 unsigned MaxParameters = 0,
2251 unsigned Start = 0,
2252 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002253 bool FirstParameter = true;
2254
2255 TemplateParameterList *Params = Template->getTemplateParameters();
2256 TemplateParameterList::iterator PEnd = Params->end();
2257 if (MaxParameters)
2258 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002259 for (TemplateParameterList::iterator P = Params->begin() + Start;
2260 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002261 bool HasDefaultArg = false;
2262 std::string PlaceholderStr;
2263 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2264 if (TTP->wasDeclaredWithTypename())
2265 PlaceholderStr = "typename";
2266 else
2267 PlaceholderStr = "class";
2268
2269 if (TTP->getIdentifier()) {
2270 PlaceholderStr += ' ';
2271 PlaceholderStr += TTP->getIdentifier()->getName();
2272 }
2273
2274 HasDefaultArg = TTP->hasDefaultArgument();
2275 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002276 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002277 if (NTTP->getIdentifier())
2278 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002279 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002280 HasDefaultArg = NTTP->hasDefaultArgument();
2281 } else {
2282 assert(isa<TemplateTemplateParmDecl>(*P));
2283 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2284
2285 // Since putting the template argument list into the placeholder would
2286 // be very, very long, we just use an abbreviation.
2287 PlaceholderStr = "template<...> class";
2288 if (TTP->getIdentifier()) {
2289 PlaceholderStr += ' ';
2290 PlaceholderStr += TTP->getIdentifier()->getName();
2291 }
2292
2293 HasDefaultArg = TTP->hasDefaultArgument();
2294 }
2295
Douglas Gregor218937c2011-02-01 19:23:04 +00002296 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002297 // When we see an optional default argument, put that argument and
2298 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002299 CodeCompletionBuilder Opt(Result.getAllocator(),
2300 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002301 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002302 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002303 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002304 P - Params->begin(), true);
2305 Result.AddOptionalChunk(Opt.TakeString());
2306 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002307 }
2308
Douglas Gregor218937c2011-02-01 19:23:04 +00002309 InDefaultArg = false;
2310
Douglas Gregor86d9a522009-09-21 16:56:56 +00002311 if (FirstParameter)
2312 FirstParameter = false;
2313 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002314 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002315
2316 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002317 Result.AddPlaceholderChunk(
2318 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002319 }
2320}
2321
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002322/// \brief Add a qualifier to the given code-completion string, if the
2323/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002324static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002325AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002326 NestedNameSpecifier *Qualifier,
2327 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002328 ASTContext &Context,
2329 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002330 if (!Qualifier)
2331 return;
2332
2333 std::string PrintedNNS;
2334 {
2335 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002336 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002337 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002338 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002339 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002340 else
Douglas Gregordae68752011-02-01 22:57:45 +00002341 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002342}
2343
Douglas Gregor218937c2011-02-01 19:23:04 +00002344static void
2345AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2346 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002347 const FunctionProtoType *Proto
2348 = Function->getType()->getAs<FunctionProtoType>();
2349 if (!Proto || !Proto->getTypeQuals())
2350 return;
2351
Douglas Gregora63f6de2011-02-01 21:15:40 +00002352 // FIXME: Add ref-qualifier!
2353
2354 // Handle single qualifiers without copying
2355 if (Proto->getTypeQuals() == Qualifiers::Const) {
2356 Result.AddInformativeChunk(" const");
2357 return;
2358 }
2359
2360 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2361 Result.AddInformativeChunk(" volatile");
2362 return;
2363 }
2364
2365 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2366 Result.AddInformativeChunk(" restrict");
2367 return;
2368 }
2369
2370 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002371 std::string QualsStr;
David Blaikie4ef832f2012-08-10 00:55:35 +00002372 if (Proto->isConst())
Douglas Gregora61a8792009-12-11 18:44:16 +00002373 QualsStr += " const";
David Blaikie4ef832f2012-08-10 00:55:35 +00002374 if (Proto->isVolatile())
Douglas Gregora61a8792009-12-11 18:44:16 +00002375 QualsStr += " volatile";
David Blaikie4ef832f2012-08-10 00:55:35 +00002376 if (Proto->isRestrict())
Douglas Gregora61a8792009-12-11 18:44:16 +00002377 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002378 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002379}
2380
Douglas Gregor6f942b22010-09-21 16:06:22 +00002381/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002382static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
2383 NamedDecl *ND, CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002384 DeclarationName Name = ND->getDeclName();
2385 if (!Name)
2386 return;
2387
2388 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002389 case DeclarationName::CXXOperatorName: {
2390 const char *OperatorName = 0;
2391 switch (Name.getCXXOverloadedOperator()) {
2392 case OO_None:
2393 case OO_Conditional:
2394 case NUM_OVERLOADED_OPERATORS:
2395 OperatorName = "operator";
2396 break;
2397
2398#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2399 case OO_##Name: OperatorName = "operator" Spelling; break;
2400#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2401#include "clang/Basic/OperatorKinds.def"
2402
2403 case OO_New: OperatorName = "operator new"; break;
2404 case OO_Delete: OperatorName = "operator delete"; break;
2405 case OO_Array_New: OperatorName = "operator new[]"; break;
2406 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2407 case OO_Call: OperatorName = "operator()"; break;
2408 case OO_Subscript: OperatorName = "operator[]"; break;
2409 }
2410 Result.AddTypedTextChunk(OperatorName);
2411 break;
2412 }
2413
Douglas Gregor6f942b22010-09-21 16:06:22 +00002414 case DeclarationName::Identifier:
2415 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002416 case DeclarationName::CXXDestructorName:
2417 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002418 Result.AddTypedTextChunk(
2419 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002420 break;
2421
2422 case DeclarationName::CXXUsingDirective:
2423 case DeclarationName::ObjCZeroArgSelector:
2424 case DeclarationName::ObjCOneArgSelector:
2425 case DeclarationName::ObjCMultiArgSelector:
2426 break;
2427
2428 case DeclarationName::CXXConstructorName: {
2429 CXXRecordDecl *Record = 0;
2430 QualType Ty = Name.getCXXNameType();
2431 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2432 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2433 else if (const InjectedClassNameType *InjectedTy
2434 = Ty->getAs<InjectedClassNameType>())
2435 Record = InjectedTy->getDecl();
2436 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002437 Result.AddTypedTextChunk(
2438 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002439 break;
2440 }
2441
Douglas Gregordae68752011-02-01 22:57:45 +00002442 Result.AddTypedTextChunk(
2443 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002444 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002445 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002446 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002447 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002448 }
2449 break;
2450 }
2451 }
2452}
2453
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002454CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002455 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002456 CodeCompletionTUInfo &CCTUInfo,
2457 bool IncludeBriefComments) {
2458 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo,
2459 IncludeBriefComments);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002460}
2461
Douglas Gregor86d9a522009-09-21 16:56:56 +00002462/// \brief If possible, create a new code completion string for the given
2463/// result.
2464///
2465/// \returns Either a new, heap-allocated code completion string describing
2466/// how to use this result, or NULL to indicate that the string or name of the
2467/// result is all that is needed.
2468CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002469CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2470 Preprocessor &PP,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002471 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002472 CodeCompletionTUInfo &CCTUInfo,
2473 bool IncludeBriefComments) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002474 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002475
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002476 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002477 if (Kind == RK_Pattern) {
2478 Pattern->Priority = Priority;
2479 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002480
2481 if (Declaration) {
2482 Result.addParentContext(Declaration->getDeclContext());
2483 Pattern->ParentKind = Result.getParentKind();
2484 Pattern->ParentName = Result.getParentName();
2485 }
2486
Douglas Gregor218937c2011-02-01 19:23:04 +00002487 return Pattern;
2488 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002489
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002490 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002491 Result.AddTypedTextChunk(Keyword);
2492 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002493 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002494
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002495 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002496 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002497 assert(MI && "Not a macro?");
2498
Douglas Gregordae68752011-02-01 22:57:45 +00002499 Result.AddTypedTextChunk(
2500 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002501
2502 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002503 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002504
2505 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002506 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002507 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002508
2509 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2510 if (MI->isC99Varargs()) {
2511 --AEnd;
2512
2513 if (A == AEnd) {
2514 Result.AddPlaceholderChunk("...");
2515 }
Douglas Gregore4244702011-07-30 08:17:44 +00002516 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002517
Douglas Gregore4244702011-07-30 08:17:44 +00002518 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002519 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002520 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002521
2522 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002523 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002524 if (MI->isC99Varargs())
2525 Arg += ", ...";
2526 else
2527 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002528 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002529 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002530 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002531
2532 // Non-variadic macros are simple.
2533 Result.AddPlaceholderChunk(
2534 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002535 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002536 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002537 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002538 }
2539
Douglas Gregord8e8a582010-05-25 21:41:55 +00002540 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002541 NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002542 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002543
2544 if (IncludeBriefComments) {
2545 // Add documentation comment, if it exists.
Dmitri Gribenkof50555e2012-08-11 00:51:43 +00002546 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002547 Result.addBriefComment(RC->getBriefText(Ctx));
2548 }
2549 }
2550
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002551 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002552 Result.AddTypedTextChunk(
2553 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002554 Result.AddTextChunk("::");
2555 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002556 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002557
2558 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2559 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2560 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2561 }
2562 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002563
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002564 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002565
Douglas Gregor86d9a522009-09-21 16:56:56 +00002566 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002567 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002568 Ctx, Policy);
2569 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002570 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002571 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002572 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002573 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002574 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002575 }
2576
2577 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002578 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002579 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002580 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002581 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002582
Douglas Gregor86d9a522009-09-21 16:56:56 +00002583 // Figure out which template parameters are deduced (or have default
2584 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002585 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002586 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002587 unsigned LastDeducibleArgument;
2588 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2589 --LastDeducibleArgument) {
2590 if (!Deduced[LastDeducibleArgument - 1]) {
2591 // C++0x: Figure out if the template argument has a default. If so,
2592 // the user doesn't need to type this argument.
2593 // FIXME: We need to abstract template parameters better!
2594 bool HasDefaultArg = false;
2595 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002596 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002597 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2598 HasDefaultArg = TTP->hasDefaultArgument();
2599 else if (NonTypeTemplateParmDecl *NTTP
2600 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2601 HasDefaultArg = NTTP->hasDefaultArgument();
2602 else {
2603 assert(isa<TemplateTemplateParmDecl>(Param));
2604 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002605 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002606 }
2607
2608 if (!HasDefaultArg)
2609 break;
2610 }
2611 }
2612
2613 if (LastDeducibleArgument) {
2614 // Some of the function template arguments cannot be deduced from a
2615 // function call, so we introduce an explicit template argument list
2616 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002617 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002618 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002619 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002620 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002621 }
2622
2623 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002624 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002625 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002626 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002627 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002628 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002629 }
2630
2631 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002632 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002633 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002634 Result.AddTypedTextChunk(
2635 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002636 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002637 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002638 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002639 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002640 }
2641
Douglas Gregor9630eb62009-11-17 16:44:22 +00002642 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002643 Selector Sel = Method->getSelector();
2644 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002645 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002646 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002647 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002648 }
2649
Douglas Gregor813d8342011-02-18 22:29:55 +00002650 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002651 SelName += ':';
2652 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002653 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002654 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002655 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002656
2657 // If there is only one parameter, and we're past it, add an empty
2658 // typed-text chunk since there is nothing to type.
2659 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002660 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002661 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002662 unsigned Idx = 0;
2663 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2664 PEnd = Method->param_end();
2665 P != PEnd; (void)++P, ++Idx) {
2666 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002667 std::string Keyword;
2668 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002669 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002670 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002671 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002672 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002673 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002674 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002675 else
Douglas Gregordae68752011-02-01 22:57:45 +00002676 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002677 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002678
2679 // If we're before the starting parameter, skip the placeholder.
2680 if (Idx < StartParameter)
2681 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002682
2683 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002684
2685 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002686 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002687 else {
John McCallf85e1932011-06-15 23:02:42 +00002688 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002689 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2690 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002691 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002692 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002693 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002694 }
2695
Douglas Gregore17794f2010-08-31 05:13:43 +00002696 if (Method->isVariadic() && (P + 1) == PEnd)
2697 Arg += ", ...";
2698
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002699 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002700 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002701 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002702 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002703 else
Douglas Gregordae68752011-02-01 22:57:45 +00002704 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002705 }
2706
Douglas Gregor2a17af02009-12-23 00:21:46 +00002707 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002708 if (Method->param_size() == 0) {
2709 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002710 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002711 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002712 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002713 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002714 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002715 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002716
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002717 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002718 }
2719
Douglas Gregor218937c2011-02-01 19:23:04 +00002720 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002721 }
2722
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002723 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002724 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002725 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002726
Douglas Gregordae68752011-02-01 22:57:45 +00002727 Result.AddTypedTextChunk(
2728 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002729 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002730}
2731
Douglas Gregor86d802e2009-09-23 00:34:09 +00002732CodeCompletionString *
2733CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2734 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002735 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002736 CodeCompletionAllocator &Allocator,
2737 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002738 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002739
Douglas Gregor218937c2011-02-01 19:23:04 +00002740 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002741 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002742 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002743 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002744 const FunctionProtoType *Proto
2745 = dyn_cast<FunctionProtoType>(getFunctionType());
2746 if (!FDecl && !Proto) {
2747 // Function without a prototype. Just give the return type and a
2748 // highlighted ellipsis.
2749 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002750 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002751 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002752 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002753 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2754 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2755 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002756 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002757 }
2758
2759 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002760 Result.AddTextChunk(
2761 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002762 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002763 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002764 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002765 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002766
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002767 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002768 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2769 for (unsigned I = 0; I != NumParams; ++I) {
2770 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002771 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002772
2773 std::string ArgString;
2774 QualType ArgType;
2775
2776 if (FDecl) {
2777 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2778 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2779 } else {
2780 ArgType = Proto->getArgType(I);
2781 }
2782
John McCallf85e1932011-06-15 23:02:42 +00002783 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002784
2785 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002786 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2787 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002788 else
Douglas Gregordae68752011-02-01 22:57:45 +00002789 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002790 }
2791
2792 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002793 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002794 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002795 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002796 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002797 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002798 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002799 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002800
Douglas Gregor218937c2011-02-01 19:23:04 +00002801 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002802}
2803
Chris Lattner5f9e2722011-07-23 10:55:15 +00002804unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002805 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002806 bool PreferredTypeIsPointer) {
2807 unsigned Priority = CCP_Macro;
2808
Douglas Gregorb05496d2010-09-20 21:11:48 +00002809 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2810 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2811 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002812 Priority = CCP_Constant;
2813 if (PreferredTypeIsPointer)
2814 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002815 }
2816 // Treat "YES", "NO", "true", and "false" as constants.
2817 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2818 MacroName.equals("true") || MacroName.equals("false"))
2819 Priority = CCP_Constant;
2820 // Treat "bool" as a type.
2821 else if (MacroName.equals("bool"))
2822 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2823
Douglas Gregor1827e102010-08-16 16:18:59 +00002824
2825 return Priority;
2826}
2827
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002828CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2829 if (!D)
2830 return CXCursor_UnexposedDecl;
2831
2832 switch (D->getKind()) {
2833 case Decl::Enum: return CXCursor_EnumDecl;
2834 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2835 case Decl::Field: return CXCursor_FieldDecl;
2836 case Decl::Function:
2837 return CXCursor_FunctionDecl;
2838 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2839 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002840 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002841
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002842 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002843 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2844 case Decl::ObjCMethod:
2845 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2846 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2847 case Decl::CXXMethod: return CXCursor_CXXMethod;
2848 case Decl::CXXConstructor: return CXCursor_Constructor;
2849 case Decl::CXXDestructor: return CXCursor_Destructor;
2850 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2851 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002852 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002853 case Decl::ParmVar: return CXCursor_ParmDecl;
2854 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002855 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002856 case Decl::Var: return CXCursor_VarDecl;
2857 case Decl::Namespace: return CXCursor_Namespace;
2858 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2859 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2860 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2861 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2862 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2863 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002864 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002865 case Decl::ClassTemplatePartialSpecialization:
2866 return CXCursor_ClassTemplatePartialSpecialization;
2867 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor8e5900c2012-04-30 23:41:16 +00002868 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002869
2870 case Decl::Using:
2871 case Decl::UnresolvedUsingValue:
2872 case Decl::UnresolvedUsingTypename:
2873 return CXCursor_UsingDeclaration;
2874
Douglas Gregor352697a2011-06-03 23:08:58 +00002875 case Decl::ObjCPropertyImpl:
2876 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2877 case ObjCPropertyImplDecl::Dynamic:
2878 return CXCursor_ObjCDynamicDecl;
2879
2880 case ObjCPropertyImplDecl::Synthesize:
2881 return CXCursor_ObjCSynthesizeDecl;
2882 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002883
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002884 default:
2885 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2886 switch (TD->getTagKind()) {
2887 case TTK_Struct: return CXCursor_StructDecl;
2888 case TTK_Class: return CXCursor_ClassDecl;
2889 case TTK_Union: return CXCursor_UnionDecl;
2890 case TTK_Enum: return CXCursor_EnumDecl;
2891 }
2892 }
2893 }
2894
2895 return CXCursor_UnexposedDecl;
2896}
2897
Douglas Gregor590c7d52010-07-08 20:55:51 +00002898static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2899 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002900 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002901
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002902 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002903
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002904 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2905 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002906 M != MEnd; ++M) {
Alexander Kornienko8a64bb52012-08-29 00:20:03 +00002907 // FIXME: Eventually, we'd want to be able to look back to the macro
2908 // definition that was actually active at the point of code completion (even
2909 // if that macro has since been #undef'd).
2910 if (M->first->hasMacroDefinition())
2911 Results.AddResult(Result(M->first,
Douglas Gregor1827e102010-08-16 16:18:59 +00002912 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002913 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002914 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002915 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002916
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002917 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002918
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002919}
2920
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002921static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2922 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002923 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002924
2925 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002926
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002927 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2928 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2929 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2930 Results.AddResult(Result("__func__", CCP_Constant));
2931 Results.ExitScope();
2932}
2933
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002934static void HandleCodeCompleteResults(Sema *S,
2935 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002936 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002937 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002938 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002939 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002940 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002941}
2942
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002943static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2944 Sema::ParserCompletionContext PCC) {
2945 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002946 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002947 return CodeCompletionContext::CCC_TopLevel;
2948
John McCallf312b1e2010-08-26 23:41:50 +00002949 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002950 return CodeCompletionContext::CCC_ClassStructUnion;
2951
John McCallf312b1e2010-08-26 23:41:50 +00002952 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002953 return CodeCompletionContext::CCC_ObjCInterface;
2954
John McCallf312b1e2010-08-26 23:41:50 +00002955 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002956 return CodeCompletionContext::CCC_ObjCImplementation;
2957
John McCallf312b1e2010-08-26 23:41:50 +00002958 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002959 return CodeCompletionContext::CCC_ObjCIvarList;
2960
John McCallf312b1e2010-08-26 23:41:50 +00002961 case Sema::PCC_Template:
2962 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002963 if (S.CurContext->isFileContext())
2964 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002965 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002966 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002967 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002968
John McCallf312b1e2010-08-26 23:41:50 +00002969 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002970 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002971
John McCallf312b1e2010-08-26 23:41:50 +00002972 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002973 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2974 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002975 return CodeCompletionContext::CCC_ParenthesizedExpression;
2976 else
2977 return CodeCompletionContext::CCC_Expression;
2978
2979 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002980 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002981 return CodeCompletionContext::CCC_Expression;
2982
John McCallf312b1e2010-08-26 23:41:50 +00002983 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002984 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002985
John McCallf312b1e2010-08-26 23:41:50 +00002986 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002987 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002988
2989 case Sema::PCC_ParenthesizedExpression:
2990 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002991
2992 case Sema::PCC_LocalDeclarationSpecifiers:
2993 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002994 }
David Blaikie7530c032012-01-17 06:56:22 +00002995
2996 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002997}
2998
Douglas Gregorf6961522010-08-27 21:18:54 +00002999/// \brief If we're in a C++ virtual member function, add completion results
3000/// that invoke the functions we override, since it's common to invoke the
3001/// overridden function as well as adding new functionality.
3002///
3003/// \param S The semantic analysis object for which we are generating results.
3004///
3005/// \param InContext This context in which the nested-name-specifier preceding
3006/// the code-completion point
3007static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3008 ResultBuilder &Results) {
3009 // Look through blocks.
3010 DeclContext *CurContext = S.CurContext;
3011 while (isa<BlockDecl>(CurContext))
3012 CurContext = CurContext->getParent();
3013
3014
3015 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3016 if (!Method || !Method->isVirtual())
3017 return;
3018
3019 // We need to have names for all of the parameters, if we're going to
3020 // generate a forwarding call.
3021 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3022 PEnd = Method->param_end();
3023 P != PEnd;
3024 ++P) {
3025 if (!(*P)->getDeclName())
3026 return;
3027 }
3028
Douglas Gregor8987b232011-09-27 23:30:47 +00003029 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00003030 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3031 MEnd = Method->end_overridden_methods();
3032 M != MEnd; ++M) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003033 CodeCompletionBuilder Builder(Results.getAllocator(),
3034 Results.getCodeCompletionTUInfo());
Douglas Gregorf6961522010-08-27 21:18:54 +00003035 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3036 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3037 continue;
3038
3039 // If we need a nested-name-specifier, add one now.
3040 if (!InContext) {
3041 NestedNameSpecifier *NNS
3042 = getRequiredQualification(S.Context, CurContext,
3043 Overridden->getDeclContext());
3044 if (NNS) {
3045 std::string Str;
3046 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003047 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003048 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003049 }
3050 } else if (!InContext->Equals(Overridden->getDeclContext()))
3051 continue;
3052
Douglas Gregordae68752011-02-01 22:57:45 +00003053 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003054 Overridden->getNameAsString()));
3055 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003056 bool FirstParam = true;
3057 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3058 PEnd = Method->param_end();
3059 P != PEnd; ++P) {
3060 if (FirstParam)
3061 FirstParam = false;
3062 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003063 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003064
Douglas Gregordae68752011-02-01 22:57:45 +00003065 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003066 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003067 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003068 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3069 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003070 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003071 CXCursor_CXXMethod,
3072 CXAvailability_Available,
3073 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003074 Results.Ignore(Overridden);
3075 }
3076}
3077
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003078void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3079 ModuleIdPath Path) {
3080 typedef CodeCompletionResult Result;
3081 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003082 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003083 CodeCompletionContext::CCC_Other);
3084 Results.EnterNewScope();
3085
3086 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003087 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003088 typedef CodeCompletionResult Result;
3089 if (Path.empty()) {
3090 // Enumerate all top-level modules.
3091 llvm::SmallVector<Module *, 8> Modules;
3092 PP.getHeaderSearchInfo().collectAllModules(Modules);
3093 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3094 Builder.AddTypedTextChunk(
3095 Builder.getAllocator().CopyString(Modules[I]->Name));
3096 Results.AddResult(Result(Builder.TakeString(),
3097 CCP_Declaration,
3098 CXCursor_NotImplemented,
3099 Modules[I]->isAvailable()
3100 ? CXAvailability_Available
3101 : CXAvailability_NotAvailable));
3102 }
3103 } else {
3104 // Load the named module.
3105 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3106 Module::AllVisible,
3107 /*IsInclusionDirective=*/false);
3108 // Enumerate submodules.
3109 if (Mod) {
3110 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3111 SubEnd = Mod->submodule_end();
3112 Sub != SubEnd; ++Sub) {
3113
3114 Builder.AddTypedTextChunk(
3115 Builder.getAllocator().CopyString((*Sub)->Name));
3116 Results.AddResult(Result(Builder.TakeString(),
3117 CCP_Declaration,
3118 CXCursor_NotImplemented,
3119 (*Sub)->isAvailable()
3120 ? CXAvailability_Available
3121 : CXAvailability_NotAvailable));
3122 }
3123 }
3124 }
3125 Results.ExitScope();
3126 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3127 Results.data(),Results.size());
3128}
3129
Douglas Gregor01dfea02010-01-10 23:08:15 +00003130void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003131 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003132 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003133 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003134 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003135 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003136 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003137
Douglas Gregor01dfea02010-01-10 23:08:15 +00003138 // Determine how to filter results, e.g., so that the names of
3139 // values (functions, enumerators, function templates, etc.) are
3140 // only allowed where we can have an expression.
3141 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003142 case PCC_Namespace:
3143 case PCC_Class:
3144 case PCC_ObjCInterface:
3145 case PCC_ObjCImplementation:
3146 case PCC_ObjCInstanceVariableList:
3147 case PCC_Template:
3148 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003149 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003150 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003151 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3152 break;
3153
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003154 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003155 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003156 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003157 case PCC_ForInit:
3158 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003159 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003160 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3161 else
3162 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003163
David Blaikie4e4d0842012-03-11 07:00:24 +00003164 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003165 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003166 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003167
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003168 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003169 // Unfiltered
3170 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003171 }
3172
Douglas Gregor3cdee122010-08-26 16:36:48 +00003173 // If we are in a C++ non-static member function, check the qualifiers on
3174 // the member function to filter/prioritize the results list.
3175 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3176 if (CurMethod->isInstance())
3177 Results.setObjectTypeQualifiers(
3178 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3179
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003180 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003181 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3182 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003183
Douglas Gregorbca403c2010-01-13 23:51:12 +00003184 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003185 Results.ExitScope();
3186
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003187 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003188 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003189 case PCC_Expression:
3190 case PCC_Statement:
3191 case PCC_RecoveryInFunction:
3192 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003193 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003194 break;
3195
3196 case PCC_Namespace:
3197 case PCC_Class:
3198 case PCC_ObjCInterface:
3199 case PCC_ObjCImplementation:
3200 case PCC_ObjCInstanceVariableList:
3201 case PCC_Template:
3202 case PCC_MemberTemplate:
3203 case PCC_ForInit:
3204 case PCC_Condition:
3205 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003206 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003207 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003208 }
3209
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003210 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003211 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003212
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003213 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003214 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003215}
3216
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003217static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3218 ParsedType Receiver,
3219 IdentifierInfo **SelIdents,
3220 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003221 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003222 bool IsSuper,
3223 ResultBuilder &Results);
3224
3225void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3226 bool AllowNonIdentifiers,
3227 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003228 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003229 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003230 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003231 AllowNestedNameSpecifiers
3232 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3233 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003234 Results.EnterNewScope();
3235
3236 // Type qualifiers can come after names.
3237 Results.AddResult(Result("const"));
3238 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003239 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003240 Results.AddResult(Result("restrict"));
3241
David Blaikie4e4d0842012-03-11 07:00:24 +00003242 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003243 if (AllowNonIdentifiers) {
3244 Results.AddResult(Result("operator"));
3245 }
3246
3247 // Add nested-name-specifiers.
3248 if (AllowNestedNameSpecifiers) {
3249 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003250 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003251 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3252 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3253 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003254 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003255 }
3256 }
3257 Results.ExitScope();
3258
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003259 // If we're in a context where we might have an expression (rather than a
3260 // declaration), and what we've seen so far is an Objective-C type that could
3261 // be a receiver of a class message, this may be a class message send with
3262 // the initial opening bracket '[' missing. Add appropriate completions.
3263 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3264 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3265 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3266 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3267 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3268 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3269 DS.getTypeQualifiers() == 0 &&
3270 S &&
3271 (S->getFlags() & Scope::DeclScope) != 0 &&
3272 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3273 Scope::FunctionPrototypeScope |
3274 Scope::AtCatchScope)) == 0) {
3275 ParsedType T = DS.getRepAsType();
3276 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003277 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003278 }
3279
Douglas Gregor4497dd42010-08-24 04:59:56 +00003280 // Note that we intentionally suppress macro results here, since we do not
3281 // encourage using macros to produce the names of entities.
3282
Douglas Gregor52779fb2010-09-23 23:01:17 +00003283 HandleCodeCompleteResults(this, CodeCompleter,
3284 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003285 Results.data(), Results.size());
3286}
3287
Douglas Gregorfb629412010-08-23 21:17:50 +00003288struct Sema::CodeCompleteExpressionData {
3289 CodeCompleteExpressionData(QualType PreferredType = QualType())
3290 : PreferredType(PreferredType), IntegralConstantExpression(false),
3291 ObjCCollection(false) { }
3292
3293 QualType PreferredType;
3294 bool IntegralConstantExpression;
3295 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003296 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003297};
3298
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003299/// \brief Perform code-completion in an expression context when we know what
3300/// type we're looking for.
Douglas Gregorfb629412010-08-23 21:17:50 +00003301void Sema::CodeCompleteExpression(Scope *S,
3302 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003303 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003304 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003305 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003306 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003307 if (Data.ObjCCollection)
3308 Results.setFilter(&ResultBuilder::IsObjCCollection);
3309 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003310 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003311 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003312 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3313 else
3314 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003315
3316 if (!Data.PreferredType.isNull())
3317 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3318
3319 // Ignore any declarations that we were told that we don't care about.
3320 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3321 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003322
3323 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003324 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3325 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003326
3327 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003328 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003329 Results.ExitScope();
3330
Douglas Gregor590c7d52010-07-08 20:55:51 +00003331 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003332 if (!Data.PreferredType.isNull())
3333 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3334 || Data.PreferredType->isMemberPointerType()
3335 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003336
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003337 if (S->getFnParent() &&
3338 !Data.ObjCCollection &&
3339 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003340 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003341
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003342 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003343 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003344 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003345 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3346 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003347 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003348}
3349
Douglas Gregorac5fd842010-09-18 01:28:11 +00003350void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3351 if (E.isInvalid())
3352 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003353 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003354 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003355}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003356
Douglas Gregor73449212010-12-09 23:01:55 +00003357/// \brief The set of properties that have already been added, referenced by
3358/// property name.
3359typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3360
Douglas Gregorb92a4082012-06-12 13:44:08 +00003361/// \brief Retrieve the container definition, if any?
3362static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3363 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3364 if (Interface->hasDefinition())
3365 return Interface->getDefinition();
3366
3367 return Interface;
3368 }
3369
3370 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3371 if (Protocol->hasDefinition())
3372 return Protocol->getDefinition();
3373
3374 return Protocol;
3375 }
3376 return Container;
3377}
3378
3379static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003380 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003381 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003382 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003383 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003384 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003385 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003386
Douglas Gregorb92a4082012-06-12 13:44:08 +00003387 // Retrieve the definition.
3388 Container = getContainerDef(Container);
3389
Douglas Gregor95ac6552009-11-18 01:29:26 +00003390 // Add properties in this container.
3391 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3392 PEnd = Container->prop_end();
3393 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003394 ++P) {
3395 if (AddedProperties.insert(P->getIdentifier()))
David Blaikie581deb32012-06-06 20:45:41 +00003396 Results.MaybeAddResult(Result(*P, 0), CurContext);
Douglas Gregor73449212010-12-09 23:01:55 +00003397 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003398
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003399 // Add nullary methods
3400 if (AllowNullaryMethods) {
3401 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003402 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003403 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3404 MEnd = Container->meth_end();
3405 M != MEnd; ++M) {
3406 if (M->getSelector().isUnarySelector())
3407 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3408 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003409 CodeCompletionBuilder Builder(Results.getAllocator(),
3410 Results.getCodeCompletionTUInfo());
David Blaikie581deb32012-06-06 20:45:41 +00003411 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003412 Builder.AddTypedTextChunk(
3413 Results.getAllocator().CopyString(Name->getName()));
3414
David Blaikie581deb32012-06-06 20:45:41 +00003415 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregorba103062012-03-27 23:34:16 +00003416 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003417 CurContext);
3418 }
3419 }
3420 }
3421
3422
Douglas Gregor95ac6552009-11-18 01:29:26 +00003423 // Add properties in referenced protocols.
3424 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3425 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3426 PEnd = Protocol->protocol_end();
3427 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003428 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3429 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003430 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003431 if (AllowCategories) {
3432 // Look through categories.
3433 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3434 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003435 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3436 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003437 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003438
3439 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003440 for (ObjCInterfaceDecl::all_protocol_iterator
3441 I = IFace->all_referenced_protocol_begin(),
3442 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003443 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3444 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003445
3446 // Look in the superclass.
3447 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003448 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3449 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003450 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003451 } else if (const ObjCCategoryDecl *Category
3452 = dyn_cast<ObjCCategoryDecl>(Container)) {
3453 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003454 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3455 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003456 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003457 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3458 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003459 }
3460}
3461
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003462void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003463 SourceLocation OpLoc,
3464 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003465 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003466 return;
3467
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003468 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3469 if (ConvertedBase.isInvalid())
3470 return;
3471 Base = ConvertedBase.get();
3472
John McCall0a2c5e22010-08-25 06:19:51 +00003473 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003474
Douglas Gregor81b747b2009-09-17 21:32:03 +00003475 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003476
3477 if (IsArrow) {
3478 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3479 BaseType = Ptr->getPointeeType();
3480 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003481 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003482 else
3483 return;
3484 }
3485
Douglas Gregor3da626b2011-07-07 16:03:39 +00003486 enum CodeCompletionContext::Kind contextKind;
3487
3488 if (IsArrow) {
3489 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3490 }
3491 else {
3492 if (BaseType->isObjCObjectPointerType() ||
3493 BaseType->isObjCObjectOrInterfaceType()) {
3494 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3495 }
3496 else {
3497 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3498 }
3499 }
3500
Douglas Gregor218937c2011-02-01 19:23:04 +00003501 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003502 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003503 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003504 BaseType),
3505 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003506 Results.EnterNewScope();
3507 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003508 // Indicate that we are performing a member access, and the cv-qualifiers
3509 // for the base object type.
3510 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3511
Douglas Gregor95ac6552009-11-18 01:29:26 +00003512 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003513 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003514 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003515 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3516 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003517
David Blaikie4e4d0842012-03-11 07:00:24 +00003518 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003519 if (!Results.empty()) {
3520 // The "template" keyword can follow "->" or "." in the grammar.
3521 // However, we only want to suggest the template keyword if something
3522 // is dependent.
3523 bool IsDependent = BaseType->isDependentType();
3524 if (!IsDependent) {
3525 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3526 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3527 IsDependent = Ctx->isDependentContext();
3528 break;
3529 }
3530 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003531
Douglas Gregor95ac6552009-11-18 01:29:26 +00003532 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003533 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003534 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003535 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003536 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3537 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003538 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003539
3540 // Add property results based on our interface.
3541 const ObjCObjectPointerType *ObjCPtr
3542 = BaseType->getAsObjCInterfacePointerType();
3543 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003544 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3545 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003546 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003547
3548 // Add properties from the protocols in a qualified interface.
3549 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3550 E = ObjCPtr->qual_end();
3551 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003552 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3553 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003554 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003555 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003556 // Objective-C instance variable access.
3557 ObjCInterfaceDecl *Class = 0;
3558 if (const ObjCObjectPointerType *ObjCPtr
3559 = BaseType->getAs<ObjCObjectPointerType>())
3560 Class = ObjCPtr->getInterfaceDecl();
3561 else
John McCallc12c5bb2010-05-15 11:32:37 +00003562 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003563
3564 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003565 if (Class) {
3566 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3567 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003568 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3569 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003570 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003571 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003572
3573 // FIXME: How do we cope with isa?
3574
3575 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003576
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003577 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003578 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003579 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003580 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003581}
3582
Douglas Gregor374929f2009-09-18 15:37:17 +00003583void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3584 if (!CodeCompleter)
3585 return;
3586
John McCall0a2c5e22010-08-25 06:19:51 +00003587 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003588 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003589 enum CodeCompletionContext::Kind ContextKind
3590 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003591 switch ((DeclSpec::TST)TagSpec) {
3592 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003593 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003594 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003595 break;
3596
3597 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003598 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003599 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003600 break;
3601
3602 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003603 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003604 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003605 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003606 break;
3607
3608 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003609 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003610 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003611
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003612 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3613 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003614 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003615
3616 // First pass: look for tags.
3617 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003618 LookupVisibleDecls(S, LookupTagName, Consumer,
3619 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003620
Douglas Gregor8071e422010-08-15 06:18:01 +00003621 if (CodeCompleter->includeGlobals()) {
3622 // Second pass: look for nested name specifiers.
3623 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3624 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3625 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003626
Douglas Gregor52779fb2010-09-23 23:01:17 +00003627 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003628 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003629}
3630
Douglas Gregor1a480c42010-08-27 17:35:51 +00003631void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003632 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003633 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003634 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003635 Results.EnterNewScope();
3636 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3637 Results.AddResult("const");
3638 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3639 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003640 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003641 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3642 Results.AddResult("restrict");
3643 Results.ExitScope();
3644 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003645 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003646 Results.data(), Results.size());
3647}
3648
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003649void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003650 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003651 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003652
John McCall781472f2010-08-25 08:40:02 +00003653 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003654 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3655 if (!type->isEnumeralType()) {
3656 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003657 Data.IntegralConstantExpression = true;
3658 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003659 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003660 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003661
3662 // Code-complete the cases of a switch statement over an enumeration type
3663 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003664 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003665 if (EnumDecl *Def = Enum->getDefinition())
3666 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003667
3668 // Determine which enumerators we have already seen in the switch statement.
3669 // FIXME: Ideally, we would also be able to look *past* the code-completion
3670 // token, in case we are code-completing in the middle of the switch and not
3671 // at the end. However, we aren't able to do so at the moment.
3672 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003673 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003674 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3675 SC = SC->getNextSwitchCase()) {
3676 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3677 if (!Case)
3678 continue;
3679
3680 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3681 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3682 if (EnumConstantDecl *Enumerator
3683 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3684 // We look into the AST of the case statement to determine which
3685 // enumerator was named. Alternatively, we could compute the value of
3686 // the integral constant expression, then compare it against the
3687 // values of each enumerator. However, value-based approach would not
3688 // work as well with C++ templates where enumerators declared within a
3689 // template are type- and value-dependent.
3690 EnumeratorsSeen.insert(Enumerator);
3691
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003692 // If this is a qualified-id, keep track of the nested-name-specifier
3693 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003694 //
3695 // switch (TagD.getKind()) {
3696 // case TagDecl::TK_enum:
3697 // break;
3698 // case XXX
3699 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003700 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003701 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3702 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003703 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003704 }
3705 }
3706
David Blaikie4e4d0842012-03-11 07:00:24 +00003707 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003708 // If there are no prior enumerators in C++, check whether we have to
3709 // qualify the names of the enumerators that we suggest, because they
3710 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003711 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003712 }
3713
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003714 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003715 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003716 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003717 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003718 Results.EnterNewScope();
3719 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3720 EEnd = Enum->enumerator_end();
3721 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003722 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003723 continue;
3724
David Blaikie581deb32012-06-06 20:45:41 +00003725 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003726 R.Priority = CCP_EnumInCase;
3727 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003728 }
3729 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003730
Douglas Gregor3da626b2011-07-07 16:03:39 +00003731 //We need to make sure we're setting the right context,
3732 //so only say we include macros if the code completer says we do
3733 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3734 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003735 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003736 kind = CodeCompletionContext::CCC_OtherWithMacros;
3737 }
3738
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003739 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003740 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003741 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003742}
3743
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003744namespace {
3745 struct IsBetterOverloadCandidate {
3746 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003747 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003748
3749 public:
John McCall5769d612010-02-08 23:07:23 +00003750 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3751 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003752
3753 bool
3754 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003755 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003756 }
3757 };
3758}
3759
Ahmed Charles13a140c2012-02-25 11:00:22 +00003760static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3761 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003762 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003763
3764 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003765 if (!Args[I])
3766 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003767
Douglas Gregord28dcd72010-05-30 06:10:08 +00003768 return false;
3769}
3770
Richard Trieuf81e5a92011-09-09 02:00:50 +00003771void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003772 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003773 if (!CodeCompleter)
3774 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003775
3776 // When we're code-completing for a call, we fall back to ordinary
3777 // name code-completion whenever we can't produce specific
3778 // results. We may want to revisit this strategy in the future,
3779 // e.g., by merging the two kinds of results.
3780
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003781 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003782
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003783 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003784 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3785 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003786 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003787 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003788 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003789
John McCall3b4294e2009-12-16 12:17:52 +00003790 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003791 SourceLocation Loc = Fn->getExprLoc();
3792 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003793
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003794 // FIXME: What if we're calling something that isn't a function declaration?
3795 // FIXME: What if we're calling a pseudo-destructor?
3796 // FIXME: What if we're calling a member function?
3797
Douglas Gregorc0265402010-01-21 15:46:19 +00003798 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003799 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003800
John McCall3b4294e2009-12-16 12:17:52 +00003801 Expr *NakedFn = Fn->IgnoreParenCasts();
3802 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003803 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003804 /*PartialOverloading=*/ true);
3805 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3806 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003807 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003808 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003809 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003810 Results.push_back(ResultCandidate(FDecl));
3811 else
John McCall86820f52010-01-26 01:37:31 +00003812 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003813 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3814 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003815 }
John McCall3b4294e2009-12-16 12:17:52 +00003816 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003817
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003818 QualType ParamType;
3819
Douglas Gregorc0265402010-01-21 15:46:19 +00003820 if (!CandidateSet.empty()) {
3821 // Sort the overload candidate set by placing the best overloads first.
3822 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003823 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003824
Douglas Gregorc0265402010-01-21 15:46:19 +00003825 // Add the remaining viable overload candidates as code-completion reslults.
3826 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3827 CandEnd = CandidateSet.end();
3828 Cand != CandEnd; ++Cand) {
3829 if (Cand->Viable)
3830 Results.push_back(ResultCandidate(Cand->Function));
3831 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003832
3833 // From the viable candidates, try to determine the type of this parameter.
3834 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3835 if (const FunctionType *FType = Results[I].getFunctionType())
3836 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003837 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003838 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003839 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003840 else if (!Context.hasSameUnqualifiedType(
3841 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003842 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003843 ParamType = QualType();
3844 break;
3845 }
3846 }
3847 }
3848 } else {
3849 // Try to determine the parameter type from the type of the expression
3850 // being called.
3851 QualType FunctionType = Fn->getType();
3852 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3853 FunctionType = Ptr->getPointeeType();
3854 else if (const BlockPointerType *BlockPtr
3855 = FunctionType->getAs<BlockPointerType>())
3856 FunctionType = BlockPtr->getPointeeType();
3857 else if (const MemberPointerType *MemPtr
3858 = FunctionType->getAs<MemberPointerType>())
3859 FunctionType = MemPtr->getPointeeType();
3860
3861 if (const FunctionProtoType *Proto
3862 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003863 if (Args.size() < Proto->getNumArgs())
3864 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003865 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003866 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003867
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003868 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003869 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003870 else
3871 CodeCompleteExpression(S, ParamType);
3872
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003873 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003874 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003875 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003876}
3877
John McCalld226f652010-08-21 09:40:31 +00003878void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3879 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003880 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003881 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003882 return;
3883 }
3884
3885 CodeCompleteExpression(S, VD->getType());
3886}
3887
3888void Sema::CodeCompleteReturn(Scope *S) {
3889 QualType ResultType;
3890 if (isa<BlockDecl>(CurContext)) {
3891 if (BlockScopeInfo *BSI = getCurBlock())
3892 ResultType = BSI->ReturnType;
3893 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3894 ResultType = Function->getResultType();
3895 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3896 ResultType = Method->getResultType();
3897
3898 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003899 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003900 else
3901 CodeCompleteExpression(S, ResultType);
3902}
3903
Douglas Gregord2d8be62011-07-30 08:36:53 +00003904void Sema::CodeCompleteAfterIf(Scope *S) {
3905 typedef CodeCompletionResult Result;
3906 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003907 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003908 mapCodeCompletionContext(*this, PCC_Statement));
3909 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3910 Results.EnterNewScope();
3911
3912 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3913 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3914 CodeCompleter->includeGlobals());
3915
3916 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3917
3918 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003919 CodeCompletionBuilder Builder(Results.getAllocator(),
3920 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003921 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003922 if (Results.includeCodePatterns()) {
3923 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3924 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3925 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3926 Builder.AddPlaceholderChunk("statements");
3927 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3928 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3929 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003930 Results.AddResult(Builder.TakeString());
3931
3932 // "else if" block
3933 Builder.AddTypedTextChunk("else");
3934 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3935 Builder.AddTextChunk("if");
3936 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3937 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003938 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003939 Builder.AddPlaceholderChunk("condition");
3940 else
3941 Builder.AddPlaceholderChunk("expression");
3942 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003943 if (Results.includeCodePatterns()) {
3944 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3945 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3946 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3947 Builder.AddPlaceholderChunk("statements");
3948 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3949 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3950 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003951 Results.AddResult(Builder.TakeString());
3952
3953 Results.ExitScope();
3954
3955 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003956 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003957
3958 if (CodeCompleter->includeMacros())
3959 AddMacroResults(PP, Results);
3960
3961 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3962 Results.data(),Results.size());
3963}
3964
Richard Trieuf81e5a92011-09-09 02:00:50 +00003965void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003966 if (LHS)
3967 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3968 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003969 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003970}
3971
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003972void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003973 bool EnteringContext) {
3974 if (!SS.getScopeRep() || !CodeCompleter)
3975 return;
3976
Douglas Gregor86d9a522009-09-21 16:56:56 +00003977 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3978 if (!Ctx)
3979 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003980
3981 // Try to instantiate any non-dependent declaration contexts before
3982 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003983 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003984 return;
3985
Douglas Gregor218937c2011-02-01 19:23:04 +00003986 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003987 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003988 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003989 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003990
Douglas Gregor86d9a522009-09-21 16:56:56 +00003991 // The "template" keyword can follow "::" in the grammar, but only
3992 // put it into the grammar if the nested-name-specifier is dependent.
3993 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3994 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003995 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003996
3997 // Add calls to overridden virtual functions, if there are any.
3998 //
3999 // FIXME: This isn't wonderful, because we don't know whether we're actually
4000 // in a context that permits expressions. This is a general issue with
4001 // qualified-id completions.
4002 if (!EnteringContext)
4003 MaybeAddOverrideCalls(*this, Ctx, Results);
4004 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004005
Douglas Gregorf6961522010-08-27 21:18:54 +00004006 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4007 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4008
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004009 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00004010 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004011 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00004012}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004013
4014void Sema::CodeCompleteUsing(Scope *S) {
4015 if (!CodeCompleter)
4016 return;
4017
Douglas Gregor218937c2011-02-01 19:23:04 +00004018 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004019 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004020 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4021 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004022 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004023
4024 // If we aren't in class scope, we could see the "namespace" keyword.
4025 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00004026 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004027
4028 // After "using", we can see anything that would start a
4029 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004030 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004031 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4032 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004033 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004034
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004035 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004036 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004037 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004038}
4039
4040void Sema::CodeCompleteUsingDirective(Scope *S) {
4041 if (!CodeCompleter)
4042 return;
4043
Douglas Gregor86d9a522009-09-21 16:56:56 +00004044 // After "using namespace", we expect to see a namespace name or namespace
4045 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004046 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004047 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004048 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004049 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004050 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004051 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004052 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4053 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004054 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004055 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004056 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004057 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004058}
4059
4060void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4061 if (!CodeCompleter)
4062 return;
4063
Douglas Gregor86d9a522009-09-21 16:56:56 +00004064 DeclContext *Ctx = (DeclContext *)S->getEntity();
4065 if (!S->getParent())
4066 Ctx = Context.getTranslationUnitDecl();
4067
Douglas Gregor52779fb2010-09-23 23:01:17 +00004068 bool SuppressedGlobalResults
4069 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4070
Douglas Gregor218937c2011-02-01 19:23:04 +00004071 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004072 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004073 SuppressedGlobalResults
4074 ? CodeCompletionContext::CCC_Namespace
4075 : CodeCompletionContext::CCC_Other,
4076 &ResultBuilder::IsNamespace);
4077
4078 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004079 // We only want to see those namespaces that have already been defined
4080 // within this scope, because its likely that the user is creating an
4081 // extended namespace declaration. Keep track of the most recent
4082 // definition of each namespace.
4083 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4084 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4085 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4086 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004087 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004088
4089 // Add the most recent definition (or extended definition) of each
4090 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004091 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004092 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004093 NS = OrigToLatest.begin(),
4094 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004095 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004096 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004097 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004098 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004099 }
4100
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004101 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004102 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004103 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004104}
4105
4106void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4107 if (!CodeCompleter)
4108 return;
4109
Douglas Gregor86d9a522009-09-21 16:56:56 +00004110 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004111 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004112 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004113 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004114 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004115 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004116 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4117 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004118 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004119 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004120 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004121}
4122
Douglas Gregored8d3222009-09-18 20:05:18 +00004123void Sema::CodeCompleteOperatorName(Scope *S) {
4124 if (!CodeCompleter)
4125 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004126
John McCall0a2c5e22010-08-25 06:19:51 +00004127 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004128 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004129 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004130 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004131 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004132 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004133
Douglas Gregor86d9a522009-09-21 16:56:56 +00004134 // Add the names of overloadable operators.
4135#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4136 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004137 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004138#include "clang/Basic/OperatorKinds.def"
4139
4140 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004141 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004142 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004143 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4144 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004145
4146 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004147 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004148 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004149
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004150 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004151 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004152 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004153}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004154
Douglas Gregor0133f522010-08-28 00:00:50 +00004155void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004156 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004157 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004158 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004159 CXXConstructorDecl *Constructor
4160 = static_cast<CXXConstructorDecl *>(ConstructorD);
4161 if (!Constructor)
4162 return;
4163
Douglas Gregor218937c2011-02-01 19:23:04 +00004164 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004165 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004166 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004167 Results.EnterNewScope();
4168
4169 // Fill in any already-initialized fields or base classes.
4170 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4171 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4172 for (unsigned I = 0; I != NumInitializers; ++I) {
4173 if (Initializers[I]->isBaseInitializer())
4174 InitializedBases.insert(
4175 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4176 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004177 InitializedFields.insert(cast<FieldDecl>(
4178 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004179 }
4180
4181 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004182 CodeCompletionBuilder Builder(Results.getAllocator(),
4183 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004184 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004185 CXXRecordDecl *ClassDecl = Constructor->getParent();
4186 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4187 BaseEnd = ClassDecl->bases_end();
4188 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004189 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4190 SawLastInitializer
4191 = NumInitializers > 0 &&
4192 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4193 Context.hasSameUnqualifiedType(Base->getType(),
4194 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004195 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004196 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004197
Douglas Gregor218937c2011-02-01 19:23:04 +00004198 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004199 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004200 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004201 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4202 Builder.AddPlaceholderChunk("args");
4203 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4204 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004205 SawLastInitializer? CCP_NextInitializer
4206 : CCP_MemberDeclaration));
4207 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004208 }
4209
4210 // Add completions for virtual base classes.
4211 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4212 BaseEnd = ClassDecl->vbases_end();
4213 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004214 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4215 SawLastInitializer
4216 = NumInitializers > 0 &&
4217 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4218 Context.hasSameUnqualifiedType(Base->getType(),
4219 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004220 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004221 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004222
Douglas Gregor218937c2011-02-01 19:23:04 +00004223 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004224 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004225 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004226 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4227 Builder.AddPlaceholderChunk("args");
4228 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4229 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004230 SawLastInitializer? CCP_NextInitializer
4231 : CCP_MemberDeclaration));
4232 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004233 }
4234
4235 // Add completions for members.
4236 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4237 FieldEnd = ClassDecl->field_end();
4238 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004239 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4240 SawLastInitializer
4241 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004242 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie581deb32012-06-06 20:45:41 +00004243 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004244 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004245 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004246
4247 if (!Field->getDeclName())
4248 continue;
4249
Douglas Gregordae68752011-02-01 22:57:45 +00004250 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004251 Field->getIdentifier()->getName()));
4252 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4253 Builder.AddPlaceholderChunk("args");
4254 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4255 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004256 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004257 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004258 CXCursor_MemberRef,
4259 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004260 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004261 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004262 }
4263 Results.ExitScope();
4264
Douglas Gregor52779fb2010-09-23 23:01:17 +00004265 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004266 Results.data(), Results.size());
4267}
4268
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004269/// \brief Determine whether this scope denotes a namespace.
4270static bool isNamespaceScope(Scope *S) {
4271 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4272 if (!DC)
4273 return false;
4274
4275 return DC->isFileContext();
4276}
4277
4278void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4279 bool AfterAmpersand) {
4280 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004281 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004282 CodeCompletionContext::CCC_Other);
4283 Results.EnterNewScope();
4284
4285 // Note what has already been captured.
4286 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4287 bool IncludedThis = false;
4288 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4289 CEnd = Intro.Captures.end();
4290 C != CEnd; ++C) {
4291 if (C->Kind == LCK_This) {
4292 IncludedThis = true;
4293 continue;
4294 }
4295
4296 Known.insert(C->Id);
4297 }
4298
4299 // Look for other capturable variables.
4300 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4301 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4302 D != DEnd; ++D) {
4303 VarDecl *Var = dyn_cast<VarDecl>(*D);
4304 if (!Var ||
4305 !Var->hasLocalStorage() ||
4306 Var->hasAttr<BlocksAttr>())
4307 continue;
4308
4309 if (Known.insert(Var->getIdentifier()))
4310 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4311 }
4312 }
4313
4314 // Add 'this', if it would be valid.
4315 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4316 addThisCompletion(*this, Results);
4317
4318 Results.ExitScope();
4319
4320 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4321 Results.data(), Results.size());
4322}
4323
James Dennetta40f7922012-06-14 03:11:41 +00004324/// Macro that optionally prepends an "@" to the string literal passed in via
4325/// Keyword, depending on whether NeedAt is true or false.
4326#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4327
Douglas Gregorbca403c2010-01-13 23:51:12 +00004328static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004329 ResultBuilder &Results,
4330 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004331 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004332 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004333 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004334
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004335 CodeCompletionBuilder Builder(Results.getAllocator(),
4336 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004337 if (LangOpts.ObjC2) {
4338 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004339 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004340 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4341 Builder.AddPlaceholderChunk("property");
4342 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004343
4344 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004345 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004346 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4347 Builder.AddPlaceholderChunk("property");
4348 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004349 }
4350}
4351
Douglas Gregorbca403c2010-01-13 23:51:12 +00004352static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004353 ResultBuilder &Results,
4354 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004355 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004356
4357 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004358 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004359
4360 if (LangOpts.ObjC2) {
4361 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004362 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004363
4364 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004365 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004366
4367 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004368 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004369 }
4370}
4371
Douglas Gregorbca403c2010-01-13 23:51:12 +00004372static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004373 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004374 CodeCompletionBuilder Builder(Results.getAllocator(),
4375 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004376
4377 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004378 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004379 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4380 Builder.AddPlaceholderChunk("name");
4381 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004382
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004383 if (Results.includeCodePatterns()) {
4384 // @interface name
4385 // FIXME: Could introduce the whole pattern, including superclasses and
4386 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004387 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004388 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4389 Builder.AddPlaceholderChunk("class");
4390 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004391
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004392 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004393 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004394 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4395 Builder.AddPlaceholderChunk("protocol");
4396 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004397
4398 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004399 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004400 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4401 Builder.AddPlaceholderChunk("class");
4402 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004403 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004404
4405 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004406 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004407 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4408 Builder.AddPlaceholderChunk("alias");
4409 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4410 Builder.AddPlaceholderChunk("class");
4411 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004412}
4413
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004414void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004415 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004416 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004417 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004418 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004419 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004420 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004421 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004422 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004423 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004424 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004425 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004426 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004427 HandleCodeCompleteResults(this, CodeCompleter,
4428 CodeCompletionContext::CCC_Other,
4429 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004430}
4431
Douglas Gregorbca403c2010-01-13 23:51:12 +00004432static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004433 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004434 CodeCompletionBuilder Builder(Results.getAllocator(),
4435 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004436
4437 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004438 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004439 if (Results.getSema().getLangOpts().CPlusPlus ||
4440 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004441 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004442 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004443 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004444 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4445 Builder.AddPlaceholderChunk("type-name");
4446 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4447 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004448
4449 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004450 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004451 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004452 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4453 Builder.AddPlaceholderChunk("protocol-name");
4454 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4455 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004456
4457 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004458 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004459 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004460 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4461 Builder.AddPlaceholderChunk("selector");
4462 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4463 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004464
4465 // @"string"
4466 Builder.AddResultTypeChunk("NSString *");
4467 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4468 Builder.AddPlaceholderChunk("string");
4469 Builder.AddTextChunk("\"");
4470 Results.AddResult(Result(Builder.TakeString()));
4471
Douglas Gregor79615892012-07-17 23:24:47 +00004472 // @[objects, ...]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004473 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004474 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004475 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004476 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4477 Results.AddResult(Result(Builder.TakeString()));
4478
Douglas Gregor79615892012-07-17 23:24:47 +00004479 // @{key : object, ...}
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004480 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004481 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004482 Builder.AddPlaceholderChunk("key");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004483 Builder.AddChunk(CodeCompletionString::CK_Colon);
4484 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4485 Builder.AddPlaceholderChunk("object, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004486 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4487 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004488
Douglas Gregor79615892012-07-17 23:24:47 +00004489 // @(expression)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004490 Builder.AddResultTypeChunk("id");
4491 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004492 Builder.AddPlaceholderChunk("expression");
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004493 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4494 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004495}
4496
Douglas Gregorbca403c2010-01-13 23:51:12 +00004497static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004498 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004499 CodeCompletionBuilder Builder(Results.getAllocator(),
4500 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004501
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004502 if (Results.includeCodePatterns()) {
4503 // @try { statements } @catch ( declaration ) { statements } @finally
4504 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004505 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004506 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4507 Builder.AddPlaceholderChunk("statements");
4508 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4509 Builder.AddTextChunk("@catch");
4510 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4511 Builder.AddPlaceholderChunk("parameter");
4512 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4513 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4514 Builder.AddPlaceholderChunk("statements");
4515 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4516 Builder.AddTextChunk("@finally");
4517 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4518 Builder.AddPlaceholderChunk("statements");
4519 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4520 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004521 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004522
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004523 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004524 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004525 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4526 Builder.AddPlaceholderChunk("expression");
4527 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004528
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004529 if (Results.includeCodePatterns()) {
4530 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004531 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004532 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4533 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4534 Builder.AddPlaceholderChunk("expression");
4535 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4536 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4537 Builder.AddPlaceholderChunk("statements");
4538 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4539 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004540 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004541}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004542
Douglas Gregorbca403c2010-01-13 23:51:12 +00004543static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004544 ResultBuilder &Results,
4545 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004546 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004547 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4548 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4549 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004550 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004551 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004552}
4553
4554void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004555 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004556 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004557 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004558 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004559 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004560 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004561 HandleCodeCompleteResults(this, CodeCompleter,
4562 CodeCompletionContext::CCC_Other,
4563 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004564}
4565
4566void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004567 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004568 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004569 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004570 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004571 AddObjCStatementResults(Results, false);
4572 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004573 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004574 HandleCodeCompleteResults(this, CodeCompleter,
4575 CodeCompletionContext::CCC_Other,
4576 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004577}
4578
4579void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004580 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004581 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004582 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004583 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004584 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004585 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004586 HandleCodeCompleteResults(this, CodeCompleter,
4587 CodeCompletionContext::CCC_Other,
4588 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004589}
4590
Douglas Gregor988358f2009-11-19 00:14:45 +00004591/// \brief Determine whether the addition of the given flag to an Objective-C
4592/// property's attributes will cause a conflict.
4593static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4594 // Check if we've already added this flag.
4595 if (Attributes & NewFlag)
4596 return true;
4597
4598 Attributes |= NewFlag;
4599
4600 // Check for collisions with "readonly".
4601 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004602 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregor988358f2009-11-19 00:14:45 +00004603 return true;
4604
Jordan Rosed7403a72012-08-20 20:01:13 +00004605 // Check for more than one of { assign, copy, retain, strong, weak }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004606 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004607 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004608 ObjCDeclSpec::DQ_PR_copy |
Jordan Rosed7403a72012-08-20 20:01:13 +00004609 ObjCDeclSpec::DQ_PR_retain |
4610 ObjCDeclSpec::DQ_PR_strong |
4611 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregor988358f2009-11-19 00:14:45 +00004612 if (AssignCopyRetMask &&
4613 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004614 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004615 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004616 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004617 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
4618 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregor988358f2009-11-19 00:14:45 +00004619 return true;
4620
4621 return false;
4622}
4623
Douglas Gregora93b1082009-11-18 23:08:07 +00004624void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004625 if (!CodeCompleter)
4626 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004627
Steve Naroffece8e712009-10-08 21:55:05 +00004628 unsigned Attributes = ODS.getPropertyAttributes();
4629
John McCall0a2c5e22010-08-25 06:19:51 +00004630 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004631 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004632 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004633 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004634 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004635 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004636 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004637 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004638 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004639 if (!ObjCPropertyFlagConflicts(Attributes,
4640 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4641 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004642 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004643 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004644 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004645 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004646 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4647 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004648 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004649 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004650 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004651 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004652 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4653 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rosed7403a72012-08-20 20:01:13 +00004654
4655 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall0a7dd782012-08-21 02:47:43 +00004656 if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Jordan Rosed7403a72012-08-20 20:01:13 +00004657 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
4658 Results.AddResult(CodeCompletionResult("weak"));
4659
Douglas Gregor988358f2009-11-19 00:14:45 +00004660 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004661 CodeCompletionBuilder Setter(Results.getAllocator(),
4662 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004663 Setter.AddTypedTextChunk("setter");
4664 Setter.AddTextChunk(" = ");
4665 Setter.AddPlaceholderChunk("method");
4666 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004667 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004668 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004669 CodeCompletionBuilder Getter(Results.getAllocator(),
4670 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004671 Getter.AddTypedTextChunk("getter");
4672 Getter.AddTextChunk(" = ");
4673 Getter.AddPlaceholderChunk("method");
4674 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004675 }
Steve Naroffece8e712009-10-08 21:55:05 +00004676 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004677 HandleCodeCompleteResults(this, CodeCompleter,
4678 CodeCompletionContext::CCC_Other,
4679 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004680}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004681
James Dennettde23c7e2012-06-17 05:33:25 +00004682/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregor4ad96852009-11-19 07:41:15 +00004683/// via code completion.
4684enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004685 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4686 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4687 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004688};
4689
Douglas Gregor458433d2010-08-26 15:07:07 +00004690static bool isAcceptableObjCSelector(Selector Sel,
4691 ObjCMethodKind WantKind,
4692 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004693 unsigned NumSelIdents,
4694 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004695 if (NumSelIdents > Sel.getNumArgs())
4696 return false;
4697
4698 switch (WantKind) {
4699 case MK_Any: break;
4700 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4701 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4702 }
4703
Douglas Gregorcf544262010-11-17 21:36:08 +00004704 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4705 return false;
4706
Douglas Gregor458433d2010-08-26 15:07:07 +00004707 for (unsigned I = 0; I != NumSelIdents; ++I)
4708 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4709 return false;
4710
4711 return true;
4712}
4713
Douglas Gregor4ad96852009-11-19 07:41:15 +00004714static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4715 ObjCMethodKind WantKind,
4716 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004717 unsigned NumSelIdents,
4718 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004719 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004720 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004721}
Douglas Gregord36adf52010-09-16 16:06:31 +00004722
4723namespace {
4724 /// \brief A set of selectors, which is used to avoid introducing multiple
4725 /// completions with the same selector into the result set.
4726 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4727}
4728
Douglas Gregor36ecb042009-11-17 23:22:23 +00004729/// \brief Add all of the Objective-C methods in the given Objective-C
4730/// container to the set of results.
4731///
4732/// The container will be a class, protocol, category, or implementation of
4733/// any of the above. This mether will recurse to include methods from
4734/// the superclasses of classes along with their categories, protocols, and
4735/// implementations.
4736///
4737/// \param Container the container in which we'll look to find methods.
4738///
James Dennetta40f7922012-06-14 03:11:41 +00004739/// \param WantInstanceMethods Whether to add instance methods (only); if
4740/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004741///
4742/// \param CurContext the context in which we're performing the lookup that
4743/// finds methods.
4744///
Douglas Gregorcf544262010-11-17 21:36:08 +00004745/// \param AllowSameLength Whether we allow a method to be added to the list
4746/// when it has the same number of parameters as we have selector identifiers.
4747///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004748/// \param Results the structure into which we'll add results.
4749static void AddObjCMethods(ObjCContainerDecl *Container,
4750 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004751 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004752 IdentifierInfo **SelIdents,
4753 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004754 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004755 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004756 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004757 ResultBuilder &Results,
4758 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004759 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004760 Container = getContainerDef(Container);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004761 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4762 MEnd = Container->meth_end();
4763 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00004764 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004765 // Check whether the selector identifiers we've been given are a
4766 // subset of the identifiers for this particular method.
David Blaikie581deb32012-06-06 20:45:41 +00004767 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004768 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004769 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004770
David Blaikie262bc182012-04-30 02:36:29 +00004771 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004772 continue;
4773
David Blaikie581deb32012-06-06 20:45:41 +00004774 Result R = Result(*M, 0);
Douglas Gregord3c68542009-11-19 01:08:35 +00004775 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004776 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004777 if (!InOriginalClass)
4778 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004779 Results.MaybeAddResult(R, CurContext);
4780 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004781 }
4782
Douglas Gregore396c7b2010-09-16 15:34:59 +00004783 // Visit the protocols of protocols.
4784 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004785 if (Protocol->hasDefinition()) {
4786 const ObjCList<ObjCProtocolDecl> &Protocols
4787 = Protocol->getReferencedProtocols();
4788 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4789 E = Protocols.end();
4790 I != E; ++I)
4791 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4792 NumSelIdents, CurContext, Selectors, AllowSameLength,
4793 Results, false);
4794 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004795 }
4796
Douglas Gregor36ecb042009-11-17 23:22:23 +00004797 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004798 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004799 return;
4800
4801 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004802 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4803 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004804 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004805 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004806 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004807
4808 // Add methods in categories.
4809 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4810 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004811 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004812 NumSelIdents, CurContext, Selectors, AllowSameLength,
4813 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004814
4815 // Add a categories protocol methods.
4816 const ObjCList<ObjCProtocolDecl> &Protocols
4817 = CatDecl->getReferencedProtocols();
4818 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4819 E = Protocols.end();
4820 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004821 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004822 NumSelIdents, CurContext, Selectors, AllowSameLength,
4823 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004824
4825 // Add methods in category implementations.
4826 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004827 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004828 NumSelIdents, CurContext, Selectors, AllowSameLength,
4829 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004830 }
4831
4832 // Add methods in superclass.
4833 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004834 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004835 SelIdents, NumSelIdents, CurContext, Selectors,
4836 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004837
4838 // Add methods in our implementation, if any.
4839 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004840 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004841 NumSelIdents, CurContext, Selectors, AllowSameLength,
4842 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004843}
4844
4845
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004846void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004847 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004848
4849 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004850 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004851 if (!Class) {
4852 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004853 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004854 Class = Category->getClassInterface();
4855
4856 if (!Class)
4857 return;
4858 }
4859
4860 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004861 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004862 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004863 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004864 Results.EnterNewScope();
4865
Douglas Gregord36adf52010-09-16 16:06:31 +00004866 VisitedSelectorSet Selectors;
4867 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004868 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004869 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004870 HandleCodeCompleteResults(this, CodeCompleter,
4871 CodeCompletionContext::CCC_Other,
4872 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004873}
4874
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004875void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004876 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004877
4878 // Try to find the interface where setters might live.
4879 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004880 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004881 if (!Class) {
4882 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004883 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004884 Class = Category->getClassInterface();
4885
4886 if (!Class)
4887 return;
4888 }
4889
4890 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004891 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004892 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004893 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004894 Results.EnterNewScope();
4895
Douglas Gregord36adf52010-09-16 16:06:31 +00004896 VisitedSelectorSet Selectors;
4897 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004898 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004899
4900 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004901 HandleCodeCompleteResults(this, CodeCompleter,
4902 CodeCompletionContext::CCC_Other,
4903 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004904}
4905
Douglas Gregorafc45782011-02-15 22:19:42 +00004906void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4907 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004908 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004909 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004910 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004911 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004912 Results.EnterNewScope();
4913
4914 // Add context-sensitive, Objective-C parameter-passing keywords.
4915 bool AddedInOut = false;
4916 if ((DS.getObjCDeclQualifier() &
4917 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4918 Results.AddResult("in");
4919 Results.AddResult("inout");
4920 AddedInOut = true;
4921 }
4922 if ((DS.getObjCDeclQualifier() &
4923 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4924 Results.AddResult("out");
4925 if (!AddedInOut)
4926 Results.AddResult("inout");
4927 }
4928 if ((DS.getObjCDeclQualifier() &
4929 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4930 ObjCDeclSpec::DQ_Oneway)) == 0) {
4931 Results.AddResult("bycopy");
4932 Results.AddResult("byref");
4933 Results.AddResult("oneway");
4934 }
4935
Douglas Gregorafc45782011-02-15 22:19:42 +00004936 // If we're completing the return type of an Objective-C method and the
4937 // identifier IBAction refers to a macro, provide a completion item for
4938 // an action, e.g.,
4939 // IBAction)<#selector#>:(id)sender
4940 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4941 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004942 CodeCompletionBuilder Builder(Results.getAllocator(),
4943 Results.getCodeCompletionTUInfo(),
4944 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004945 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004946 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004947 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004948 Builder.AddChunk(CodeCompletionString::CK_Colon);
4949 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004950 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004951 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004952 Builder.AddTextChunk("sender");
4953 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4954 }
4955
Douglas Gregord32b0222010-08-24 01:06:58 +00004956 // Add various builtin type names and specifiers.
4957 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4958 Results.ExitScope();
4959
4960 // Add the various type names
4961 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4962 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4963 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4964 CodeCompleter->includeGlobals());
4965
4966 if (CodeCompleter->includeMacros())
4967 AddMacroResults(PP, Results);
4968
4969 HandleCodeCompleteResults(this, CodeCompleter,
4970 CodeCompletionContext::CCC_Type,
4971 Results.data(), Results.size());
4972}
4973
Douglas Gregor22f56992010-04-06 19:22:33 +00004974/// \brief When we have an expression with type "id", we may assume
4975/// that it has some more-specific class type based on knowledge of
4976/// common uses of Objective-C. This routine returns that class type,
4977/// or NULL if no better result could be determined.
4978static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004979 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004980 if (!Msg)
4981 return 0;
4982
4983 Selector Sel = Msg->getSelector();
4984 if (Sel.isNull())
4985 return 0;
4986
4987 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4988 if (!Id)
4989 return 0;
4990
4991 ObjCMethodDecl *Method = Msg->getMethodDecl();
4992 if (!Method)
4993 return 0;
4994
4995 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004996 ObjCInterfaceDecl *IFace = 0;
4997 switch (Msg->getReceiverKind()) {
4998 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004999 if (const ObjCObjectType *ObjType
5000 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5001 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00005002 break;
5003
5004 case ObjCMessageExpr::Instance: {
5005 QualType T = Msg->getInstanceReceiver()->getType();
5006 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5007 IFace = Ptr->getInterfaceDecl();
5008 break;
5009 }
5010
5011 case ObjCMessageExpr::SuperInstance:
5012 case ObjCMessageExpr::SuperClass:
5013 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00005014 }
5015
5016 if (!IFace)
5017 return 0;
5018
5019 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5020 if (Method->isInstanceMethod())
5021 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5022 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005023 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005024 .Case("autorelease", IFace)
5025 .Case("copy", IFace)
5026 .Case("copyWithZone", IFace)
5027 .Case("mutableCopy", IFace)
5028 .Case("mutableCopyWithZone", IFace)
5029 .Case("awakeFromCoder", IFace)
5030 .Case("replacementObjectFromCoder", IFace)
5031 .Case("class", IFace)
5032 .Case("classForCoder", IFace)
5033 .Case("superclass", Super)
5034 .Default(0);
5035
5036 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5037 .Case("new", IFace)
5038 .Case("alloc", IFace)
5039 .Case("allocWithZone", IFace)
5040 .Case("class", IFace)
5041 .Case("superclass", Super)
5042 .Default(0);
5043}
5044
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005045// Add a special completion for a message send to "super", which fills in the
5046// most likely case of forwarding all of our arguments to the superclass
5047// function.
5048///
5049/// \param S The semantic analysis object.
5050///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00005051/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005052/// the "super" keyword. Otherwise, we just need to provide the arguments.
5053///
5054/// \param SelIdents The identifiers in the selector that have already been
5055/// provided as arguments for a send to "super".
5056///
5057/// \param NumSelIdents The number of identifiers in \p SelIdents.
5058///
5059/// \param Results The set of results to augment.
5060///
5061/// \returns the Objective-C method declaration that would be invoked by
5062/// this "super" completion. If NULL, no completion was added.
5063static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5064 IdentifierInfo **SelIdents,
5065 unsigned NumSelIdents,
5066 ResultBuilder &Results) {
5067 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5068 if (!CurMethod)
5069 return 0;
5070
5071 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5072 if (!Class)
5073 return 0;
5074
5075 // Try to find a superclass method with the same selector.
5076 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005077 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5078 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005079 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5080 CurMethod->isInstanceMethod());
5081
Douglas Gregor78bcd912011-02-16 00:51:18 +00005082 // Check in categories or class extensions.
5083 if (!SuperMethod) {
5084 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5085 Category = Category->getNextClassCategory())
5086 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
5087 CurMethod->isInstanceMethod())))
5088 break;
5089 }
5090 }
5091
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005092 if (!SuperMethod)
5093 return 0;
5094
5095 // Check whether the superclass method has the same signature.
5096 if (CurMethod->param_size() != SuperMethod->param_size() ||
5097 CurMethod->isVariadic() != SuperMethod->isVariadic())
5098 return 0;
5099
5100 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5101 CurPEnd = CurMethod->param_end(),
5102 SuperP = SuperMethod->param_begin();
5103 CurP != CurPEnd; ++CurP, ++SuperP) {
5104 // Make sure the parameter types are compatible.
5105 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5106 (*SuperP)->getType()))
5107 return 0;
5108
5109 // Make sure we have a parameter name to forward!
5110 if (!(*CurP)->getIdentifier())
5111 return 0;
5112 }
5113
5114 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005115 CodeCompletionBuilder Builder(Results.getAllocator(),
5116 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005117
5118 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005119 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5120 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005121
5122 // If we need the "super" keyword, add it (plus some spacing).
5123 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005124 Builder.AddTypedTextChunk("super");
5125 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005126 }
5127
5128 Selector Sel = CurMethod->getSelector();
5129 if (Sel.isUnarySelector()) {
5130 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005131 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005132 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005133 else
Douglas Gregordae68752011-02-01 22:57:45 +00005134 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005135 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005136 } else {
5137 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5138 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5139 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005140 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005141
5142 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005143 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005144 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005145 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005146 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005147 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005148 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005149 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005150 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005151 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005152 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005153 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005154 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005155 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005156 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005157 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005158 }
5159 }
5160 }
5161
Douglas Gregorba103062012-03-27 23:34:16 +00005162 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5163 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005164 return SuperMethod;
5165}
5166
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005167void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005168 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005169 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005170 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005171 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005172 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005173 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5174 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005175
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005176 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5177 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005178 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5179 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005180
5181 // If we are in an Objective-C method inside a class that has a superclass,
5182 // add "super" as an option.
5183 if (ObjCMethodDecl *Method = getCurMethodDecl())
5184 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005185 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005186 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005187
5188 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5189 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005190
David Blaikie4e4d0842012-03-11 07:00:24 +00005191 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005192 addThisCompletion(*this, Results);
5193
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005194 Results.ExitScope();
5195
5196 if (CodeCompleter->includeMacros())
5197 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005198 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005199 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005200
5201}
5202
Douglas Gregor2725ca82010-04-21 19:57:20 +00005203void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5204 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005205 unsigned NumSelIdents,
5206 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005207 ObjCInterfaceDecl *CDecl = 0;
5208 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5209 // Figure out which interface we're in.
5210 CDecl = CurMethod->getClassInterface();
5211 if (!CDecl)
5212 return;
5213
5214 // Find the superclass of this class.
5215 CDecl = CDecl->getSuperClass();
5216 if (!CDecl)
5217 return;
5218
5219 if (CurMethod->isInstanceMethod()) {
5220 // We are inside an instance method, which means that the message
5221 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005222 // current object.
5223 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005224 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005225 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005226 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005227 }
5228
5229 // Fall through to send to the superclass in CDecl.
5230 } else {
5231 // "super" may be the name of a type or variable. Figure out which
5232 // it is.
5233 IdentifierInfo *Super = &Context.Idents.get("super");
5234 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5235 LookupOrdinaryName);
5236 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5237 // "super" names an interface. Use it.
5238 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005239 if (const ObjCObjectType *Iface
5240 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5241 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005242 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5243 // "super" names an unresolved type; we can't be more specific.
5244 } else {
5245 // Assume that "super" names some kind of value and parse that way.
5246 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005247 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005248 UnqualifiedId id;
5249 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005250 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5251 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005252 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005253 SelIdents, NumSelIdents,
5254 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005255 }
5256
5257 // Fall through
5258 }
5259
John McCallb3d87482010-08-24 05:47:05 +00005260 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005261 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005262 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005263 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005264 NumSelIdents, AtArgumentExpression,
5265 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005266}
5267
Douglas Gregorb9d77572010-09-21 00:03:25 +00005268/// \brief Given a set of code-completion results for the argument of a message
5269/// send, determine the preferred type (if any) for that argument expression.
5270static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5271 unsigned NumSelIdents) {
5272 typedef CodeCompletionResult Result;
5273 ASTContext &Context = Results.getSema().Context;
5274
5275 QualType PreferredType;
5276 unsigned BestPriority = CCP_Unlikely * 2;
5277 Result *ResultsData = Results.data();
5278 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5279 Result &R = ResultsData[I];
5280 if (R.Kind == Result::RK_Declaration &&
5281 isa<ObjCMethodDecl>(R.Declaration)) {
5282 if (R.Priority <= BestPriority) {
5283 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5284 if (NumSelIdents <= Method->param_size()) {
5285 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5286 ->getType();
5287 if (R.Priority < BestPriority || PreferredType.isNull()) {
5288 BestPriority = R.Priority;
5289 PreferredType = MyPreferredType;
5290 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5291 MyPreferredType)) {
5292 PreferredType = QualType();
5293 }
5294 }
5295 }
5296 }
5297 }
5298
5299 return PreferredType;
5300}
5301
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005302static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5303 ParsedType Receiver,
5304 IdentifierInfo **SelIdents,
5305 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005306 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005307 bool IsSuper,
5308 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005309 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005310 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005311
Douglas Gregor24a069f2009-11-17 17:59:40 +00005312 // If the given name refers to an interface type, retrieve the
5313 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005314 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005315 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005316 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005317 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5318 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005319 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005320
Douglas Gregor36ecb042009-11-17 23:22:23 +00005321 // Add all of the factory methods in this Objective-C class, its protocols,
5322 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005323 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005324
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005325 // If this is a send-to-super, try to add the special "super" send
5326 // completion.
5327 if (IsSuper) {
5328 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005329 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5330 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005331 Results.Ignore(SuperMethod);
5332 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005333
Douglas Gregor265f7492010-08-27 15:29:55 +00005334 // If we're inside an Objective-C method definition, prefer its selector to
5335 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005336 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005337 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005338
Douglas Gregord36adf52010-09-16 16:06:31 +00005339 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005340 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005341 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005342 SemaRef.CurContext, Selectors, AtArgumentExpression,
5343 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005344 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005345 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005346
Douglas Gregor719770d2010-04-06 17:30:22 +00005347 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005348 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005349 if (SemaRef.ExternalSource) {
5350 for (uint32_t I = 0,
5351 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005352 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005353 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5354 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005355 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005356
5357 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005358 }
5359 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005360
5361 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5362 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005363 M != MEnd; ++M) {
5364 for (ObjCMethodList *MethList = &M->second.second;
5365 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005366 MethList = MethList->Next) {
5367 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5368 NumSelIdents))
5369 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005370
Douglas Gregor13438f92010-04-06 16:40:00 +00005371 Result R(MethList->Method, 0);
5372 R.StartParameter = NumSelIdents;
5373 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005374 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005375 }
5376 }
5377 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005378
5379 Results.ExitScope();
5380}
Douglas Gregor13438f92010-04-06 16:40:00 +00005381
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005382void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5383 IdentifierInfo **SelIdents,
5384 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005385 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005386 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005387
5388 QualType T = this->GetTypeFromParser(Receiver);
5389
Douglas Gregor218937c2011-02-01 19:23:04 +00005390 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005391 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005392 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005393 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005394
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005395 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5396 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005397
5398 // If we're actually at the argument expression (rather than prior to the
5399 // selector), we're actually performing code completion for an expression.
5400 // Determine whether we have a single, best method. If so, we can
5401 // code-complete the expression using the corresponding parameter type as
5402 // our preferred type, improving completion results.
5403 if (AtArgumentExpression) {
5404 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005405 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005406 if (PreferredType.isNull())
5407 CodeCompleteOrdinaryName(S, PCC_Expression);
5408 else
5409 CodeCompleteExpression(S, PreferredType);
5410 return;
5411 }
5412
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005413 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005414 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005415 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005416}
5417
Richard Trieuf81e5a92011-09-09 02:00:50 +00005418void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005419 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005420 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005421 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005422 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005423 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005424
5425 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005426
Douglas Gregor36ecb042009-11-17 23:22:23 +00005427 // If necessary, apply function/array conversion to the receiver.
5428 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005429 if (RecExpr) {
5430 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5431 if (Conv.isInvalid()) // conversion failed. bail.
5432 return;
5433 RecExpr = Conv.take();
5434 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005435 QualType ReceiverType = RecExpr? RecExpr->getType()
5436 : Super? Context.getObjCObjectPointerType(
5437 Context.getObjCInterfaceType(Super))
5438 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005439
Douglas Gregorda892642010-11-08 21:12:30 +00005440 // If we're messaging an expression with type "id" or "Class", check
5441 // whether we know something special about the receiver that allows
5442 // us to assume a more-specific receiver type.
5443 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5444 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5445 if (ReceiverType->isObjCClassType())
5446 return CodeCompleteObjCClassMessage(S,
5447 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5448 SelIdents, NumSelIdents,
5449 AtArgumentExpression, Super);
5450
5451 ReceiverType = Context.getObjCObjectPointerType(
5452 Context.getObjCInterfaceType(IFace));
5453 }
5454
Douglas Gregor36ecb042009-11-17 23:22:23 +00005455 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005456 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005457 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005458 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005459 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005460
Douglas Gregor36ecb042009-11-17 23:22:23 +00005461 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005462
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005463 // If this is a send-to-super, try to add the special "super" send
5464 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005465 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005466 if (ObjCMethodDecl *SuperMethod
5467 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5468 Results))
5469 Results.Ignore(SuperMethod);
5470 }
5471
Douglas Gregor265f7492010-08-27 15:29:55 +00005472 // If we're inside an Objective-C method definition, prefer its selector to
5473 // others.
5474 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5475 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005476
Douglas Gregord36adf52010-09-16 16:06:31 +00005477 // Keep track of the selectors we've already added.
5478 VisitedSelectorSet Selectors;
5479
Douglas Gregorf74a4192009-11-18 00:06:18 +00005480 // Handle messages to Class. This really isn't a message to an instance
5481 // method, so we treat it the same way we would treat a message send to a
5482 // class method.
5483 if (ReceiverType->isObjCClassType() ||
5484 ReceiverType->isObjCQualifiedClassType()) {
5485 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5486 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005487 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005488 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005489 }
5490 }
5491 // Handle messages to a qualified ID ("id<foo>").
5492 else if (const ObjCObjectPointerType *QualID
5493 = ReceiverType->getAsObjCQualifiedIdType()) {
5494 // Search protocols for instance methods.
5495 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5496 E = QualID->qual_end();
5497 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005498 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005499 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005500 }
5501 // Handle messages to a pointer to interface type.
5502 else if (const ObjCObjectPointerType *IFacePtr
5503 = ReceiverType->getAsObjCInterfacePointerType()) {
5504 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005505 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005506 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5507 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005508
5509 // Search protocols for instance methods.
5510 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5511 E = IFacePtr->qual_end();
5512 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005513 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005514 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005515 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005516 // Handle messages to "id".
5517 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005518 // We're messaging "id", so provide all instance methods we know
5519 // about as code-completion results.
5520
5521 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005522 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005523 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005524 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5525 I != N; ++I) {
5526 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005527 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005528 continue;
5529
Sebastian Redldb9d2142010-08-02 23:18:59 +00005530 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005531 }
5532 }
5533
Sebastian Redldb9d2142010-08-02 23:18:59 +00005534 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5535 MEnd = MethodPool.end();
5536 M != MEnd; ++M) {
5537 for (ObjCMethodList *MethList = &M->second.first;
5538 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005539 MethList = MethList->Next) {
5540 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5541 NumSelIdents))
5542 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005543
5544 if (!Selectors.insert(MethList->Method->getSelector()))
5545 continue;
5546
Douglas Gregor13438f92010-04-06 16:40:00 +00005547 Result R(MethList->Method, 0);
5548 R.StartParameter = NumSelIdents;
5549 R.AllParametersAreInformative = false;
5550 Results.MaybeAddResult(R, CurContext);
5551 }
5552 }
5553 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005554 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005555
5556
5557 // If we're actually at the argument expression (rather than prior to the
5558 // selector), we're actually performing code completion for an expression.
5559 // Determine whether we have a single, best method. If so, we can
5560 // code-complete the expression using the corresponding parameter type as
5561 // our preferred type, improving completion results.
5562 if (AtArgumentExpression) {
5563 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5564 NumSelIdents);
5565 if (PreferredType.isNull())
5566 CodeCompleteOrdinaryName(S, PCC_Expression);
5567 else
5568 CodeCompleteExpression(S, PreferredType);
5569 return;
5570 }
5571
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005572 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005573 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005574 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005575}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005576
Douglas Gregorfb629412010-08-23 21:17:50 +00005577void Sema::CodeCompleteObjCForCollection(Scope *S,
5578 DeclGroupPtrTy IterationVar) {
5579 CodeCompleteExpressionData Data;
5580 Data.ObjCCollection = true;
5581
5582 if (IterationVar.getAsOpaquePtr()) {
5583 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5584 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5585 if (*I)
5586 Data.IgnoreDecls.push_back(*I);
5587 }
5588 }
5589
5590 CodeCompleteExpression(S, Data);
5591}
5592
Douglas Gregor458433d2010-08-26 15:07:07 +00005593void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5594 unsigned NumSelIdents) {
5595 // If we have an external source, load the entire class method
5596 // pool from the AST file.
5597 if (ExternalSource) {
5598 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5599 I != N; ++I) {
5600 Selector Sel = ExternalSource->GetExternalSelector(I);
5601 if (Sel.isNull() || MethodPool.count(Sel))
5602 continue;
5603
5604 ReadMethodPool(Sel);
5605 }
5606 }
5607
Douglas Gregor218937c2011-02-01 19:23:04 +00005608 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005609 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005610 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005611 Results.EnterNewScope();
5612 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5613 MEnd = MethodPool.end();
5614 M != MEnd; ++M) {
5615
5616 Selector Sel = M->first;
5617 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5618 continue;
5619
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005620 CodeCompletionBuilder Builder(Results.getAllocator(),
5621 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005622 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005623 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005624 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005625 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005626 continue;
5627 }
5628
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005629 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005630 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005631 if (I == NumSelIdents) {
5632 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005633 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005634 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005635 Accumulator.clear();
5636 }
5637 }
5638
Benjamin Kramera0651c52011-07-26 16:59:25 +00005639 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005640 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005641 }
Douglas Gregordae68752011-02-01 22:57:45 +00005642 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005643 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005644 }
5645 Results.ExitScope();
5646
5647 HandleCodeCompleteResults(this, CodeCompleter,
5648 CodeCompletionContext::CCC_SelectorName,
5649 Results.data(), Results.size());
5650}
5651
Douglas Gregor55385fe2009-11-18 04:19:12 +00005652/// \brief Add all of the protocol declarations that we find in the given
5653/// (translation unit) context.
5654static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005655 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005656 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005657 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005658
5659 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5660 DEnd = Ctx->decls_end();
5661 D != DEnd; ++D) {
5662 // Record any protocols we find.
5663 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005664 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005665 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005666 }
5667}
5668
5669void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5670 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005671 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005672 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005673 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005674
Douglas Gregor70c23352010-12-09 21:44:02 +00005675 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5676 Results.EnterNewScope();
5677
5678 // Tell the result set to ignore all of the protocols we have
5679 // already seen.
5680 // FIXME: This doesn't work when caching code-completion results.
5681 for (unsigned I = 0; I != NumProtocols; ++I)
5682 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5683 Protocols[I].second))
5684 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005685
Douglas Gregor70c23352010-12-09 21:44:02 +00005686 // Add all protocols.
5687 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5688 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005689
Douglas Gregor70c23352010-12-09 21:44:02 +00005690 Results.ExitScope();
5691 }
5692
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005693 HandleCodeCompleteResults(this, CodeCompleter,
5694 CodeCompletionContext::CCC_ObjCProtocolName,
5695 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005696}
5697
5698void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005699 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005700 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005701 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005702
Douglas Gregor70c23352010-12-09 21:44:02 +00005703 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5704 Results.EnterNewScope();
5705
5706 // Add all protocols.
5707 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5708 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005709
Douglas Gregor70c23352010-12-09 21:44:02 +00005710 Results.ExitScope();
5711 }
5712
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005713 HandleCodeCompleteResults(this, CodeCompleter,
5714 CodeCompletionContext::CCC_ObjCProtocolName,
5715 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005716}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005717
5718/// \brief Add all of the Objective-C interface declarations that we find in
5719/// the given (translation unit) context.
5720static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5721 bool OnlyForwardDeclarations,
5722 bool OnlyUnimplemented,
5723 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005724 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005725
5726 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5727 DEnd = Ctx->decls_end();
5728 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005729 // Record any interfaces we find.
5730 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005731 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005732 (!OnlyUnimplemented || !Class->getImplementation()))
5733 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005734 }
5735}
5736
5737void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005738 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005739 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005740 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005741 Results.EnterNewScope();
5742
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005743 if (CodeCompleter->includeGlobals()) {
5744 // Add all classes.
5745 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5746 false, Results);
5747 }
5748
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005749 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005750
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005751 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005752 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005753 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005754}
5755
Douglas Gregorc83c6872010-04-15 22:33:43 +00005756void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5757 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005758 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005759 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005760 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005761 Results.EnterNewScope();
5762
5763 // Make sure that we ignore the class we're currently defining.
5764 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005765 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005766 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005767 Results.Ignore(CurClass);
5768
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005769 if (CodeCompleter->includeGlobals()) {
5770 // Add all classes.
5771 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5772 false, Results);
5773 }
5774
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005775 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005776
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005777 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005778 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005779 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005780}
5781
5782void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005783 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005784 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005785 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005786 Results.EnterNewScope();
5787
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005788 if (CodeCompleter->includeGlobals()) {
5789 // Add all unimplemented classes.
5790 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5791 true, Results);
5792 }
5793
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005794 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005795
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005796 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005797 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005798 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005799}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005800
5801void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005802 IdentifierInfo *ClassName,
5803 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005804 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005805
Douglas Gregor218937c2011-02-01 19:23:04 +00005806 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005807 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005808 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005809
5810 // Ignore any categories we find that have already been implemented by this
5811 // interface.
5812 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5813 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005814 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005815 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5816 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5817 Category = Category->getNextClassCategory())
5818 CategoryNames.insert(Category->getIdentifier());
5819
5820 // Add all of the categories we know about.
5821 Results.EnterNewScope();
5822 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5823 for (DeclContext::decl_iterator D = TU->decls_begin(),
5824 DEnd = TU->decls_end();
5825 D != DEnd; ++D)
5826 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5827 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005828 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005829 Results.ExitScope();
5830
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005831 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005832 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005833 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005834}
5835
5836void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005837 IdentifierInfo *ClassName,
5838 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005839 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005840
5841 // Find the corresponding interface. If we couldn't find the interface, the
5842 // program itself is ill-formed. However, we'll try to be helpful still by
5843 // providing the list of all of the categories we know about.
5844 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005845 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005846 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5847 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005848 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005849
Douglas Gregor218937c2011-02-01 19:23:04 +00005850 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005851 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005852 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005853
5854 // Add all of the categories that have have corresponding interface
5855 // declarations in this class and any of its superclasses, except for
5856 // already-implemented categories in the class itself.
5857 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5858 Results.EnterNewScope();
5859 bool IgnoreImplemented = true;
5860 while (Class) {
5861 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5862 Category = Category->getNextClassCategory())
5863 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5864 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005865 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005866
5867 Class = Class->getSuperClass();
5868 IgnoreImplemented = false;
5869 }
5870 Results.ExitScope();
5871
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005872 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005873 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005874 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005875}
Douglas Gregor322328b2009-11-18 22:32:06 +00005876
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005877void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005878 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005879 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005880 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005881 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005882
5883 // Figure out where this @synthesize lives.
5884 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005885 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005886 if (!Container ||
5887 (!isa<ObjCImplementationDecl>(Container) &&
5888 !isa<ObjCCategoryImplDecl>(Container)))
5889 return;
5890
5891 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005892 Container = getContainerDef(Container);
5893 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005894 DEnd = Container->decls_end();
5895 D != DEnd; ++D)
5896 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5897 Results.Ignore(PropertyImpl->getPropertyDecl());
5898
5899 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005900 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005901 Results.EnterNewScope();
5902 if (ObjCImplementationDecl *ClassImpl
5903 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005904 AddObjCProperties(ClassImpl->getClassInterface(), false,
5905 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005906 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005907 else
5908 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005909 false, /*AllowNullaryMethods=*/false, CurContext,
5910 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005911 Results.ExitScope();
5912
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005913 HandleCodeCompleteResults(this, CodeCompleter,
5914 CodeCompletionContext::CCC_Other,
5915 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005916}
5917
5918void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005919 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005920 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005921 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005922 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005923 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005924
5925 // Figure out where this @synthesize lives.
5926 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005927 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005928 if (!Container ||
5929 (!isa<ObjCImplementationDecl>(Container) &&
5930 !isa<ObjCCategoryImplDecl>(Container)))
5931 return;
5932
5933 // Figure out which interface we're looking into.
5934 ObjCInterfaceDecl *Class = 0;
5935 if (ObjCImplementationDecl *ClassImpl
5936 = dyn_cast<ObjCImplementationDecl>(Container))
5937 Class = ClassImpl->getClassInterface();
5938 else
5939 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5940 ->getClassInterface();
5941
Douglas Gregore8426052011-04-18 14:40:46 +00005942 // Determine the type of the property we're synthesizing.
5943 QualType PropertyType = Context.getObjCIdType();
5944 if (Class) {
5945 if (ObjCPropertyDecl *Property
5946 = Class->FindPropertyDeclaration(PropertyName)) {
5947 PropertyType
5948 = Property->getType().getNonReferenceType().getUnqualifiedType();
5949
5950 // Give preference to ivars
5951 Results.setPreferredType(PropertyType);
5952 }
5953 }
5954
Douglas Gregor322328b2009-11-18 22:32:06 +00005955 // Add all of the instance variables in this class and its superclasses.
5956 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005957 bool SawSimilarlyNamedIvar = false;
5958 std::string NameWithPrefix;
5959 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005960 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005961 std::string NameWithSuffix = PropertyName->getName().str();
5962 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005963 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005964 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5965 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005966 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5967
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005968 // Determine whether we've seen an ivar with a name similar to the
5969 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005970 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005971 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005972 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005973 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005974
5975 // Reduce the priority of this result by one, to give it a slight
5976 // advantage over other results whose names don't match so closely.
5977 if (Results.size() &&
5978 Results.data()[Results.size() - 1].Kind
5979 == CodeCompletionResult::RK_Declaration &&
5980 Results.data()[Results.size() - 1].Declaration == Ivar)
5981 Results.data()[Results.size() - 1].Priority--;
5982 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005983 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005984 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005985
5986 if (!SawSimilarlyNamedIvar) {
5987 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005988 // an ivar of the appropriate type.
5989 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005990 typedef CodeCompletionResult Result;
5991 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005992 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
5993 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005994
Douglas Gregor8987b232011-09-27 23:30:47 +00005995 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005996 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005997 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005998 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5999 Results.AddResult(Result(Builder.TakeString(), Priority,
6000 CXCursor_ObjCIvarDecl));
6001 }
6002
Douglas Gregor322328b2009-11-18 22:32:06 +00006003 Results.ExitScope();
6004
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006005 HandleCodeCompleteResults(this, CodeCompleter,
6006 CodeCompletionContext::CCC_Other,
6007 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00006008}
Douglas Gregore8f5a172010-04-07 00:21:17 +00006009
Douglas Gregor408be5a2010-08-25 01:08:01 +00006010// Mapping from selectors to the methods that implement that selector, along
6011// with the "in original class" flag.
6012typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
6013 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006014
6015/// \brief Find all of the methods that reside in the given container
6016/// (and its superclasses, protocols, etc.) that meet the given
6017/// criteria. Insert those methods into the map of known methods,
6018/// indexed by selector so they can be easily found.
6019static void FindImplementableMethods(ASTContext &Context,
6020 ObjCContainerDecl *Container,
6021 bool WantInstanceMethods,
6022 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006023 KnownMethodsMap &KnownMethods,
6024 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006025 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006026 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006027 if (!IFace->hasDefinition())
6028 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006029
6030 IFace = IFace->getDefinition();
6031 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006032
Douglas Gregore8f5a172010-04-07 00:21:17 +00006033 const ObjCList<ObjCProtocolDecl> &Protocols
6034 = IFace->getReferencedProtocols();
6035 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006036 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006037 I != E; ++I)
6038 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006039 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006040
Douglas Gregorea766182010-10-18 18:21:28 +00006041 // Add methods from any class extensions and categories.
6042 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
6043 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00006044 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
6045 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006046 KnownMethods, false);
6047
6048 // Visit the superclass.
6049 if (IFace->getSuperClass())
6050 FindImplementableMethods(Context, IFace->getSuperClass(),
6051 WantInstanceMethods, ReturnType,
6052 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006053 }
6054
6055 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6056 // Recurse into protocols.
6057 const ObjCList<ObjCProtocolDecl> &Protocols
6058 = Category->getReferencedProtocols();
6059 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006060 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006061 I != E; ++I)
6062 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006063 KnownMethods, InOriginalClass);
6064
6065 // If this category is the original class, jump to the interface.
6066 if (InOriginalClass && Category->getClassInterface())
6067 FindImplementableMethods(Context, Category->getClassInterface(),
6068 WantInstanceMethods, ReturnType, KnownMethods,
6069 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006070 }
6071
6072 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006073 // Make sure we have a definition; that's what we'll walk.
6074 if (!Protocol->hasDefinition())
6075 return;
6076 Protocol = Protocol->getDefinition();
6077 Container = Protocol;
6078
6079 // Recurse into protocols.
6080 const ObjCList<ObjCProtocolDecl> &Protocols
6081 = Protocol->getReferencedProtocols();
6082 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6083 E = Protocols.end();
6084 I != E; ++I)
6085 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6086 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006087 }
6088
6089 // Add methods in this container. This operation occurs last because
6090 // we want the methods from this container to override any methods
6091 // we've previously seen with the same selector.
6092 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6093 MEnd = Container->meth_end();
6094 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006095 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006096 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006097 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006098 continue;
6099
David Blaikie581deb32012-06-06 20:45:41 +00006100 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006101 }
6102 }
6103}
6104
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006105/// \brief Add the parenthesized return or parameter type chunk to a code
6106/// completion string.
6107static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006108 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006109 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006110 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006111 CodeCompletionBuilder &Builder) {
6112 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006113 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6114 if (!Quals.empty())
6115 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006116 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006117 Builder.getAllocator()));
6118 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6119}
6120
6121/// \brief Determine whether the given class is or inherits from a class by
6122/// the given name.
6123static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006124 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006125 if (!Class)
6126 return false;
6127
6128 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6129 return true;
6130
6131 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6132}
6133
6134/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6135/// Key-Value Observing (KVO).
6136static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6137 bool IsInstanceMethod,
6138 QualType ReturnType,
6139 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006140 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006141 ResultBuilder &Results) {
6142 IdentifierInfo *PropName = Property->getIdentifier();
6143 if (!PropName || PropName->getLength() == 0)
6144 return;
6145
Douglas Gregor8987b232011-09-27 23:30:47 +00006146 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6147
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006148 // Builder that will create each code completion.
6149 typedef CodeCompletionResult Result;
6150 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006151 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006152
6153 // The selector table.
6154 SelectorTable &Selectors = Context.Selectors;
6155
6156 // The property name, copied into the code completion allocation region
6157 // on demand.
6158 struct KeyHolder {
6159 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006160 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006161 const char *CopiedKey;
6162
Chris Lattner5f9e2722011-07-23 10:55:15 +00006163 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006164 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6165
6166 operator const char *() {
6167 if (CopiedKey)
6168 return CopiedKey;
6169
6170 return CopiedKey = Allocator.CopyString(Key);
6171 }
6172 } Key(Allocator, PropName->getName());
6173
6174 // The uppercased name of the property name.
6175 std::string UpperKey = PropName->getName();
6176 if (!UpperKey.empty())
6177 UpperKey[0] = toupper(UpperKey[0]);
6178
6179 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6180 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6181 Property->getType());
6182 bool ReturnTypeMatchesVoid
6183 = ReturnType.isNull() || ReturnType->isVoidType();
6184
6185 // Add the normal accessor -(type)key.
6186 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006187 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006188 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6189 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006190 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6191 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006192
6193 Builder.AddTypedTextChunk(Key);
6194 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6195 CXCursor_ObjCInstanceMethodDecl));
6196 }
6197
6198 // If we have an integral or boolean property (or the user has provided
6199 // an integral or boolean return type), add the accessor -(type)isKey.
6200 if (IsInstanceMethod &&
6201 ((!ReturnType.isNull() &&
6202 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6203 (ReturnType.isNull() &&
6204 (Property->getType()->isIntegerType() ||
6205 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006206 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006207 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006208 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006209 if (ReturnType.isNull()) {
6210 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6211 Builder.AddTextChunk("BOOL");
6212 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6213 }
6214
6215 Builder.AddTypedTextChunk(
6216 Allocator.CopyString(SelectorId->getName()));
6217 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6218 CXCursor_ObjCInstanceMethodDecl));
6219 }
6220 }
6221
6222 // Add the normal mutator.
6223 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6224 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006225 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006226 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006227 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006228 if (ReturnType.isNull()) {
6229 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6230 Builder.AddTextChunk("void");
6231 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6232 }
6233
6234 Builder.AddTypedTextChunk(
6235 Allocator.CopyString(SelectorId->getName()));
6236 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006237 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6238 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006239 Builder.AddTextChunk(Key);
6240 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6241 CXCursor_ObjCInstanceMethodDecl));
6242 }
6243 }
6244
6245 // Indexed and unordered accessors
6246 unsigned IndexedGetterPriority = CCP_CodePattern;
6247 unsigned IndexedSetterPriority = CCP_CodePattern;
6248 unsigned UnorderedGetterPriority = CCP_CodePattern;
6249 unsigned UnorderedSetterPriority = CCP_CodePattern;
6250 if (const ObjCObjectPointerType *ObjCPointer
6251 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6252 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6253 // If this interface type is not provably derived from a known
6254 // collection, penalize the corresponding completions.
6255 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6256 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6257 if (!InheritsFromClassNamed(IFace, "NSArray"))
6258 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6259 }
6260
6261 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6262 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6263 if (!InheritsFromClassNamed(IFace, "NSSet"))
6264 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6265 }
6266 }
6267 } else {
6268 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6269 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6270 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6271 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6272 }
6273
6274 // Add -(NSUInteger)countOf<key>
6275 if (IsInstanceMethod &&
6276 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006277 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006278 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006279 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006280 if (ReturnType.isNull()) {
6281 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6282 Builder.AddTextChunk("NSUInteger");
6283 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6284 }
6285
6286 Builder.AddTypedTextChunk(
6287 Allocator.CopyString(SelectorId->getName()));
6288 Results.AddResult(Result(Builder.TakeString(),
6289 std::min(IndexedGetterPriority,
6290 UnorderedGetterPriority),
6291 CXCursor_ObjCInstanceMethodDecl));
6292 }
6293 }
6294
6295 // Indexed getters
6296 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6297 if (IsInstanceMethod &&
6298 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006299 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006300 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006301 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006302 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006303 if (ReturnType.isNull()) {
6304 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6305 Builder.AddTextChunk("id");
6306 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6307 }
6308
6309 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6310 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6311 Builder.AddTextChunk("NSUInteger");
6312 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6313 Builder.AddTextChunk("index");
6314 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6315 CXCursor_ObjCInstanceMethodDecl));
6316 }
6317 }
6318
6319 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6320 if (IsInstanceMethod &&
6321 (ReturnType.isNull() ||
6322 (ReturnType->isObjCObjectPointerType() &&
6323 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6324 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6325 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006326 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006327 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006328 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006329 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006330 if (ReturnType.isNull()) {
6331 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6332 Builder.AddTextChunk("NSArray *");
6333 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6334 }
6335
6336 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6337 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6338 Builder.AddTextChunk("NSIndexSet *");
6339 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6340 Builder.AddTextChunk("indexes");
6341 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6342 CXCursor_ObjCInstanceMethodDecl));
6343 }
6344 }
6345
6346 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6347 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006348 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006349 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006350 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006351 &Context.Idents.get("range")
6352 };
6353
Douglas Gregore74c25c2011-05-04 23:50:46 +00006354 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006355 if (ReturnType.isNull()) {
6356 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6357 Builder.AddTextChunk("void");
6358 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6359 }
6360
6361 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6362 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6363 Builder.AddPlaceholderChunk("object-type");
6364 Builder.AddTextChunk(" **");
6365 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6366 Builder.AddTextChunk("buffer");
6367 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6368 Builder.AddTypedTextChunk("range:");
6369 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6370 Builder.AddTextChunk("NSRange");
6371 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6372 Builder.AddTextChunk("inRange");
6373 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6374 CXCursor_ObjCInstanceMethodDecl));
6375 }
6376 }
6377
6378 // Mutable indexed accessors
6379
6380 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6381 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006382 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006383 IdentifierInfo *SelectorIds[2] = {
6384 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006385 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006386 };
6387
Douglas Gregore74c25c2011-05-04 23:50:46 +00006388 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006389 if (ReturnType.isNull()) {
6390 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6391 Builder.AddTextChunk("void");
6392 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6393 }
6394
6395 Builder.AddTypedTextChunk("insertObject:");
6396 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6397 Builder.AddPlaceholderChunk("object-type");
6398 Builder.AddTextChunk(" *");
6399 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6400 Builder.AddTextChunk("object");
6401 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6402 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6403 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6404 Builder.AddPlaceholderChunk("NSUInteger");
6405 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6406 Builder.AddTextChunk("index");
6407 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6408 CXCursor_ObjCInstanceMethodDecl));
6409 }
6410 }
6411
6412 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6413 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006414 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006415 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006416 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006417 &Context.Idents.get("atIndexes")
6418 };
6419
Douglas Gregore74c25c2011-05-04 23:50:46 +00006420 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006421 if (ReturnType.isNull()) {
6422 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6423 Builder.AddTextChunk("void");
6424 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6425 }
6426
6427 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6428 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6429 Builder.AddTextChunk("NSArray *");
6430 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6431 Builder.AddTextChunk("array");
6432 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6433 Builder.AddTypedTextChunk("atIndexes:");
6434 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6435 Builder.AddPlaceholderChunk("NSIndexSet *");
6436 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6437 Builder.AddTextChunk("indexes");
6438 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6439 CXCursor_ObjCInstanceMethodDecl));
6440 }
6441 }
6442
6443 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6444 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006445 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006446 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006447 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006448 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006449 if (ReturnType.isNull()) {
6450 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6451 Builder.AddTextChunk("void");
6452 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6453 }
6454
6455 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6456 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6457 Builder.AddTextChunk("NSUInteger");
6458 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6459 Builder.AddTextChunk("index");
6460 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6461 CXCursor_ObjCInstanceMethodDecl));
6462 }
6463 }
6464
6465 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6466 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006467 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006468 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006469 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006470 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006471 if (ReturnType.isNull()) {
6472 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6473 Builder.AddTextChunk("void");
6474 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6475 }
6476
6477 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6478 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6479 Builder.AddTextChunk("NSIndexSet *");
6480 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6481 Builder.AddTextChunk("indexes");
6482 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6483 CXCursor_ObjCInstanceMethodDecl));
6484 }
6485 }
6486
6487 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6488 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006489 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006490 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006491 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006492 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006493 &Context.Idents.get("withObject")
6494 };
6495
Douglas Gregore74c25c2011-05-04 23:50:46 +00006496 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006497 if (ReturnType.isNull()) {
6498 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6499 Builder.AddTextChunk("void");
6500 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6501 }
6502
6503 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6504 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6505 Builder.AddPlaceholderChunk("NSUInteger");
6506 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6507 Builder.AddTextChunk("index");
6508 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6509 Builder.AddTypedTextChunk("withObject:");
6510 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6511 Builder.AddTextChunk("id");
6512 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6513 Builder.AddTextChunk("object");
6514 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6515 CXCursor_ObjCInstanceMethodDecl));
6516 }
6517 }
6518
6519 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6520 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006521 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006522 = (Twine("replace") + UpperKey + "AtIndexes").str();
6523 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006524 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006525 &Context.Idents.get(SelectorName1),
6526 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006527 };
6528
Douglas Gregore74c25c2011-05-04 23:50:46 +00006529 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006530 if (ReturnType.isNull()) {
6531 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6532 Builder.AddTextChunk("void");
6533 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6534 }
6535
6536 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6537 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6538 Builder.AddPlaceholderChunk("NSIndexSet *");
6539 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6540 Builder.AddTextChunk("indexes");
6541 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6542 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6543 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6544 Builder.AddTextChunk("NSArray *");
6545 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6546 Builder.AddTextChunk("array");
6547 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6548 CXCursor_ObjCInstanceMethodDecl));
6549 }
6550 }
6551
6552 // Unordered getters
6553 // - (NSEnumerator *)enumeratorOfKey
6554 if (IsInstanceMethod &&
6555 (ReturnType.isNull() ||
6556 (ReturnType->isObjCObjectPointerType() &&
6557 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6558 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6559 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006560 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006561 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006562 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006563 if (ReturnType.isNull()) {
6564 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6565 Builder.AddTextChunk("NSEnumerator *");
6566 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6567 }
6568
6569 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6570 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6571 CXCursor_ObjCInstanceMethodDecl));
6572 }
6573 }
6574
6575 // - (type *)memberOfKey:(type *)object
6576 if (IsInstanceMethod &&
6577 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006578 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006579 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006580 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006581 if (ReturnType.isNull()) {
6582 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6583 Builder.AddPlaceholderChunk("object-type");
6584 Builder.AddTextChunk(" *");
6585 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6586 }
6587
6588 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6589 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6590 if (ReturnType.isNull()) {
6591 Builder.AddPlaceholderChunk("object-type");
6592 Builder.AddTextChunk(" *");
6593 } else {
6594 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006595 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006596 Builder.getAllocator()));
6597 }
6598 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6599 Builder.AddTextChunk("object");
6600 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6601 CXCursor_ObjCInstanceMethodDecl));
6602 }
6603 }
6604
6605 // Mutable unordered accessors
6606 // - (void)addKeyObject:(type *)object
6607 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006608 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006609 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006610 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006611 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006612 if (ReturnType.isNull()) {
6613 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6614 Builder.AddTextChunk("void");
6615 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6616 }
6617
6618 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6619 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6620 Builder.AddPlaceholderChunk("object-type");
6621 Builder.AddTextChunk(" *");
6622 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6623 Builder.AddTextChunk("object");
6624 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6625 CXCursor_ObjCInstanceMethodDecl));
6626 }
6627 }
6628
6629 // - (void)addKey:(NSSet *)objects
6630 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006631 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006632 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006633 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006634 if (ReturnType.isNull()) {
6635 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6636 Builder.AddTextChunk("void");
6637 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6638 }
6639
6640 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6641 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6642 Builder.AddTextChunk("NSSet *");
6643 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6644 Builder.AddTextChunk("objects");
6645 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6646 CXCursor_ObjCInstanceMethodDecl));
6647 }
6648 }
6649
6650 // - (void)removeKeyObject:(type *)object
6651 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006652 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006653 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006654 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006655 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006656 if (ReturnType.isNull()) {
6657 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6658 Builder.AddTextChunk("void");
6659 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6660 }
6661
6662 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6663 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6664 Builder.AddPlaceholderChunk("object-type");
6665 Builder.AddTextChunk(" *");
6666 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6667 Builder.AddTextChunk("object");
6668 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6669 CXCursor_ObjCInstanceMethodDecl));
6670 }
6671 }
6672
6673 // - (void)removeKey:(NSSet *)objects
6674 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006675 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006676 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006677 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006678 if (ReturnType.isNull()) {
6679 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6680 Builder.AddTextChunk("void");
6681 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6682 }
6683
6684 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6685 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6686 Builder.AddTextChunk("NSSet *");
6687 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6688 Builder.AddTextChunk("objects");
6689 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6690 CXCursor_ObjCInstanceMethodDecl));
6691 }
6692 }
6693
6694 // - (void)intersectKey:(NSSet *)objects
6695 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006696 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006697 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006698 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006699 if (ReturnType.isNull()) {
6700 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6701 Builder.AddTextChunk("void");
6702 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6703 }
6704
6705 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6706 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6707 Builder.AddTextChunk("NSSet *");
6708 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6709 Builder.AddTextChunk("objects");
6710 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6711 CXCursor_ObjCInstanceMethodDecl));
6712 }
6713 }
6714
6715 // Key-Value Observing
6716 // + (NSSet *)keyPathsForValuesAffectingKey
6717 if (!IsInstanceMethod &&
6718 (ReturnType.isNull() ||
6719 (ReturnType->isObjCObjectPointerType() &&
6720 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6721 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6722 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006723 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006724 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006725 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006726 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006727 if (ReturnType.isNull()) {
6728 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6729 Builder.AddTextChunk("NSSet *");
6730 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6731 }
6732
6733 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6734 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006735 CXCursor_ObjCClassMethodDecl));
6736 }
6737 }
6738
6739 // + (BOOL)automaticallyNotifiesObserversForKey
6740 if (!IsInstanceMethod &&
6741 (ReturnType.isNull() ||
6742 ReturnType->isIntegerType() ||
6743 ReturnType->isBooleanType())) {
6744 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006745 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006746 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6747 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6748 if (ReturnType.isNull()) {
6749 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6750 Builder.AddTextChunk("BOOL");
6751 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6752 }
6753
6754 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6755 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6756 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006757 }
6758 }
6759}
6760
Douglas Gregore8f5a172010-04-07 00:21:17 +00006761void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6762 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006763 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006764 // Determine the return type of the method we're declaring, if
6765 // provided.
6766 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006767 Decl *IDecl = 0;
6768 if (CurContext->isObjCContainer()) {
6769 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6770 IDecl = cast<Decl>(OCD);
6771 }
Douglas Gregorea766182010-10-18 18:21:28 +00006772 // Determine where we should start searching for methods.
6773 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006774 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006775 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006776 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6777 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006778 IsInImplementation = true;
6779 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006780 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006781 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006782 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006783 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006784 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006785 }
6786
6787 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006788 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006789 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006790 }
6791
Douglas Gregorea766182010-10-18 18:21:28 +00006792 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006793 HandleCodeCompleteResults(this, CodeCompleter,
6794 CodeCompletionContext::CCC_Other,
6795 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006796 return;
6797 }
6798
6799 // Find all of the methods that we could declare/implement here.
6800 KnownMethodsMap KnownMethods;
6801 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006802 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006803
Douglas Gregore8f5a172010-04-07 00:21:17 +00006804 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006805 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006806 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006807 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006808 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006809 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006810 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006811 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6812 MEnd = KnownMethods.end();
6813 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006814 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006815 CodeCompletionBuilder Builder(Results.getAllocator(),
6816 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006817
6818 // If the result type was not already provided, add it to the
6819 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006820 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006821 AddObjCPassingTypeChunk(Method->getResultType(),
6822 Method->getObjCDeclQualifier(),
6823 Context, Policy,
6824 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006825
6826 Selector Sel = Method->getSelector();
6827
6828 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006829 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006830 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006831
6832 // Add parameters to the pattern.
6833 unsigned I = 0;
6834 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6835 PEnd = Method->param_end();
6836 P != PEnd; (void)++P, ++I) {
6837 // Add the part of the selector name.
6838 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006839 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006840 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006841 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6842 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006843 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006844 } else
6845 break;
6846
6847 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006848 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6849 (*P)->getObjCDeclQualifier(),
6850 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006851 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006852
6853 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006854 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006855 }
6856
6857 if (Method->isVariadic()) {
6858 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006859 Builder.AddChunk(CodeCompletionString::CK_Comma);
6860 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006861 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006862
Douglas Gregor447107d2010-05-28 00:57:46 +00006863 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006864 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006865 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6866 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6867 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006868 if (!Method->getResultType()->isVoidType()) {
6869 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006870 Builder.AddTextChunk("return");
6871 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6872 Builder.AddPlaceholderChunk("expression");
6873 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006874 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006875 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006876
Douglas Gregor218937c2011-02-01 19:23:04 +00006877 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6878 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006879 }
6880
Douglas Gregor408be5a2010-08-25 01:08:01 +00006881 unsigned Priority = CCP_CodePattern;
6882 if (!M->second.second)
6883 Priority += CCD_InBaseClass;
6884
Douglas Gregorba103062012-03-27 23:34:16 +00006885 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006886 }
6887
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006888 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6889 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006890 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006891 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006892 Containers.push_back(SearchDecl);
6893
Douglas Gregore74c25c2011-05-04 23:50:46 +00006894 VisitedSelectorSet KnownSelectors;
6895 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6896 MEnd = KnownMethods.end();
6897 M != MEnd; ++M)
6898 KnownSelectors.insert(M->first);
6899
6900
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006901 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6902 if (!IFace)
6903 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6904 IFace = Category->getClassInterface();
6905
6906 if (IFace) {
6907 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6908 Category = Category->getNextClassCategory())
6909 Containers.push_back(Category);
6910 }
6911
6912 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6913 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6914 PEnd = Containers[I]->prop_end();
6915 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00006916 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006917 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006918 }
6919 }
6920 }
6921
Douglas Gregore8f5a172010-04-07 00:21:17 +00006922 Results.ExitScope();
6923
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006924 HandleCodeCompleteResults(this, CodeCompleter,
6925 CodeCompletionContext::CCC_Other,
6926 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006927}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006928
6929void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6930 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006931 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006932 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006933 IdentifierInfo **SelIdents,
6934 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006935 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006936 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006937 if (ExternalSource) {
6938 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6939 I != N; ++I) {
6940 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006941 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006942 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006943
6944 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006945 }
6946 }
6947
6948 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006949 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006950 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006951 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006952 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006953
6954 if (ReturnTy)
6955 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006956
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006957 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006958 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6959 MEnd = MethodPool.end();
6960 M != MEnd; ++M) {
6961 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6962 &M->second.second;
6963 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006964 MethList = MethList->Next) {
6965 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6966 NumSelIdents))
6967 continue;
6968
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006969 if (AtParameterName) {
6970 // Suggest parameter names we've seen before.
6971 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6972 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6973 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006974 CodeCompletionBuilder Builder(Results.getAllocator(),
6975 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00006976 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006977 Param->getIdentifier()->getName()));
6978 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006979 }
6980 }
6981
6982 continue;
6983 }
6984
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006985 Result R(MethList->Method, 0);
6986 R.StartParameter = NumSelIdents;
6987 R.AllParametersAreInformative = false;
6988 R.DeclaringEntity = true;
6989 Results.MaybeAddResult(R, CurContext);
6990 }
6991 }
6992
6993 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006994 HandleCodeCompleteResults(this, CodeCompleter,
6995 CodeCompletionContext::CCC_Other,
6996 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006997}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006998
Douglas Gregorf29c5232010-08-24 22:20:20 +00006999void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007000 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007001 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007002 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007003 Results.EnterNewScope();
7004
7005 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007006 CodeCompletionBuilder Builder(Results.getAllocator(),
7007 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007008 Builder.AddTypedTextChunk("if");
7009 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7010 Builder.AddPlaceholderChunk("condition");
7011 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007012
7013 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007014 Builder.AddTypedTextChunk("ifdef");
7015 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7016 Builder.AddPlaceholderChunk("macro");
7017 Results.AddResult(Builder.TakeString());
7018
Douglas Gregorf44e8542010-08-24 19:08:16 +00007019 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007020 Builder.AddTypedTextChunk("ifndef");
7021 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7022 Builder.AddPlaceholderChunk("macro");
7023 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007024
7025 if (InConditional) {
7026 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007027 Builder.AddTypedTextChunk("elif");
7028 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7029 Builder.AddPlaceholderChunk("condition");
7030 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007031
7032 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007033 Builder.AddTypedTextChunk("else");
7034 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007035
7036 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007037 Builder.AddTypedTextChunk("endif");
7038 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007039 }
7040
7041 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007042 Builder.AddTypedTextChunk("include");
7043 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7044 Builder.AddTextChunk("\"");
7045 Builder.AddPlaceholderChunk("header");
7046 Builder.AddTextChunk("\"");
7047 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007048
7049 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007050 Builder.AddTypedTextChunk("include");
7051 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7052 Builder.AddTextChunk("<");
7053 Builder.AddPlaceholderChunk("header");
7054 Builder.AddTextChunk(">");
7055 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007056
7057 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007058 Builder.AddTypedTextChunk("define");
7059 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7060 Builder.AddPlaceholderChunk("macro");
7061 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007062
7063 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007064 Builder.AddTypedTextChunk("define");
7065 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7066 Builder.AddPlaceholderChunk("macro");
7067 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7068 Builder.AddPlaceholderChunk("args");
7069 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7070 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007071
7072 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007073 Builder.AddTypedTextChunk("undef");
7074 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7075 Builder.AddPlaceholderChunk("macro");
7076 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007077
7078 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007079 Builder.AddTypedTextChunk("line");
7080 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7081 Builder.AddPlaceholderChunk("number");
7082 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007083
7084 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007085 Builder.AddTypedTextChunk("line");
7086 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7087 Builder.AddPlaceholderChunk("number");
7088 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7089 Builder.AddTextChunk("\"");
7090 Builder.AddPlaceholderChunk("filename");
7091 Builder.AddTextChunk("\"");
7092 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007093
7094 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007095 Builder.AddTypedTextChunk("error");
7096 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7097 Builder.AddPlaceholderChunk("message");
7098 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007099
7100 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007101 Builder.AddTypedTextChunk("pragma");
7102 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7103 Builder.AddPlaceholderChunk("arguments");
7104 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007105
David Blaikie4e4d0842012-03-11 07:00:24 +00007106 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007107 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007108 Builder.AddTypedTextChunk("import");
7109 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7110 Builder.AddTextChunk("\"");
7111 Builder.AddPlaceholderChunk("header");
7112 Builder.AddTextChunk("\"");
7113 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007114
7115 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007116 Builder.AddTypedTextChunk("import");
7117 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7118 Builder.AddTextChunk("<");
7119 Builder.AddPlaceholderChunk("header");
7120 Builder.AddTextChunk(">");
7121 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007122 }
7123
7124 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007125 Builder.AddTypedTextChunk("include_next");
7126 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7127 Builder.AddTextChunk("\"");
7128 Builder.AddPlaceholderChunk("header");
7129 Builder.AddTextChunk("\"");
7130 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007131
7132 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007133 Builder.AddTypedTextChunk("include_next");
7134 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7135 Builder.AddTextChunk("<");
7136 Builder.AddPlaceholderChunk("header");
7137 Builder.AddTextChunk(">");
7138 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007139
7140 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007141 Builder.AddTypedTextChunk("warning");
7142 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7143 Builder.AddPlaceholderChunk("message");
7144 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007145
7146 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7147 // completions for them. And __include_macros is a Clang-internal extension
7148 // that we don't want to encourage anyone to use.
7149
7150 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7151 Results.ExitScope();
7152
Douglas Gregorf44e8542010-08-24 19:08:16 +00007153 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007154 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007155 Results.data(), Results.size());
7156}
7157
7158void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007159 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007160 S->getFnParent()? Sema::PCC_RecoveryInFunction
7161 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007162}
7163
Douglas Gregorf29c5232010-08-24 22:20:20 +00007164void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007165 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007166 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007167 IsDefinition? CodeCompletionContext::CCC_MacroName
7168 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007169 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7170 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007171 CodeCompletionBuilder Builder(Results.getAllocator(),
7172 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007173 Results.EnterNewScope();
7174 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7175 MEnd = PP.macro_end();
7176 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007177 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007178 M->first->getName()));
7179 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007180 }
7181 Results.ExitScope();
7182 } else if (IsDefinition) {
7183 // FIXME: Can we detect when the user just wrote an include guard above?
7184 }
7185
Douglas Gregor52779fb2010-09-23 23:01:17 +00007186 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007187 Results.data(), Results.size());
7188}
7189
Douglas Gregorf29c5232010-08-24 22:20:20 +00007190void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007191 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007192 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007193 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007194
7195 if (!CodeCompleter || CodeCompleter->includeMacros())
7196 AddMacroResults(PP, Results);
7197
7198 // defined (<macro>)
7199 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007200 CodeCompletionBuilder Builder(Results.getAllocator(),
7201 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007202 Builder.AddTypedTextChunk("defined");
7203 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7204 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7205 Builder.AddPlaceholderChunk("macro");
7206 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7207 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007208 Results.ExitScope();
7209
7210 HandleCodeCompleteResults(this, CodeCompleter,
7211 CodeCompletionContext::CCC_PreprocessorExpression,
7212 Results.data(), Results.size());
7213}
7214
7215void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7216 IdentifierInfo *Macro,
7217 MacroInfo *MacroInfo,
7218 unsigned Argument) {
7219 // FIXME: In the future, we could provide "overload" results, much like we
7220 // do for function calls.
7221
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007222 // Now just ignore this. There will be another code-completion callback
7223 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007224}
7225
Douglas Gregor55817af2010-08-25 17:04:25 +00007226void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007227 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007228 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007229 0, 0);
7230}
7231
Douglas Gregordae68752011-02-01 22:57:45 +00007232void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007233 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007234 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007235 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7236 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007237 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7238 CodeCompletionDeclConsumer Consumer(Builder,
7239 Context.getTranslationUnitDecl());
7240 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7241 Consumer);
7242 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007243
7244 if (!CodeCompleter || CodeCompleter->includeMacros())
7245 AddMacroResults(PP, Builder);
7246
7247 Results.clear();
7248 Results.insert(Results.end(),
7249 Builder.data(), Builder.data() + Builder.size());
7250}