blob: ff83324de22595c05da385e416aa84218bb60ada [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;
2372 if (Proto->getTypeQuals() & Qualifiers::Const)
2373 QualsStr += " const";
2374 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2375 QualsStr += " volatile";
2376 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2377 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,
2456 CodeCompletionTUInfo &CCTUInfo) {
2457 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002458}
2459
Douglas Gregor86d9a522009-09-21 16:56:56 +00002460/// \brief If possible, create a new code completion string for the given
2461/// result.
2462///
2463/// \returns Either a new, heap-allocated code completion string describing
2464/// how to use this result, or NULL to indicate that the string or name of the
2465/// result is all that is needed.
2466CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002467CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2468 Preprocessor &PP,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002469 CodeCompletionAllocator &Allocator,
2470 CodeCompletionTUInfo &CCTUInfo) {
2471 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002472
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002473 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002474 if (Kind == RK_Pattern) {
2475 Pattern->Priority = Priority;
2476 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002477
2478 if (Declaration) {
2479 Result.addParentContext(Declaration->getDeclContext());
2480 Pattern->ParentKind = Result.getParentKind();
2481 Pattern->ParentName = Result.getParentName();
2482 }
2483
Douglas Gregor218937c2011-02-01 19:23:04 +00002484 return Pattern;
2485 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002486
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002487 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002488 Result.AddTypedTextChunk(Keyword);
2489 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002490 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002491
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002492 if (Kind == RK_Macro) {
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002493 MacroInfo *MI = PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002494 assert(MI && "Not a macro?");
2495
Douglas Gregordae68752011-02-01 22:57:45 +00002496 Result.AddTypedTextChunk(
2497 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002498
2499 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002500 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002501
2502 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002503 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002504 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002505
2506 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2507 if (MI->isC99Varargs()) {
2508 --AEnd;
2509
2510 if (A == AEnd) {
2511 Result.AddPlaceholderChunk("...");
2512 }
Douglas Gregore4244702011-07-30 08:17:44 +00002513 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002514
Douglas Gregore4244702011-07-30 08:17:44 +00002515 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002516 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002517 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002518
2519 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002520 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002521 if (MI->isC99Varargs())
2522 Arg += ", ...";
2523 else
2524 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002525 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002526 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002527 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002528
2529 // Non-variadic macros are simple.
2530 Result.AddPlaceholderChunk(
2531 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002532 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002533 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002534 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002535 }
2536
Douglas Gregord8e8a582010-05-25 21:41:55 +00002537 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002538 NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002539 Result.addParentContext(ND->getDeclContext());
2540
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002541 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002542 Result.AddTypedTextChunk(
2543 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002544 Result.AddTextChunk("::");
2545 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002546 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002547
2548 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2549 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2550 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2551 }
2552 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002553
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002554 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002555
Douglas Gregor86d9a522009-09-21 16:56:56 +00002556 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002557 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002558 Ctx, Policy);
2559 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002560 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002561 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002562 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002563 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002564 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002565 }
2566
2567 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002568 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002569 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002570 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002571 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002572
Douglas Gregor86d9a522009-09-21 16:56:56 +00002573 // Figure out which template parameters are deduced (or have default
2574 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002575 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002576 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002577 unsigned LastDeducibleArgument;
2578 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2579 --LastDeducibleArgument) {
2580 if (!Deduced[LastDeducibleArgument - 1]) {
2581 // C++0x: Figure out if the template argument has a default. If so,
2582 // the user doesn't need to type this argument.
2583 // FIXME: We need to abstract template parameters better!
2584 bool HasDefaultArg = false;
2585 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002586 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002587 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2588 HasDefaultArg = TTP->hasDefaultArgument();
2589 else if (NonTypeTemplateParmDecl *NTTP
2590 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2591 HasDefaultArg = NTTP->hasDefaultArgument();
2592 else {
2593 assert(isa<TemplateTemplateParmDecl>(Param));
2594 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002595 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002596 }
2597
2598 if (!HasDefaultArg)
2599 break;
2600 }
2601 }
2602
2603 if (LastDeducibleArgument) {
2604 // Some of the function template arguments cannot be deduced from a
2605 // function call, so we introduce an explicit template argument list
2606 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002607 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002608 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002609 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002610 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002611 }
2612
2613 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002614 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002615 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002616 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002617 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002618 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002619 }
2620
2621 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002622 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002623 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002624 Result.AddTypedTextChunk(
2625 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002626 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002627 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002628 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002629 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002630 }
2631
Douglas Gregor9630eb62009-11-17 16:44:22 +00002632 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002633 Selector Sel = Method->getSelector();
2634 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002635 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002636 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002637 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002638 }
2639
Douglas Gregor813d8342011-02-18 22:29:55 +00002640 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002641 SelName += ':';
2642 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002643 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002644 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002645 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002646
2647 // If there is only one parameter, and we're past it, add an empty
2648 // typed-text chunk since there is nothing to type.
2649 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002650 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002651 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002652 unsigned Idx = 0;
2653 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2654 PEnd = Method->param_end();
2655 P != PEnd; (void)++P, ++Idx) {
2656 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002657 std::string Keyword;
2658 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002659 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002660 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002661 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002662 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002663 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002664 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002665 else
Douglas Gregordae68752011-02-01 22:57:45 +00002666 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002667 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002668
2669 // If we're before the starting parameter, skip the placeholder.
2670 if (Idx < StartParameter)
2671 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002672
2673 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002674
2675 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002676 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002677 else {
John McCallf85e1932011-06-15 23:02:42 +00002678 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002679 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2680 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002681 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002682 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002683 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002684 }
2685
Douglas Gregore17794f2010-08-31 05:13:43 +00002686 if (Method->isVariadic() && (P + 1) == PEnd)
2687 Arg += ", ...";
2688
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002689 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002690 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002691 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002692 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002693 else
Douglas Gregordae68752011-02-01 22:57:45 +00002694 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002695 }
2696
Douglas Gregor2a17af02009-12-23 00:21:46 +00002697 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002698 if (Method->param_size() == 0) {
2699 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002700 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002701 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002702 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002703 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002704 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002705 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002706
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002707 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002708 }
2709
Douglas Gregor218937c2011-02-01 19:23:04 +00002710 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002711 }
2712
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002713 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002714 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002715 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002716
Douglas Gregordae68752011-02-01 22:57:45 +00002717 Result.AddTypedTextChunk(
2718 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002719 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002720}
2721
Douglas Gregor86d802e2009-09-23 00:34:09 +00002722CodeCompletionString *
2723CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2724 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002725 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002726 CodeCompletionAllocator &Allocator,
2727 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002728 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002729
Douglas Gregor218937c2011-02-01 19:23:04 +00002730 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002731 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002732 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002733 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002734 const FunctionProtoType *Proto
2735 = dyn_cast<FunctionProtoType>(getFunctionType());
2736 if (!FDecl && !Proto) {
2737 // Function without a prototype. Just give the return type and a
2738 // highlighted ellipsis.
2739 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002740 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002741 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002742 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002743 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2744 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2745 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002746 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002747 }
2748
2749 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002750 Result.AddTextChunk(
2751 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002752 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002753 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002754 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002755 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002756
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002757 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002758 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2759 for (unsigned I = 0; I != NumParams; ++I) {
2760 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002761 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002762
2763 std::string ArgString;
2764 QualType ArgType;
2765
2766 if (FDecl) {
2767 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2768 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2769 } else {
2770 ArgType = Proto->getArgType(I);
2771 }
2772
John McCallf85e1932011-06-15 23:02:42 +00002773 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002774
2775 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002776 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2777 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002778 else
Douglas Gregordae68752011-02-01 22:57:45 +00002779 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002780 }
2781
2782 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002783 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002784 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002785 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002786 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002787 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002788 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002789 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002790
Douglas Gregor218937c2011-02-01 19:23:04 +00002791 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002792}
2793
Chris Lattner5f9e2722011-07-23 10:55:15 +00002794unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002795 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002796 bool PreferredTypeIsPointer) {
2797 unsigned Priority = CCP_Macro;
2798
Douglas Gregorb05496d2010-09-20 21:11:48 +00002799 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2800 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2801 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002802 Priority = CCP_Constant;
2803 if (PreferredTypeIsPointer)
2804 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002805 }
2806 // Treat "YES", "NO", "true", and "false" as constants.
2807 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2808 MacroName.equals("true") || MacroName.equals("false"))
2809 Priority = CCP_Constant;
2810 // Treat "bool" as a type.
2811 else if (MacroName.equals("bool"))
2812 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2813
Douglas Gregor1827e102010-08-16 16:18:59 +00002814
2815 return Priority;
2816}
2817
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002818CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2819 if (!D)
2820 return CXCursor_UnexposedDecl;
2821
2822 switch (D->getKind()) {
2823 case Decl::Enum: return CXCursor_EnumDecl;
2824 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2825 case Decl::Field: return CXCursor_FieldDecl;
2826 case Decl::Function:
2827 return CXCursor_FunctionDecl;
2828 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2829 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002830 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002831
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002832 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002833 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2834 case Decl::ObjCMethod:
2835 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2836 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2837 case Decl::CXXMethod: return CXCursor_CXXMethod;
2838 case Decl::CXXConstructor: return CXCursor_Constructor;
2839 case Decl::CXXDestructor: return CXCursor_Destructor;
2840 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2841 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002842 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002843 case Decl::ParmVar: return CXCursor_ParmDecl;
2844 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002845 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002846 case Decl::Var: return CXCursor_VarDecl;
2847 case Decl::Namespace: return CXCursor_Namespace;
2848 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2849 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2850 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2851 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2852 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2853 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002854 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002855 case Decl::ClassTemplatePartialSpecialization:
2856 return CXCursor_ClassTemplatePartialSpecialization;
2857 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor8e5900c2012-04-30 23:41:16 +00002858 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002859
2860 case Decl::Using:
2861 case Decl::UnresolvedUsingValue:
2862 case Decl::UnresolvedUsingTypename:
2863 return CXCursor_UsingDeclaration;
2864
Douglas Gregor352697a2011-06-03 23:08:58 +00002865 case Decl::ObjCPropertyImpl:
2866 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2867 case ObjCPropertyImplDecl::Dynamic:
2868 return CXCursor_ObjCDynamicDecl;
2869
2870 case ObjCPropertyImplDecl::Synthesize:
2871 return CXCursor_ObjCSynthesizeDecl;
2872 }
Douglas Gregor352697a2011-06-03 23:08:58 +00002873
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002874 default:
2875 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2876 switch (TD->getTagKind()) {
2877 case TTK_Struct: return CXCursor_StructDecl;
2878 case TTK_Class: return CXCursor_ClassDecl;
2879 case TTK_Union: return CXCursor_UnionDecl;
2880 case TTK_Enum: return CXCursor_EnumDecl;
2881 }
2882 }
2883 }
2884
2885 return CXCursor_UnexposedDecl;
2886}
2887
Douglas Gregor590c7d52010-07-08 20:55:51 +00002888static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2889 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002890 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002891
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002892 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002893
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002894 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2895 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002896 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002897 Results.AddResult(Result(M->first,
2898 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002899 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002900 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002901 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002902
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002903 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002904
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002905}
2906
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002907static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2908 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002909 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002910
2911 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002912
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002913 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2914 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2915 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2916 Results.AddResult(Result("__func__", CCP_Constant));
2917 Results.ExitScope();
2918}
2919
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002920static void HandleCodeCompleteResults(Sema *S,
2921 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002922 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002923 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002924 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002925 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002926 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002927}
2928
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002929static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2930 Sema::ParserCompletionContext PCC) {
2931 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002932 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002933 return CodeCompletionContext::CCC_TopLevel;
2934
John McCallf312b1e2010-08-26 23:41:50 +00002935 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002936 return CodeCompletionContext::CCC_ClassStructUnion;
2937
John McCallf312b1e2010-08-26 23:41:50 +00002938 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002939 return CodeCompletionContext::CCC_ObjCInterface;
2940
John McCallf312b1e2010-08-26 23:41:50 +00002941 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002942 return CodeCompletionContext::CCC_ObjCImplementation;
2943
John McCallf312b1e2010-08-26 23:41:50 +00002944 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002945 return CodeCompletionContext::CCC_ObjCIvarList;
2946
John McCallf312b1e2010-08-26 23:41:50 +00002947 case Sema::PCC_Template:
2948 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002949 if (S.CurContext->isFileContext())
2950 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002951 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002952 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002953 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002954
John McCallf312b1e2010-08-26 23:41:50 +00002955 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002956 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002957
John McCallf312b1e2010-08-26 23:41:50 +00002958 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002959 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2960 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002961 return CodeCompletionContext::CCC_ParenthesizedExpression;
2962 else
2963 return CodeCompletionContext::CCC_Expression;
2964
2965 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002966 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002967 return CodeCompletionContext::CCC_Expression;
2968
John McCallf312b1e2010-08-26 23:41:50 +00002969 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002970 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002971
John McCallf312b1e2010-08-26 23:41:50 +00002972 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002973 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002974
2975 case Sema::PCC_ParenthesizedExpression:
2976 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002977
2978 case Sema::PCC_LocalDeclarationSpecifiers:
2979 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002980 }
David Blaikie7530c032012-01-17 06:56:22 +00002981
2982 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002983}
2984
Douglas Gregorf6961522010-08-27 21:18:54 +00002985/// \brief If we're in a C++ virtual member function, add completion results
2986/// that invoke the functions we override, since it's common to invoke the
2987/// overridden function as well as adding new functionality.
2988///
2989/// \param S The semantic analysis object for which we are generating results.
2990///
2991/// \param InContext This context in which the nested-name-specifier preceding
2992/// the code-completion point
2993static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2994 ResultBuilder &Results) {
2995 // Look through blocks.
2996 DeclContext *CurContext = S.CurContext;
2997 while (isa<BlockDecl>(CurContext))
2998 CurContext = CurContext->getParent();
2999
3000
3001 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3002 if (!Method || !Method->isVirtual())
3003 return;
3004
3005 // We need to have names for all of the parameters, if we're going to
3006 // generate a forwarding call.
3007 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3008 PEnd = Method->param_end();
3009 P != PEnd;
3010 ++P) {
3011 if (!(*P)->getDeclName())
3012 return;
3013 }
3014
Douglas Gregor8987b232011-09-27 23:30:47 +00003015 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00003016 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3017 MEnd = Method->end_overridden_methods();
3018 M != MEnd; ++M) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003019 CodeCompletionBuilder Builder(Results.getAllocator(),
3020 Results.getCodeCompletionTUInfo());
Douglas Gregorf6961522010-08-27 21:18:54 +00003021 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3022 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3023 continue;
3024
3025 // If we need a nested-name-specifier, add one now.
3026 if (!InContext) {
3027 NestedNameSpecifier *NNS
3028 = getRequiredQualification(S.Context, CurContext,
3029 Overridden->getDeclContext());
3030 if (NNS) {
3031 std::string Str;
3032 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003033 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003034 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003035 }
3036 } else if (!InContext->Equals(Overridden->getDeclContext()))
3037 continue;
3038
Douglas Gregordae68752011-02-01 22:57:45 +00003039 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003040 Overridden->getNameAsString()));
3041 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003042 bool FirstParam = true;
3043 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3044 PEnd = Method->param_end();
3045 P != PEnd; ++P) {
3046 if (FirstParam)
3047 FirstParam = false;
3048 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003049 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003050
Douglas Gregordae68752011-02-01 22:57:45 +00003051 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003052 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003053 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003054 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3055 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003056 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003057 CXCursor_CXXMethod,
3058 CXAvailability_Available,
3059 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003060 Results.Ignore(Overridden);
3061 }
3062}
3063
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003064void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3065 ModuleIdPath Path) {
3066 typedef CodeCompletionResult Result;
3067 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003068 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003069 CodeCompletionContext::CCC_Other);
3070 Results.EnterNewScope();
3071
3072 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003073 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003074 typedef CodeCompletionResult Result;
3075 if (Path.empty()) {
3076 // Enumerate all top-level modules.
3077 llvm::SmallVector<Module *, 8> Modules;
3078 PP.getHeaderSearchInfo().collectAllModules(Modules);
3079 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3080 Builder.AddTypedTextChunk(
3081 Builder.getAllocator().CopyString(Modules[I]->Name));
3082 Results.AddResult(Result(Builder.TakeString(),
3083 CCP_Declaration,
3084 CXCursor_NotImplemented,
3085 Modules[I]->isAvailable()
3086 ? CXAvailability_Available
3087 : CXAvailability_NotAvailable));
3088 }
3089 } else {
3090 // Load the named module.
3091 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3092 Module::AllVisible,
3093 /*IsInclusionDirective=*/false);
3094 // Enumerate submodules.
3095 if (Mod) {
3096 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3097 SubEnd = Mod->submodule_end();
3098 Sub != SubEnd; ++Sub) {
3099
3100 Builder.AddTypedTextChunk(
3101 Builder.getAllocator().CopyString((*Sub)->Name));
3102 Results.AddResult(Result(Builder.TakeString(),
3103 CCP_Declaration,
3104 CXCursor_NotImplemented,
3105 (*Sub)->isAvailable()
3106 ? CXAvailability_Available
3107 : CXAvailability_NotAvailable));
3108 }
3109 }
3110 }
3111 Results.ExitScope();
3112 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3113 Results.data(),Results.size());
3114}
3115
Douglas Gregor01dfea02010-01-10 23:08:15 +00003116void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003117 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00003118 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003119 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003120 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003121 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003122 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003123
Douglas Gregor01dfea02010-01-10 23:08:15 +00003124 // Determine how to filter results, e.g., so that the names of
3125 // values (functions, enumerators, function templates, etc.) are
3126 // only allowed where we can have an expression.
3127 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003128 case PCC_Namespace:
3129 case PCC_Class:
3130 case PCC_ObjCInterface:
3131 case PCC_ObjCImplementation:
3132 case PCC_ObjCInstanceVariableList:
3133 case PCC_Template:
3134 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003135 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003136 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003137 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3138 break;
3139
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003140 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003141 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003142 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003143 case PCC_ForInit:
3144 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003145 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003146 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3147 else
3148 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003149
David Blaikie4e4d0842012-03-11 07:00:24 +00003150 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003151 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003152 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003153
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003154 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003155 // Unfiltered
3156 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003157 }
3158
Douglas Gregor3cdee122010-08-26 16:36:48 +00003159 // If we are in a C++ non-static member function, check the qualifiers on
3160 // the member function to filter/prioritize the results list.
3161 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3162 if (CurMethod->isInstance())
3163 Results.setObjectTypeQualifiers(
3164 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3165
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003166 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003167 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3168 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003169
Douglas Gregorbca403c2010-01-13 23:51:12 +00003170 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003171 Results.ExitScope();
3172
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003173 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003174 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003175 case PCC_Expression:
3176 case PCC_Statement:
3177 case PCC_RecoveryInFunction:
3178 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003179 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003180 break;
3181
3182 case PCC_Namespace:
3183 case PCC_Class:
3184 case PCC_ObjCInterface:
3185 case PCC_ObjCImplementation:
3186 case PCC_ObjCInstanceVariableList:
3187 case PCC_Template:
3188 case PCC_MemberTemplate:
3189 case PCC_ForInit:
3190 case PCC_Condition:
3191 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003192 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003193 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003194 }
3195
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003196 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003197 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003198
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003199 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003200 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003201}
3202
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003203static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3204 ParsedType Receiver,
3205 IdentifierInfo **SelIdents,
3206 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003207 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003208 bool IsSuper,
3209 ResultBuilder &Results);
3210
3211void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3212 bool AllowNonIdentifiers,
3213 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003214 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003215 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003216 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003217 AllowNestedNameSpecifiers
3218 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3219 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003220 Results.EnterNewScope();
3221
3222 // Type qualifiers can come after names.
3223 Results.AddResult(Result("const"));
3224 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003225 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003226 Results.AddResult(Result("restrict"));
3227
David Blaikie4e4d0842012-03-11 07:00:24 +00003228 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003229 if (AllowNonIdentifiers) {
3230 Results.AddResult(Result("operator"));
3231 }
3232
3233 // Add nested-name-specifiers.
3234 if (AllowNestedNameSpecifiers) {
3235 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003236 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003237 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3238 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3239 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003240 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003241 }
3242 }
3243 Results.ExitScope();
3244
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003245 // If we're in a context where we might have an expression (rather than a
3246 // declaration), and what we've seen so far is an Objective-C type that could
3247 // be a receiver of a class message, this may be a class message send with
3248 // the initial opening bracket '[' missing. Add appropriate completions.
3249 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3250 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3251 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3252 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3253 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3254 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3255 DS.getTypeQualifiers() == 0 &&
3256 S &&
3257 (S->getFlags() & Scope::DeclScope) != 0 &&
3258 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3259 Scope::FunctionPrototypeScope |
3260 Scope::AtCatchScope)) == 0) {
3261 ParsedType T = DS.getRepAsType();
3262 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003263 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003264 }
3265
Douglas Gregor4497dd42010-08-24 04:59:56 +00003266 // Note that we intentionally suppress macro results here, since we do not
3267 // encourage using macros to produce the names of entities.
3268
Douglas Gregor52779fb2010-09-23 23:01:17 +00003269 HandleCodeCompleteResults(this, CodeCompleter,
3270 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003271 Results.data(), Results.size());
3272}
3273
Douglas Gregorfb629412010-08-23 21:17:50 +00003274struct Sema::CodeCompleteExpressionData {
3275 CodeCompleteExpressionData(QualType PreferredType = QualType())
3276 : PreferredType(PreferredType), IntegralConstantExpression(false),
3277 ObjCCollection(false) { }
3278
3279 QualType PreferredType;
3280 bool IntegralConstantExpression;
3281 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003282 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003283};
3284
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003285/// \brief Perform code-completion in an expression context when we know what
3286/// type we're looking for.
Douglas Gregorfb629412010-08-23 21:17:50 +00003287void Sema::CodeCompleteExpression(Scope *S,
3288 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00003289 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003290 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003291 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003292 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003293 if (Data.ObjCCollection)
3294 Results.setFilter(&ResultBuilder::IsObjCCollection);
3295 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003296 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003297 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003298 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3299 else
3300 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003301
3302 if (!Data.PreferredType.isNull())
3303 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3304
3305 // Ignore any declarations that we were told that we don't care about.
3306 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3307 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003308
3309 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003310 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3311 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003312
3313 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003314 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003315 Results.ExitScope();
3316
Douglas Gregor590c7d52010-07-08 20:55:51 +00003317 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003318 if (!Data.PreferredType.isNull())
3319 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3320 || Data.PreferredType->isMemberPointerType()
3321 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003322
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003323 if (S->getFnParent() &&
3324 !Data.ObjCCollection &&
3325 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003326 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003327
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003328 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003329 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003330 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003331 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3332 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003333 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003334}
3335
Douglas Gregorac5fd842010-09-18 01:28:11 +00003336void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3337 if (E.isInvalid())
3338 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003339 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003340 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003341}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003342
Douglas Gregor73449212010-12-09 23:01:55 +00003343/// \brief The set of properties that have already been added, referenced by
3344/// property name.
3345typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3346
Douglas Gregorb92a4082012-06-12 13:44:08 +00003347/// \brief Retrieve the container definition, if any?
3348static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3349 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3350 if (Interface->hasDefinition())
3351 return Interface->getDefinition();
3352
3353 return Interface;
3354 }
3355
3356 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3357 if (Protocol->hasDefinition())
3358 return Protocol->getDefinition();
3359
3360 return Protocol;
3361 }
3362 return Container;
3363}
3364
3365static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003366 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003367 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003368 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003369 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003370 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003371 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003372
Douglas Gregorb92a4082012-06-12 13:44:08 +00003373 // Retrieve the definition.
3374 Container = getContainerDef(Container);
3375
Douglas Gregor95ac6552009-11-18 01:29:26 +00003376 // Add properties in this container.
3377 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3378 PEnd = Container->prop_end();
3379 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003380 ++P) {
3381 if (AddedProperties.insert(P->getIdentifier()))
David Blaikie581deb32012-06-06 20:45:41 +00003382 Results.MaybeAddResult(Result(*P, 0), CurContext);
Douglas Gregor73449212010-12-09 23:01:55 +00003383 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003384
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003385 // Add nullary methods
3386 if (AllowNullaryMethods) {
3387 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003388 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003389 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3390 MEnd = Container->meth_end();
3391 M != MEnd; ++M) {
3392 if (M->getSelector().isUnarySelector())
3393 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3394 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003395 CodeCompletionBuilder Builder(Results.getAllocator(),
3396 Results.getCodeCompletionTUInfo());
David Blaikie581deb32012-06-06 20:45:41 +00003397 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003398 Builder.AddTypedTextChunk(
3399 Results.getAllocator().CopyString(Name->getName()));
3400
David Blaikie581deb32012-06-06 20:45:41 +00003401 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregorba103062012-03-27 23:34:16 +00003402 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003403 CurContext);
3404 }
3405 }
3406 }
3407
3408
Douglas Gregor95ac6552009-11-18 01:29:26 +00003409 // Add properties in referenced protocols.
3410 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3411 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3412 PEnd = Protocol->protocol_end();
3413 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003414 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3415 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003416 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003417 if (AllowCategories) {
3418 // Look through categories.
3419 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3420 Category; Category = Category->getNextClassCategory())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003421 AddObjCProperties(Category, AllowCategories, AllowNullaryMethods,
3422 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003423 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003424
3425 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003426 for (ObjCInterfaceDecl::all_protocol_iterator
3427 I = IFace->all_referenced_protocol_begin(),
3428 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003429 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3430 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003431
3432 // Look in the superclass.
3433 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003434 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3435 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003436 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003437 } else if (const ObjCCategoryDecl *Category
3438 = dyn_cast<ObjCCategoryDecl>(Container)) {
3439 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003440 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3441 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003442 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003443 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3444 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003445 }
3446}
3447
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003448void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003449 SourceLocation OpLoc,
3450 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003451 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003452 return;
3453
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003454 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3455 if (ConvertedBase.isInvalid())
3456 return;
3457 Base = ConvertedBase.get();
3458
John McCall0a2c5e22010-08-25 06:19:51 +00003459 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003460
Douglas Gregor81b747b2009-09-17 21:32:03 +00003461 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003462
3463 if (IsArrow) {
3464 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3465 BaseType = Ptr->getPointeeType();
3466 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003467 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003468 else
3469 return;
3470 }
3471
Douglas Gregor3da626b2011-07-07 16:03:39 +00003472 enum CodeCompletionContext::Kind contextKind;
3473
3474 if (IsArrow) {
3475 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3476 }
3477 else {
3478 if (BaseType->isObjCObjectPointerType() ||
3479 BaseType->isObjCObjectOrInterfaceType()) {
3480 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3481 }
3482 else {
3483 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3484 }
3485 }
3486
Douglas Gregor218937c2011-02-01 19:23:04 +00003487 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003488 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003489 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003490 BaseType),
3491 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003492 Results.EnterNewScope();
3493 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003494 // Indicate that we are performing a member access, and the cv-qualifiers
3495 // for the base object type.
3496 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3497
Douglas Gregor95ac6552009-11-18 01:29:26 +00003498 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003499 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003500 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003501 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3502 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003503
David Blaikie4e4d0842012-03-11 07:00:24 +00003504 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003505 if (!Results.empty()) {
3506 // The "template" keyword can follow "->" or "." in the grammar.
3507 // However, we only want to suggest the template keyword if something
3508 // is dependent.
3509 bool IsDependent = BaseType->isDependentType();
3510 if (!IsDependent) {
3511 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3512 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3513 IsDependent = Ctx->isDependentContext();
3514 break;
3515 }
3516 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003517
Douglas Gregor95ac6552009-11-18 01:29:26 +00003518 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003519 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003520 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003521 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003522 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3523 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003524 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003525
3526 // Add property results based on our interface.
3527 const ObjCObjectPointerType *ObjCPtr
3528 = BaseType->getAsObjCInterfacePointerType();
3529 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003530 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3531 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003532 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003533
3534 // Add properties from the protocols in a qualified interface.
3535 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3536 E = ObjCPtr->qual_end();
3537 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003538 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3539 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003540 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003541 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003542 // Objective-C instance variable access.
3543 ObjCInterfaceDecl *Class = 0;
3544 if (const ObjCObjectPointerType *ObjCPtr
3545 = BaseType->getAs<ObjCObjectPointerType>())
3546 Class = ObjCPtr->getInterfaceDecl();
3547 else
John McCallc12c5bb2010-05-15 11:32:37 +00003548 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003549
3550 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003551 if (Class) {
3552 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3553 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003554 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3555 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003556 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003557 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003558
3559 // FIXME: How do we cope with isa?
3560
3561 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003562
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003563 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003564 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003565 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003566 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003567}
3568
Douglas Gregor374929f2009-09-18 15:37:17 +00003569void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3570 if (!CodeCompleter)
3571 return;
3572
John McCall0a2c5e22010-08-25 06:19:51 +00003573 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003574 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003575 enum CodeCompletionContext::Kind ContextKind
3576 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003577 switch ((DeclSpec::TST)TagSpec) {
3578 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003579 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003580 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003581 break;
3582
3583 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003584 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003585 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003586 break;
3587
3588 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003589 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003590 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003591 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003592 break;
3593
3594 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003595 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003596 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003597
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003598 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3599 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003600 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003601
3602 // First pass: look for tags.
3603 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003604 LookupVisibleDecls(S, LookupTagName, Consumer,
3605 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003606
Douglas Gregor8071e422010-08-15 06:18:01 +00003607 if (CodeCompleter->includeGlobals()) {
3608 // Second pass: look for nested name specifiers.
3609 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3610 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3611 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003612
Douglas Gregor52779fb2010-09-23 23:01:17 +00003613 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003614 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003615}
3616
Douglas Gregor1a480c42010-08-27 17:35:51 +00003617void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003618 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003619 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003620 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003621 Results.EnterNewScope();
3622 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3623 Results.AddResult("const");
3624 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3625 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003626 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003627 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3628 Results.AddResult("restrict");
3629 Results.ExitScope();
3630 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003631 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003632 Results.data(), Results.size());
3633}
3634
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003635void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003636 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003637 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003638
John McCall781472f2010-08-25 08:40:02 +00003639 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003640 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3641 if (!type->isEnumeralType()) {
3642 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003643 Data.IntegralConstantExpression = true;
3644 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003645 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003646 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003647
3648 // Code-complete the cases of a switch statement over an enumeration type
3649 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003650 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003651 if (EnumDecl *Def = Enum->getDefinition())
3652 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003653
3654 // Determine which enumerators we have already seen in the switch statement.
3655 // FIXME: Ideally, we would also be able to look *past* the code-completion
3656 // token, in case we are code-completing in the middle of the switch and not
3657 // at the end. However, we aren't able to do so at the moment.
3658 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003659 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003660 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3661 SC = SC->getNextSwitchCase()) {
3662 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3663 if (!Case)
3664 continue;
3665
3666 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3667 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3668 if (EnumConstantDecl *Enumerator
3669 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3670 // We look into the AST of the case statement to determine which
3671 // enumerator was named. Alternatively, we could compute the value of
3672 // the integral constant expression, then compare it against the
3673 // values of each enumerator. However, value-based approach would not
3674 // work as well with C++ templates where enumerators declared within a
3675 // template are type- and value-dependent.
3676 EnumeratorsSeen.insert(Enumerator);
3677
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003678 // If this is a qualified-id, keep track of the nested-name-specifier
3679 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003680 //
3681 // switch (TagD.getKind()) {
3682 // case TagDecl::TK_enum:
3683 // break;
3684 // case XXX
3685 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003686 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003687 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3688 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003689 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003690 }
3691 }
3692
David Blaikie4e4d0842012-03-11 07:00:24 +00003693 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003694 // If there are no prior enumerators in C++, check whether we have to
3695 // qualify the names of the enumerators that we suggest, because they
3696 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003697 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003698 }
3699
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003700 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003701 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003702 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003703 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003704 Results.EnterNewScope();
3705 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3706 EEnd = Enum->enumerator_end();
3707 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003708 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003709 continue;
3710
David Blaikie581deb32012-06-06 20:45:41 +00003711 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003712 R.Priority = CCP_EnumInCase;
3713 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003714 }
3715 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003716
Douglas Gregor3da626b2011-07-07 16:03:39 +00003717 //We need to make sure we're setting the right context,
3718 //so only say we include macros if the code completer says we do
3719 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3720 if (CodeCompleter->includeMacros()) {
Douglas Gregorbca403c2010-01-13 23:51:12 +00003721 AddMacroResults(PP, Results);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003722 kind = CodeCompletionContext::CCC_OtherWithMacros;
3723 }
3724
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003725 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003726 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003727 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003728}
3729
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003730namespace {
3731 struct IsBetterOverloadCandidate {
3732 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003733 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003734
3735 public:
John McCall5769d612010-02-08 23:07:23 +00003736 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3737 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003738
3739 bool
3740 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003741 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003742 }
3743 };
3744}
3745
Ahmed Charles13a140c2012-02-25 11:00:22 +00003746static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3747 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003748 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003749
3750 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003751 if (!Args[I])
3752 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003753
Douglas Gregord28dcd72010-05-30 06:10:08 +00003754 return false;
3755}
3756
Richard Trieuf81e5a92011-09-09 02:00:50 +00003757void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003758 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003759 if (!CodeCompleter)
3760 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003761
3762 // When we're code-completing for a call, we fall back to ordinary
3763 // name code-completion whenever we can't produce specific
3764 // results. We may want to revisit this strategy in the future,
3765 // e.g., by merging the two kinds of results.
3766
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003767 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003768
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003769 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003770 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3771 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003772 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003773 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003774 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003775
John McCall3b4294e2009-12-16 12:17:52 +00003776 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003777 SourceLocation Loc = Fn->getExprLoc();
3778 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003779
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003780 // FIXME: What if we're calling something that isn't a function declaration?
3781 // FIXME: What if we're calling a pseudo-destructor?
3782 // FIXME: What if we're calling a member function?
3783
Douglas Gregorc0265402010-01-21 15:46:19 +00003784 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003785 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003786
John McCall3b4294e2009-12-16 12:17:52 +00003787 Expr *NakedFn = Fn->IgnoreParenCasts();
3788 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003789 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003790 /*PartialOverloading=*/ true);
3791 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3792 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003793 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003794 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003795 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003796 Results.push_back(ResultCandidate(FDecl));
3797 else
John McCall86820f52010-01-26 01:37:31 +00003798 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003799 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3800 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003801 }
John McCall3b4294e2009-12-16 12:17:52 +00003802 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003803
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003804 QualType ParamType;
3805
Douglas Gregorc0265402010-01-21 15:46:19 +00003806 if (!CandidateSet.empty()) {
3807 // Sort the overload candidate set by placing the best overloads first.
3808 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003809 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003810
Douglas Gregorc0265402010-01-21 15:46:19 +00003811 // Add the remaining viable overload candidates as code-completion reslults.
3812 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3813 CandEnd = CandidateSet.end();
3814 Cand != CandEnd; ++Cand) {
3815 if (Cand->Viable)
3816 Results.push_back(ResultCandidate(Cand->Function));
3817 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003818
3819 // From the viable candidates, try to determine the type of this parameter.
3820 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3821 if (const FunctionType *FType = Results[I].getFunctionType())
3822 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003823 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003824 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003825 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003826 else if (!Context.hasSameUnqualifiedType(
3827 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003828 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003829 ParamType = QualType();
3830 break;
3831 }
3832 }
3833 }
3834 } else {
3835 // Try to determine the parameter type from the type of the expression
3836 // being called.
3837 QualType FunctionType = Fn->getType();
3838 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3839 FunctionType = Ptr->getPointeeType();
3840 else if (const BlockPointerType *BlockPtr
3841 = FunctionType->getAs<BlockPointerType>())
3842 FunctionType = BlockPtr->getPointeeType();
3843 else if (const MemberPointerType *MemPtr
3844 = FunctionType->getAs<MemberPointerType>())
3845 FunctionType = MemPtr->getPointeeType();
3846
3847 if (const FunctionProtoType *Proto
3848 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003849 if (Args.size() < Proto->getNumArgs())
3850 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003851 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003852 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003853
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003854 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003855 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003856 else
3857 CodeCompleteExpression(S, ParamType);
3858
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003859 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003860 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003861 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003862}
3863
John McCalld226f652010-08-21 09:40:31 +00003864void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3865 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003866 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003867 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003868 return;
3869 }
3870
3871 CodeCompleteExpression(S, VD->getType());
3872}
3873
3874void Sema::CodeCompleteReturn(Scope *S) {
3875 QualType ResultType;
3876 if (isa<BlockDecl>(CurContext)) {
3877 if (BlockScopeInfo *BSI = getCurBlock())
3878 ResultType = BSI->ReturnType;
3879 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3880 ResultType = Function->getResultType();
3881 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3882 ResultType = Method->getResultType();
3883
3884 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003885 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003886 else
3887 CodeCompleteExpression(S, ResultType);
3888}
3889
Douglas Gregord2d8be62011-07-30 08:36:53 +00003890void Sema::CodeCompleteAfterIf(Scope *S) {
3891 typedef CodeCompletionResult Result;
3892 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003893 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003894 mapCodeCompletionContext(*this, PCC_Statement));
3895 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3896 Results.EnterNewScope();
3897
3898 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3899 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3900 CodeCompleter->includeGlobals());
3901
3902 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3903
3904 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003905 CodeCompletionBuilder Builder(Results.getAllocator(),
3906 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003907 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003908 if (Results.includeCodePatterns()) {
3909 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3910 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3911 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3912 Builder.AddPlaceholderChunk("statements");
3913 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3914 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3915 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003916 Results.AddResult(Builder.TakeString());
3917
3918 // "else if" block
3919 Builder.AddTypedTextChunk("else");
3920 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3921 Builder.AddTextChunk("if");
3922 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3923 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003924 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003925 Builder.AddPlaceholderChunk("condition");
3926 else
3927 Builder.AddPlaceholderChunk("expression");
3928 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003929 if (Results.includeCodePatterns()) {
3930 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3931 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3932 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3933 Builder.AddPlaceholderChunk("statements");
3934 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3935 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3936 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003937 Results.AddResult(Builder.TakeString());
3938
3939 Results.ExitScope();
3940
3941 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003942 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003943
3944 if (CodeCompleter->includeMacros())
3945 AddMacroResults(PP, Results);
3946
3947 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3948 Results.data(),Results.size());
3949}
3950
Richard Trieuf81e5a92011-09-09 02:00:50 +00003951void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003952 if (LHS)
3953 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3954 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003955 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003956}
3957
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003958void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003959 bool EnteringContext) {
3960 if (!SS.getScopeRep() || !CodeCompleter)
3961 return;
3962
Douglas Gregor86d9a522009-09-21 16:56:56 +00003963 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3964 if (!Ctx)
3965 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003966
3967 // Try to instantiate any non-dependent declaration contexts before
3968 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003969 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003970 return;
3971
Douglas Gregor218937c2011-02-01 19:23:04 +00003972 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003973 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003974 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003975 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003976
Douglas Gregor86d9a522009-09-21 16:56:56 +00003977 // The "template" keyword can follow "::" in the grammar, but only
3978 // put it into the grammar if the nested-name-specifier is dependent.
3979 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3980 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003981 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003982
3983 // Add calls to overridden virtual functions, if there are any.
3984 //
3985 // FIXME: This isn't wonderful, because we don't know whether we're actually
3986 // in a context that permits expressions. This is a general issue with
3987 // qualified-id completions.
3988 if (!EnteringContext)
3989 MaybeAddOverrideCalls(*this, Ctx, Results);
3990 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003991
Douglas Gregorf6961522010-08-27 21:18:54 +00003992 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3993 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3994
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003995 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00003996 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003997 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003998}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003999
4000void Sema::CodeCompleteUsing(Scope *S) {
4001 if (!CodeCompleter)
4002 return;
4003
Douglas Gregor218937c2011-02-01 19:23:04 +00004004 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004005 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004006 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4007 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004008 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004009
4010 // If we aren't in class scope, we could see the "namespace" keyword.
4011 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00004012 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004013
4014 // After "using", we can see anything that would start a
4015 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004016 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004017 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4018 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004019 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004020
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004021 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004022 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004023 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004024}
4025
4026void Sema::CodeCompleteUsingDirective(Scope *S) {
4027 if (!CodeCompleter)
4028 return;
4029
Douglas Gregor86d9a522009-09-21 16:56:56 +00004030 // After "using namespace", we expect to see a namespace name or namespace
4031 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004032 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004033 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004034 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004035 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004036 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004037 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004038 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4039 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004040 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004041 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004042 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004043 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004044}
4045
4046void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4047 if (!CodeCompleter)
4048 return;
4049
Douglas Gregor86d9a522009-09-21 16:56:56 +00004050 DeclContext *Ctx = (DeclContext *)S->getEntity();
4051 if (!S->getParent())
4052 Ctx = Context.getTranslationUnitDecl();
4053
Douglas Gregor52779fb2010-09-23 23:01:17 +00004054 bool SuppressedGlobalResults
4055 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4056
Douglas Gregor218937c2011-02-01 19:23:04 +00004057 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004058 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004059 SuppressedGlobalResults
4060 ? CodeCompletionContext::CCC_Namespace
4061 : CodeCompletionContext::CCC_Other,
4062 &ResultBuilder::IsNamespace);
4063
4064 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004065 // We only want to see those namespaces that have already been defined
4066 // within this scope, because its likely that the user is creating an
4067 // extended namespace declaration. Keep track of the most recent
4068 // definition of each namespace.
4069 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4070 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4071 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4072 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004073 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004074
4075 // Add the most recent definition (or extended definition) of each
4076 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004077 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004078 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004079 NS = OrigToLatest.begin(),
4080 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004081 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004082 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004083 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004084 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004085 }
4086
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004087 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004088 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004089 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004090}
4091
4092void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4093 if (!CodeCompleter)
4094 return;
4095
Douglas Gregor86d9a522009-09-21 16:56:56 +00004096 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004097 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004098 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004099 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004100 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004101 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004102 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4103 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004104 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004105 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004106 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004107}
4108
Douglas Gregored8d3222009-09-18 20:05:18 +00004109void Sema::CodeCompleteOperatorName(Scope *S) {
4110 if (!CodeCompleter)
4111 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004112
John McCall0a2c5e22010-08-25 06:19:51 +00004113 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004114 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004115 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004116 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004117 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004118 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004119
Douglas Gregor86d9a522009-09-21 16:56:56 +00004120 // Add the names of overloadable operators.
4121#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4122 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004123 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004124#include "clang/Basic/OperatorKinds.def"
4125
4126 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004127 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004128 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004129 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4130 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004131
4132 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004133 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004134 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004135
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004136 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004137 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004138 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004139}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004140
Douglas Gregor0133f522010-08-28 00:00:50 +00004141void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004142 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004143 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004144 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004145 CXXConstructorDecl *Constructor
4146 = static_cast<CXXConstructorDecl *>(ConstructorD);
4147 if (!Constructor)
4148 return;
4149
Douglas Gregor218937c2011-02-01 19:23:04 +00004150 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004151 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004152 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004153 Results.EnterNewScope();
4154
4155 // Fill in any already-initialized fields or base classes.
4156 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4157 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4158 for (unsigned I = 0; I != NumInitializers; ++I) {
4159 if (Initializers[I]->isBaseInitializer())
4160 InitializedBases.insert(
4161 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4162 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004163 InitializedFields.insert(cast<FieldDecl>(
4164 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004165 }
4166
4167 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004168 CodeCompletionBuilder Builder(Results.getAllocator(),
4169 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004170 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004171 CXXRecordDecl *ClassDecl = Constructor->getParent();
4172 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4173 BaseEnd = ClassDecl->bases_end();
4174 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004175 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4176 SawLastInitializer
4177 = NumInitializers > 0 &&
4178 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4179 Context.hasSameUnqualifiedType(Base->getType(),
4180 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004181 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004182 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004183
Douglas Gregor218937c2011-02-01 19:23:04 +00004184 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004185 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004186 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004187 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4188 Builder.AddPlaceholderChunk("args");
4189 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4190 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004191 SawLastInitializer? CCP_NextInitializer
4192 : CCP_MemberDeclaration));
4193 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004194 }
4195
4196 // Add completions for virtual base classes.
4197 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4198 BaseEnd = ClassDecl->vbases_end();
4199 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004200 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4201 SawLastInitializer
4202 = NumInitializers > 0 &&
4203 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4204 Context.hasSameUnqualifiedType(Base->getType(),
4205 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004206 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004207 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004208
Douglas Gregor218937c2011-02-01 19:23:04 +00004209 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004210 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004211 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004212 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4213 Builder.AddPlaceholderChunk("args");
4214 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4215 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004216 SawLastInitializer? CCP_NextInitializer
4217 : CCP_MemberDeclaration));
4218 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004219 }
4220
4221 // Add completions for members.
4222 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4223 FieldEnd = ClassDecl->field_end();
4224 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004225 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4226 SawLastInitializer
4227 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004228 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie581deb32012-06-06 20:45:41 +00004229 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004230 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004231 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004232
4233 if (!Field->getDeclName())
4234 continue;
4235
Douglas Gregordae68752011-02-01 22:57:45 +00004236 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004237 Field->getIdentifier()->getName()));
4238 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4239 Builder.AddPlaceholderChunk("args");
4240 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4241 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004242 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004243 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004244 CXCursor_MemberRef,
4245 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004246 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004247 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004248 }
4249 Results.ExitScope();
4250
Douglas Gregor52779fb2010-09-23 23:01:17 +00004251 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004252 Results.data(), Results.size());
4253}
4254
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004255/// \brief Determine whether this scope denotes a namespace.
4256static bool isNamespaceScope(Scope *S) {
4257 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4258 if (!DC)
4259 return false;
4260
4261 return DC->isFileContext();
4262}
4263
4264void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4265 bool AfterAmpersand) {
4266 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004267 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004268 CodeCompletionContext::CCC_Other);
4269 Results.EnterNewScope();
4270
4271 // Note what has already been captured.
4272 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4273 bool IncludedThis = false;
4274 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4275 CEnd = Intro.Captures.end();
4276 C != CEnd; ++C) {
4277 if (C->Kind == LCK_This) {
4278 IncludedThis = true;
4279 continue;
4280 }
4281
4282 Known.insert(C->Id);
4283 }
4284
4285 // Look for other capturable variables.
4286 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4287 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4288 D != DEnd; ++D) {
4289 VarDecl *Var = dyn_cast<VarDecl>(*D);
4290 if (!Var ||
4291 !Var->hasLocalStorage() ||
4292 Var->hasAttr<BlocksAttr>())
4293 continue;
4294
4295 if (Known.insert(Var->getIdentifier()))
4296 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4297 }
4298 }
4299
4300 // Add 'this', if it would be valid.
4301 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4302 addThisCompletion(*this, Results);
4303
4304 Results.ExitScope();
4305
4306 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4307 Results.data(), Results.size());
4308}
4309
James Dennetta40f7922012-06-14 03:11:41 +00004310/// Macro that optionally prepends an "@" to the string literal passed in via
4311/// Keyword, depending on whether NeedAt is true or false.
4312#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4313
Douglas Gregorbca403c2010-01-13 23:51:12 +00004314static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004315 ResultBuilder &Results,
4316 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004317 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004318 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004319 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004320
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004321 CodeCompletionBuilder Builder(Results.getAllocator(),
4322 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004323 if (LangOpts.ObjC2) {
4324 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004325 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004326 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4327 Builder.AddPlaceholderChunk("property");
4328 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004329
4330 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004331 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004332 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4333 Builder.AddPlaceholderChunk("property");
4334 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004335 }
4336}
4337
Douglas Gregorbca403c2010-01-13 23:51:12 +00004338static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004339 ResultBuilder &Results,
4340 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004341 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004342
4343 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004344 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004345
4346 if (LangOpts.ObjC2) {
4347 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004348 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004349
4350 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004351 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004352
4353 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004354 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004355 }
4356}
4357
Douglas Gregorbca403c2010-01-13 23:51:12 +00004358static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004359 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004360 CodeCompletionBuilder Builder(Results.getAllocator(),
4361 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004362
4363 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004364 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004365 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4366 Builder.AddPlaceholderChunk("name");
4367 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004368
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004369 if (Results.includeCodePatterns()) {
4370 // @interface name
4371 // FIXME: Could introduce the whole pattern, including superclasses and
4372 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004373 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004374 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4375 Builder.AddPlaceholderChunk("class");
4376 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004377
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004378 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004379 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004380 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4381 Builder.AddPlaceholderChunk("protocol");
4382 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004383
4384 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004385 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004386 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4387 Builder.AddPlaceholderChunk("class");
4388 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004389 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004390
4391 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004392 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004393 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4394 Builder.AddPlaceholderChunk("alias");
4395 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4396 Builder.AddPlaceholderChunk("class");
4397 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004398}
4399
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004400void Sema::CodeCompleteObjCAtDirective(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004401 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004402 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004403 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004404 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004405 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004406 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004407 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004408 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004409 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004410 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004411 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004412 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004413 HandleCodeCompleteResults(this, CodeCompleter,
4414 CodeCompletionContext::CCC_Other,
4415 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004416}
4417
Douglas Gregorbca403c2010-01-13 23:51:12 +00004418static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004419 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004420 CodeCompletionBuilder Builder(Results.getAllocator(),
4421 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004422
4423 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004424 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004425 if (Results.getSema().getLangOpts().CPlusPlus ||
4426 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004427 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004428 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004429 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004430 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4431 Builder.AddPlaceholderChunk("type-name");
4432 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4433 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004434
4435 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004436 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004437 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004438 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4439 Builder.AddPlaceholderChunk("protocol-name");
4440 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4441 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004442
4443 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004444 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004445 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004446 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4447 Builder.AddPlaceholderChunk("selector");
4448 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4449 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004450
4451 // @"string"
4452 Builder.AddResultTypeChunk("NSString *");
4453 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4454 Builder.AddPlaceholderChunk("string");
4455 Builder.AddTextChunk("\"");
4456 Results.AddResult(Result(Builder.TakeString()));
4457
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004458 // @[ objects, ... ]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004459 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004460 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004461 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4462 Builder.AddPlaceholderChunk("objects, ...");
4463 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4464 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4465 Results.AddResult(Result(Builder.TakeString()));
4466
4467 // @{ key : object, ... }
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004468 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004469 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004470 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4471 Builder.AddPlaceholderChunk("key");
4472 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4473 Builder.AddChunk(CodeCompletionString::CK_Colon);
4474 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4475 Builder.AddPlaceholderChunk("object, ...");
4476 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4477 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4478 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004479
4480 // @( expression )
4481 Builder.AddResultTypeChunk("id");
4482 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
4483 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4484 Builder.AddPlaceholderChunk("expression");
4485 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4486 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4487 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004488}
4489
Douglas Gregorbca403c2010-01-13 23:51:12 +00004490static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004491 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004492 CodeCompletionBuilder Builder(Results.getAllocator(),
4493 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004494
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004495 if (Results.includeCodePatterns()) {
4496 // @try { statements } @catch ( declaration ) { statements } @finally
4497 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004498 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004499 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4500 Builder.AddPlaceholderChunk("statements");
4501 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4502 Builder.AddTextChunk("@catch");
4503 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4504 Builder.AddPlaceholderChunk("parameter");
4505 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4506 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4507 Builder.AddPlaceholderChunk("statements");
4508 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4509 Builder.AddTextChunk("@finally");
4510 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4511 Builder.AddPlaceholderChunk("statements");
4512 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4513 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004514 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004515
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004516 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004517 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004518 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4519 Builder.AddPlaceholderChunk("expression");
4520 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004521
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004522 if (Results.includeCodePatterns()) {
4523 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004524 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004525 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4526 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4527 Builder.AddPlaceholderChunk("expression");
4528 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4529 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4530 Builder.AddPlaceholderChunk("statements");
4531 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4532 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004533 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004534}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004535
Douglas Gregorbca403c2010-01-13 23:51:12 +00004536static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004537 ResultBuilder &Results,
4538 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004539 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004540 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4541 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4542 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004543 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004544 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004545}
4546
4547void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004548 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004549 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004550 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004551 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004552 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004553 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004554 HandleCodeCompleteResults(this, CodeCompleter,
4555 CodeCompletionContext::CCC_Other,
4556 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004557}
4558
4559void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004560 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004561 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004562 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004563 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004564 AddObjCStatementResults(Results, false);
4565 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004566 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004567 HandleCodeCompleteResults(this, CodeCompleter,
4568 CodeCompletionContext::CCC_Other,
4569 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004570}
4571
4572void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004573 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004574 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004575 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004576 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004577 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004578 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004579 HandleCodeCompleteResults(this, CodeCompleter,
4580 CodeCompletionContext::CCC_Other,
4581 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004582}
4583
Douglas Gregor988358f2009-11-19 00:14:45 +00004584/// \brief Determine whether the addition of the given flag to an Objective-C
4585/// property's attributes will cause a conflict.
4586static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4587 // Check if we've already added this flag.
4588 if (Attributes & NewFlag)
4589 return true;
4590
4591 Attributes |= NewFlag;
4592
4593 // Check for collisions with "readonly".
4594 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4595 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4596 ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004597 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004598 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004599 ObjCDeclSpec::DQ_PR_retain |
4600 ObjCDeclSpec::DQ_PR_strong)))
Douglas Gregor988358f2009-11-19 00:14:45 +00004601 return true;
4602
John McCallf85e1932011-06-15 23:02:42 +00004603 // Check for more than one of { assign, copy, retain, strong }.
Douglas Gregor988358f2009-11-19 00:14:45 +00004604 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004605 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004606 ObjCDeclSpec::DQ_PR_copy |
John McCallf85e1932011-06-15 23:02:42 +00004607 ObjCDeclSpec::DQ_PR_retain|
4608 ObjCDeclSpec::DQ_PR_strong);
Douglas Gregor988358f2009-11-19 00:14:45 +00004609 if (AssignCopyRetMask &&
4610 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004611 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004612 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004613 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
4614 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong)
Douglas Gregor988358f2009-11-19 00:14:45 +00004615 return true;
4616
4617 return false;
4618}
4619
Douglas Gregora93b1082009-11-18 23:08:07 +00004620void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004621 if (!CodeCompleter)
4622 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004623
Steve Naroffece8e712009-10-08 21:55:05 +00004624 unsigned Attributes = ODS.getPropertyAttributes();
4625
John McCall0a2c5e22010-08-25 06:19:51 +00004626 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004627 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004628 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004629 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004630 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004631 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004632 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004633 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004634 Results.AddResult(CodeCompletionResult("assign"));
John McCallf85e1932011-06-15 23:02:42 +00004635 if (!ObjCPropertyFlagConflicts(Attributes,
4636 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4637 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004638 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004639 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004640 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004641 Results.AddResult(CodeCompletionResult("retain"));
John McCallf85e1932011-06-15 23:02:42 +00004642 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
4643 Results.AddResult(CodeCompletionResult("strong"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004644 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004645 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004646 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004647 Results.AddResult(CodeCompletionResult("nonatomic"));
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004648 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
4649 Results.AddResult(CodeCompletionResult("atomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004650 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004651 CodeCompletionBuilder Setter(Results.getAllocator(),
4652 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004653 Setter.AddTypedTextChunk("setter");
4654 Setter.AddTextChunk(" = ");
4655 Setter.AddPlaceholderChunk("method");
4656 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004657 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004658 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004659 CodeCompletionBuilder Getter(Results.getAllocator(),
4660 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004661 Getter.AddTypedTextChunk("getter");
4662 Getter.AddTextChunk(" = ");
4663 Getter.AddPlaceholderChunk("method");
4664 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004665 }
Steve Naroffece8e712009-10-08 21:55:05 +00004666 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004667 HandleCodeCompleteResults(this, CodeCompleter,
4668 CodeCompletionContext::CCC_Other,
4669 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004670}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004671
James Dennettde23c7e2012-06-17 05:33:25 +00004672/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregor4ad96852009-11-19 07:41:15 +00004673/// via code completion.
4674enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004675 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4676 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4677 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004678};
4679
Douglas Gregor458433d2010-08-26 15:07:07 +00004680static bool isAcceptableObjCSelector(Selector Sel,
4681 ObjCMethodKind WantKind,
4682 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004683 unsigned NumSelIdents,
4684 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004685 if (NumSelIdents > Sel.getNumArgs())
4686 return false;
4687
4688 switch (WantKind) {
4689 case MK_Any: break;
4690 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4691 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4692 }
4693
Douglas Gregorcf544262010-11-17 21:36:08 +00004694 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4695 return false;
4696
Douglas Gregor458433d2010-08-26 15:07:07 +00004697 for (unsigned I = 0; I != NumSelIdents; ++I)
4698 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4699 return false;
4700
4701 return true;
4702}
4703
Douglas Gregor4ad96852009-11-19 07:41:15 +00004704static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4705 ObjCMethodKind WantKind,
4706 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004707 unsigned NumSelIdents,
4708 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004709 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004710 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004711}
Douglas Gregord36adf52010-09-16 16:06:31 +00004712
4713namespace {
4714 /// \brief A set of selectors, which is used to avoid introducing multiple
4715 /// completions with the same selector into the result set.
4716 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4717}
4718
Douglas Gregor36ecb042009-11-17 23:22:23 +00004719/// \brief Add all of the Objective-C methods in the given Objective-C
4720/// container to the set of results.
4721///
4722/// The container will be a class, protocol, category, or implementation of
4723/// any of the above. This mether will recurse to include methods from
4724/// the superclasses of classes along with their categories, protocols, and
4725/// implementations.
4726///
4727/// \param Container the container in which we'll look to find methods.
4728///
James Dennetta40f7922012-06-14 03:11:41 +00004729/// \param WantInstanceMethods Whether to add instance methods (only); if
4730/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004731///
4732/// \param CurContext the context in which we're performing the lookup that
4733/// finds methods.
4734///
Douglas Gregorcf544262010-11-17 21:36:08 +00004735/// \param AllowSameLength Whether we allow a method to be added to the list
4736/// when it has the same number of parameters as we have selector identifiers.
4737///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004738/// \param Results the structure into which we'll add results.
4739static void AddObjCMethods(ObjCContainerDecl *Container,
4740 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004741 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004742 IdentifierInfo **SelIdents,
4743 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004744 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004745 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004746 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004747 ResultBuilder &Results,
4748 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004749 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004750 Container = getContainerDef(Container);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004751 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4752 MEnd = Container->meth_end();
4753 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00004754 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004755 // Check whether the selector identifiers we've been given are a
4756 // subset of the identifiers for this particular method.
David Blaikie581deb32012-06-06 20:45:41 +00004757 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004758 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004759 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004760
David Blaikie262bc182012-04-30 02:36:29 +00004761 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004762 continue;
4763
David Blaikie581deb32012-06-06 20:45:41 +00004764 Result R = Result(*M, 0);
Douglas Gregord3c68542009-11-19 01:08:35 +00004765 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004766 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004767 if (!InOriginalClass)
4768 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004769 Results.MaybeAddResult(R, CurContext);
4770 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004771 }
4772
Douglas Gregore396c7b2010-09-16 15:34:59 +00004773 // Visit the protocols of protocols.
4774 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004775 if (Protocol->hasDefinition()) {
4776 const ObjCList<ObjCProtocolDecl> &Protocols
4777 = Protocol->getReferencedProtocols();
4778 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4779 E = Protocols.end();
4780 I != E; ++I)
4781 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4782 NumSelIdents, CurContext, Selectors, AllowSameLength,
4783 Results, false);
4784 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004785 }
4786
Douglas Gregor36ecb042009-11-17 23:22:23 +00004787 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004788 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004789 return;
4790
4791 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004792 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4793 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004794 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004795 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004796 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004797
4798 // Add methods in categories.
4799 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4800 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004801 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004802 NumSelIdents, CurContext, Selectors, AllowSameLength,
4803 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004804
4805 // Add a categories protocol methods.
4806 const ObjCList<ObjCProtocolDecl> &Protocols
4807 = CatDecl->getReferencedProtocols();
4808 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4809 E = Protocols.end();
4810 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004811 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004812 NumSelIdents, CurContext, Selectors, AllowSameLength,
4813 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004814
4815 // Add methods in category implementations.
4816 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004817 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004818 NumSelIdents, CurContext, Selectors, AllowSameLength,
4819 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004820 }
4821
4822 // Add methods in superclass.
4823 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004824 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004825 SelIdents, NumSelIdents, CurContext, Selectors,
4826 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004827
4828 // Add methods in our implementation, if any.
4829 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004830 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004831 NumSelIdents, CurContext, Selectors, AllowSameLength,
4832 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004833}
4834
4835
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004836void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004837 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004838
4839 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004840 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004841 if (!Class) {
4842 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004843 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004844 Class = Category->getClassInterface();
4845
4846 if (!Class)
4847 return;
4848 }
4849
4850 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004851 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004852 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004853 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004854 Results.EnterNewScope();
4855
Douglas Gregord36adf52010-09-16 16:06:31 +00004856 VisitedSelectorSet Selectors;
4857 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004858 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004859 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004860 HandleCodeCompleteResults(this, CodeCompleter,
4861 CodeCompletionContext::CCC_Other,
4862 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004863}
4864
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004865void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004866 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004867
4868 // Try to find the interface where setters might live.
4869 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004870 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004871 if (!Class) {
4872 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004873 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004874 Class = Category->getClassInterface();
4875
4876 if (!Class)
4877 return;
4878 }
4879
4880 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004881 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004882 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004883 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004884 Results.EnterNewScope();
4885
Douglas Gregord36adf52010-09-16 16:06:31 +00004886 VisitedSelectorSet Selectors;
4887 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004888 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004889
4890 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004891 HandleCodeCompleteResults(this, CodeCompleter,
4892 CodeCompletionContext::CCC_Other,
4893 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004894}
4895
Douglas Gregorafc45782011-02-15 22:19:42 +00004896void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4897 bool IsParameter) {
John McCall0a2c5e22010-08-25 06:19:51 +00004898 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004899 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004900 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004901 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004902 Results.EnterNewScope();
4903
4904 // Add context-sensitive, Objective-C parameter-passing keywords.
4905 bool AddedInOut = false;
4906 if ((DS.getObjCDeclQualifier() &
4907 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4908 Results.AddResult("in");
4909 Results.AddResult("inout");
4910 AddedInOut = true;
4911 }
4912 if ((DS.getObjCDeclQualifier() &
4913 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4914 Results.AddResult("out");
4915 if (!AddedInOut)
4916 Results.AddResult("inout");
4917 }
4918 if ((DS.getObjCDeclQualifier() &
4919 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4920 ObjCDeclSpec::DQ_Oneway)) == 0) {
4921 Results.AddResult("bycopy");
4922 Results.AddResult("byref");
4923 Results.AddResult("oneway");
4924 }
4925
Douglas Gregorafc45782011-02-15 22:19:42 +00004926 // If we're completing the return type of an Objective-C method and the
4927 // identifier IBAction refers to a macro, provide a completion item for
4928 // an action, e.g.,
4929 // IBAction)<#selector#>:(id)sender
4930 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4931 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004932 CodeCompletionBuilder Builder(Results.getAllocator(),
4933 Results.getCodeCompletionTUInfo(),
4934 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004935 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004936 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004937 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004938 Builder.AddChunk(CodeCompletionString::CK_Colon);
4939 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004940 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004941 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004942 Builder.AddTextChunk("sender");
4943 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4944 }
4945
Douglas Gregord32b0222010-08-24 01:06:58 +00004946 // Add various builtin type names and specifiers.
4947 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4948 Results.ExitScope();
4949
4950 // Add the various type names
4951 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4952 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4953 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4954 CodeCompleter->includeGlobals());
4955
4956 if (CodeCompleter->includeMacros())
4957 AddMacroResults(PP, Results);
4958
4959 HandleCodeCompleteResults(this, CodeCompleter,
4960 CodeCompletionContext::CCC_Type,
4961 Results.data(), Results.size());
4962}
4963
Douglas Gregor22f56992010-04-06 19:22:33 +00004964/// \brief When we have an expression with type "id", we may assume
4965/// that it has some more-specific class type based on knowledge of
4966/// common uses of Objective-C. This routine returns that class type,
4967/// or NULL if no better result could be determined.
4968static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004969 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004970 if (!Msg)
4971 return 0;
4972
4973 Selector Sel = Msg->getSelector();
4974 if (Sel.isNull())
4975 return 0;
4976
4977 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4978 if (!Id)
4979 return 0;
4980
4981 ObjCMethodDecl *Method = Msg->getMethodDecl();
4982 if (!Method)
4983 return 0;
4984
4985 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004986 ObjCInterfaceDecl *IFace = 0;
4987 switch (Msg->getReceiverKind()) {
4988 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004989 if (const ObjCObjectType *ObjType
4990 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4991 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004992 break;
4993
4994 case ObjCMessageExpr::Instance: {
4995 QualType T = Msg->getInstanceReceiver()->getType();
4996 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4997 IFace = Ptr->getInterfaceDecl();
4998 break;
4999 }
5000
5001 case ObjCMessageExpr::SuperInstance:
5002 case ObjCMessageExpr::SuperClass:
5003 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00005004 }
5005
5006 if (!IFace)
5007 return 0;
5008
5009 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5010 if (Method->isInstanceMethod())
5011 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5012 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005013 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005014 .Case("autorelease", IFace)
5015 .Case("copy", IFace)
5016 .Case("copyWithZone", IFace)
5017 .Case("mutableCopy", IFace)
5018 .Case("mutableCopyWithZone", IFace)
5019 .Case("awakeFromCoder", IFace)
5020 .Case("replacementObjectFromCoder", IFace)
5021 .Case("class", IFace)
5022 .Case("classForCoder", IFace)
5023 .Case("superclass", Super)
5024 .Default(0);
5025
5026 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5027 .Case("new", IFace)
5028 .Case("alloc", IFace)
5029 .Case("allocWithZone", IFace)
5030 .Case("class", IFace)
5031 .Case("superclass", Super)
5032 .Default(0);
5033}
5034
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005035// Add a special completion for a message send to "super", which fills in the
5036// most likely case of forwarding all of our arguments to the superclass
5037// function.
5038///
5039/// \param S The semantic analysis object.
5040///
5041/// \param S NeedSuperKeyword Whether we need to prefix this completion with
5042/// the "super" keyword. Otherwise, we just need to provide the arguments.
5043///
5044/// \param SelIdents The identifiers in the selector that have already been
5045/// provided as arguments for a send to "super".
5046///
5047/// \param NumSelIdents The number of identifiers in \p SelIdents.
5048///
5049/// \param Results The set of results to augment.
5050///
5051/// \returns the Objective-C method declaration that would be invoked by
5052/// this "super" completion. If NULL, no completion was added.
5053static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5054 IdentifierInfo **SelIdents,
5055 unsigned NumSelIdents,
5056 ResultBuilder &Results) {
5057 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5058 if (!CurMethod)
5059 return 0;
5060
5061 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5062 if (!Class)
5063 return 0;
5064
5065 // Try to find a superclass method with the same selector.
5066 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005067 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5068 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005069 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5070 CurMethod->isInstanceMethod());
5071
Douglas Gregor78bcd912011-02-16 00:51:18 +00005072 // Check in categories or class extensions.
5073 if (!SuperMethod) {
5074 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5075 Category = Category->getNextClassCategory())
5076 if ((SuperMethod = Category->getMethod(CurMethod->getSelector(),
5077 CurMethod->isInstanceMethod())))
5078 break;
5079 }
5080 }
5081
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005082 if (!SuperMethod)
5083 return 0;
5084
5085 // Check whether the superclass method has the same signature.
5086 if (CurMethod->param_size() != SuperMethod->param_size() ||
5087 CurMethod->isVariadic() != SuperMethod->isVariadic())
5088 return 0;
5089
5090 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5091 CurPEnd = CurMethod->param_end(),
5092 SuperP = SuperMethod->param_begin();
5093 CurP != CurPEnd; ++CurP, ++SuperP) {
5094 // Make sure the parameter types are compatible.
5095 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5096 (*SuperP)->getType()))
5097 return 0;
5098
5099 // Make sure we have a parameter name to forward!
5100 if (!(*CurP)->getIdentifier())
5101 return 0;
5102 }
5103
5104 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005105 CodeCompletionBuilder Builder(Results.getAllocator(),
5106 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005107
5108 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005109 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5110 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005111
5112 // If we need the "super" keyword, add it (plus some spacing).
5113 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005114 Builder.AddTypedTextChunk("super");
5115 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005116 }
5117
5118 Selector Sel = CurMethod->getSelector();
5119 if (Sel.isUnarySelector()) {
5120 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005121 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005122 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005123 else
Douglas Gregordae68752011-02-01 22:57:45 +00005124 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005125 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005126 } else {
5127 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5128 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5129 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005130 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005131
5132 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005133 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005134 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005135 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005136 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005137 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005138 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005139 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005140 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005141 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005142 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005143 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005144 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005145 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005146 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005147 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005148 }
5149 }
5150 }
5151
Douglas Gregorba103062012-03-27 23:34:16 +00005152 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5153 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005154 return SuperMethod;
5155}
5156
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005157void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005158 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005159 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005160 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005161 CodeCompletionContext::CCC_ObjCMessageReceiver,
David Blaikie4e4d0842012-03-11 07:00:24 +00005162 getLangOpts().CPlusPlus0x
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005163 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5164 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005165
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005166 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5167 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005168 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5169 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005170
5171 // If we are in an Objective-C method inside a class that has a superclass,
5172 // add "super" as an option.
5173 if (ObjCMethodDecl *Method = getCurMethodDecl())
5174 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005175 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005176 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005177
5178 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5179 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005180
David Blaikie4e4d0842012-03-11 07:00:24 +00005181 if (getLangOpts().CPlusPlus0x)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005182 addThisCompletion(*this, Results);
5183
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005184 Results.ExitScope();
5185
5186 if (CodeCompleter->includeMacros())
5187 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005188 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005189 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005190
5191}
5192
Douglas Gregor2725ca82010-04-21 19:57:20 +00005193void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5194 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005195 unsigned NumSelIdents,
5196 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005197 ObjCInterfaceDecl *CDecl = 0;
5198 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5199 // Figure out which interface we're in.
5200 CDecl = CurMethod->getClassInterface();
5201 if (!CDecl)
5202 return;
5203
5204 // Find the superclass of this class.
5205 CDecl = CDecl->getSuperClass();
5206 if (!CDecl)
5207 return;
5208
5209 if (CurMethod->isInstanceMethod()) {
5210 // We are inside an instance method, which means that the message
5211 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005212 // current object.
5213 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005214 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005215 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005216 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005217 }
5218
5219 // Fall through to send to the superclass in CDecl.
5220 } else {
5221 // "super" may be the name of a type or variable. Figure out which
5222 // it is.
5223 IdentifierInfo *Super = &Context.Idents.get("super");
5224 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5225 LookupOrdinaryName);
5226 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5227 // "super" names an interface. Use it.
5228 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005229 if (const ObjCObjectType *Iface
5230 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5231 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005232 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5233 // "super" names an unresolved type; we can't be more specific.
5234 } else {
5235 // Assume that "super" names some kind of value and parse that way.
5236 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005237 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005238 UnqualifiedId id;
5239 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005240 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5241 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005242 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005243 SelIdents, NumSelIdents,
5244 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005245 }
5246
5247 // Fall through
5248 }
5249
John McCallb3d87482010-08-24 05:47:05 +00005250 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005251 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005252 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005253 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005254 NumSelIdents, AtArgumentExpression,
5255 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005256}
5257
Douglas Gregorb9d77572010-09-21 00:03:25 +00005258/// \brief Given a set of code-completion results for the argument of a message
5259/// send, determine the preferred type (if any) for that argument expression.
5260static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5261 unsigned NumSelIdents) {
5262 typedef CodeCompletionResult Result;
5263 ASTContext &Context = Results.getSema().Context;
5264
5265 QualType PreferredType;
5266 unsigned BestPriority = CCP_Unlikely * 2;
5267 Result *ResultsData = Results.data();
5268 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5269 Result &R = ResultsData[I];
5270 if (R.Kind == Result::RK_Declaration &&
5271 isa<ObjCMethodDecl>(R.Declaration)) {
5272 if (R.Priority <= BestPriority) {
5273 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
5274 if (NumSelIdents <= Method->param_size()) {
5275 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5276 ->getType();
5277 if (R.Priority < BestPriority || PreferredType.isNull()) {
5278 BestPriority = R.Priority;
5279 PreferredType = MyPreferredType;
5280 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5281 MyPreferredType)) {
5282 PreferredType = QualType();
5283 }
5284 }
5285 }
5286 }
5287 }
5288
5289 return PreferredType;
5290}
5291
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005292static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5293 ParsedType Receiver,
5294 IdentifierInfo **SelIdents,
5295 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005296 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005297 bool IsSuper,
5298 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005299 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005300 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005301
Douglas Gregor24a069f2009-11-17 17:59:40 +00005302 // If the given name refers to an interface type, retrieve the
5303 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005304 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005305 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005306 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005307 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5308 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005309 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005310
Douglas Gregor36ecb042009-11-17 23:22:23 +00005311 // Add all of the factory methods in this Objective-C class, its protocols,
5312 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005313 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005314
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005315 // If this is a send-to-super, try to add the special "super" send
5316 // completion.
5317 if (IsSuper) {
5318 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005319 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5320 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005321 Results.Ignore(SuperMethod);
5322 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005323
Douglas Gregor265f7492010-08-27 15:29:55 +00005324 // If we're inside an Objective-C method definition, prefer its selector to
5325 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005326 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005327 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005328
Douglas Gregord36adf52010-09-16 16:06:31 +00005329 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005330 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005331 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005332 SemaRef.CurContext, Selectors, AtArgumentExpression,
5333 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005334 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005335 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005336
Douglas Gregor719770d2010-04-06 17:30:22 +00005337 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005338 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005339 if (SemaRef.ExternalSource) {
5340 for (uint32_t I = 0,
5341 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005342 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005343 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
5344 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005345 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005346
5347 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005348 }
5349 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005350
5351 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5352 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005353 M != MEnd; ++M) {
5354 for (ObjCMethodList *MethList = &M->second.second;
5355 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005356 MethList = MethList->Next) {
5357 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5358 NumSelIdents))
5359 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005360
Douglas Gregor13438f92010-04-06 16:40:00 +00005361 Result R(MethList->Method, 0);
5362 R.StartParameter = NumSelIdents;
5363 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005364 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005365 }
5366 }
5367 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005368
5369 Results.ExitScope();
5370}
Douglas Gregor13438f92010-04-06 16:40:00 +00005371
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005372void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5373 IdentifierInfo **SelIdents,
5374 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005375 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005376 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005377
5378 QualType T = this->GetTypeFromParser(Receiver);
5379
Douglas Gregor218937c2011-02-01 19:23:04 +00005380 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005381 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005382 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005383 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005384
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005385 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5386 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005387
5388 // If we're actually at the argument expression (rather than prior to the
5389 // selector), we're actually performing code completion for an expression.
5390 // Determine whether we have a single, best method. If so, we can
5391 // code-complete the expression using the corresponding parameter type as
5392 // our preferred type, improving completion results.
5393 if (AtArgumentExpression) {
5394 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005395 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005396 if (PreferredType.isNull())
5397 CodeCompleteOrdinaryName(S, PCC_Expression);
5398 else
5399 CodeCompleteExpression(S, PreferredType);
5400 return;
5401 }
5402
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005403 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005404 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005405 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005406}
5407
Richard Trieuf81e5a92011-09-09 02:00:50 +00005408void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005409 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005410 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005411 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005412 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005413 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005414
5415 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005416
Douglas Gregor36ecb042009-11-17 23:22:23 +00005417 // If necessary, apply function/array conversion to the receiver.
5418 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005419 if (RecExpr) {
5420 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5421 if (Conv.isInvalid()) // conversion failed. bail.
5422 return;
5423 RecExpr = Conv.take();
5424 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005425 QualType ReceiverType = RecExpr? RecExpr->getType()
5426 : Super? Context.getObjCObjectPointerType(
5427 Context.getObjCInterfaceType(Super))
5428 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005429
Douglas Gregorda892642010-11-08 21:12:30 +00005430 // If we're messaging an expression with type "id" or "Class", check
5431 // whether we know something special about the receiver that allows
5432 // us to assume a more-specific receiver type.
5433 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5434 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5435 if (ReceiverType->isObjCClassType())
5436 return CodeCompleteObjCClassMessage(S,
5437 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5438 SelIdents, NumSelIdents,
5439 AtArgumentExpression, Super);
5440
5441 ReceiverType = Context.getObjCObjectPointerType(
5442 Context.getObjCInterfaceType(IFace));
5443 }
5444
Douglas Gregor36ecb042009-11-17 23:22:23 +00005445 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005446 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005447 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005448 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005449 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005450
Douglas Gregor36ecb042009-11-17 23:22:23 +00005451 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005452
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005453 // If this is a send-to-super, try to add the special "super" send
5454 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005455 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005456 if (ObjCMethodDecl *SuperMethod
5457 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5458 Results))
5459 Results.Ignore(SuperMethod);
5460 }
5461
Douglas Gregor265f7492010-08-27 15:29:55 +00005462 // If we're inside an Objective-C method definition, prefer its selector to
5463 // others.
5464 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5465 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005466
Douglas Gregord36adf52010-09-16 16:06:31 +00005467 // Keep track of the selectors we've already added.
5468 VisitedSelectorSet Selectors;
5469
Douglas Gregorf74a4192009-11-18 00:06:18 +00005470 // Handle messages to Class. This really isn't a message to an instance
5471 // method, so we treat it the same way we would treat a message send to a
5472 // class method.
5473 if (ReceiverType->isObjCClassType() ||
5474 ReceiverType->isObjCQualifiedClassType()) {
5475 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5476 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005477 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005478 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005479 }
5480 }
5481 // Handle messages to a qualified ID ("id<foo>").
5482 else if (const ObjCObjectPointerType *QualID
5483 = ReceiverType->getAsObjCQualifiedIdType()) {
5484 // Search protocols for instance methods.
5485 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5486 E = QualID->qual_end();
5487 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005488 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005489 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005490 }
5491 // Handle messages to a pointer to interface type.
5492 else if (const ObjCObjectPointerType *IFacePtr
5493 = ReceiverType->getAsObjCInterfacePointerType()) {
5494 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005495 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005496 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5497 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005498
5499 // Search protocols for instance methods.
5500 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5501 E = IFacePtr->qual_end();
5502 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005503 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005504 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005505 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005506 // Handle messages to "id".
5507 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005508 // We're messaging "id", so provide all instance methods we know
5509 // about as code-completion results.
5510
5511 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005512 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005513 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005514 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5515 I != N; ++I) {
5516 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005517 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005518 continue;
5519
Sebastian Redldb9d2142010-08-02 23:18:59 +00005520 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005521 }
5522 }
5523
Sebastian Redldb9d2142010-08-02 23:18:59 +00005524 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5525 MEnd = MethodPool.end();
5526 M != MEnd; ++M) {
5527 for (ObjCMethodList *MethList = &M->second.first;
5528 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005529 MethList = MethList->Next) {
5530 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5531 NumSelIdents))
5532 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005533
5534 if (!Selectors.insert(MethList->Method->getSelector()))
5535 continue;
5536
Douglas Gregor13438f92010-04-06 16:40:00 +00005537 Result R(MethList->Method, 0);
5538 R.StartParameter = NumSelIdents;
5539 R.AllParametersAreInformative = false;
5540 Results.MaybeAddResult(R, CurContext);
5541 }
5542 }
5543 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005544 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005545
5546
5547 // If we're actually at the argument expression (rather than prior to the
5548 // selector), we're actually performing code completion for an expression.
5549 // Determine whether we have a single, best method. If so, we can
5550 // code-complete the expression using the corresponding parameter type as
5551 // our preferred type, improving completion results.
5552 if (AtArgumentExpression) {
5553 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5554 NumSelIdents);
5555 if (PreferredType.isNull())
5556 CodeCompleteOrdinaryName(S, PCC_Expression);
5557 else
5558 CodeCompleteExpression(S, PreferredType);
5559 return;
5560 }
5561
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005562 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005563 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005564 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005565}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005566
Douglas Gregorfb629412010-08-23 21:17:50 +00005567void Sema::CodeCompleteObjCForCollection(Scope *S,
5568 DeclGroupPtrTy IterationVar) {
5569 CodeCompleteExpressionData Data;
5570 Data.ObjCCollection = true;
5571
5572 if (IterationVar.getAsOpaquePtr()) {
5573 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5574 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5575 if (*I)
5576 Data.IgnoreDecls.push_back(*I);
5577 }
5578 }
5579
5580 CodeCompleteExpression(S, Data);
5581}
5582
Douglas Gregor458433d2010-08-26 15:07:07 +00005583void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5584 unsigned NumSelIdents) {
5585 // If we have an external source, load the entire class method
5586 // pool from the AST file.
5587 if (ExternalSource) {
5588 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5589 I != N; ++I) {
5590 Selector Sel = ExternalSource->GetExternalSelector(I);
5591 if (Sel.isNull() || MethodPool.count(Sel))
5592 continue;
5593
5594 ReadMethodPool(Sel);
5595 }
5596 }
5597
Douglas Gregor218937c2011-02-01 19:23:04 +00005598 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005599 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005600 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005601 Results.EnterNewScope();
5602 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5603 MEnd = MethodPool.end();
5604 M != MEnd; ++M) {
5605
5606 Selector Sel = M->first;
5607 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5608 continue;
5609
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005610 CodeCompletionBuilder Builder(Results.getAllocator(),
5611 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005612 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005613 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005614 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005615 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005616 continue;
5617 }
5618
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005619 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005620 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005621 if (I == NumSelIdents) {
5622 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005623 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005624 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005625 Accumulator.clear();
5626 }
5627 }
5628
Benjamin Kramera0651c52011-07-26 16:59:25 +00005629 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005630 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005631 }
Douglas Gregordae68752011-02-01 22:57:45 +00005632 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005633 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005634 }
5635 Results.ExitScope();
5636
5637 HandleCodeCompleteResults(this, CodeCompleter,
5638 CodeCompletionContext::CCC_SelectorName,
5639 Results.data(), Results.size());
5640}
5641
Douglas Gregor55385fe2009-11-18 04:19:12 +00005642/// \brief Add all of the protocol declarations that we find in the given
5643/// (translation unit) context.
5644static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005645 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005646 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005647 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005648
5649 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5650 DEnd = Ctx->decls_end();
5651 D != DEnd; ++D) {
5652 // Record any protocols we find.
5653 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005654 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005655 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005656 }
5657}
5658
5659void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5660 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005661 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005662 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005663 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005664
Douglas Gregor70c23352010-12-09 21:44:02 +00005665 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5666 Results.EnterNewScope();
5667
5668 // Tell the result set to ignore all of the protocols we have
5669 // already seen.
5670 // FIXME: This doesn't work when caching code-completion results.
5671 for (unsigned I = 0; I != NumProtocols; ++I)
5672 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5673 Protocols[I].second))
5674 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005675
Douglas Gregor70c23352010-12-09 21:44:02 +00005676 // Add all protocols.
5677 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5678 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005679
Douglas Gregor70c23352010-12-09 21:44:02 +00005680 Results.ExitScope();
5681 }
5682
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005683 HandleCodeCompleteResults(this, CodeCompleter,
5684 CodeCompletionContext::CCC_ObjCProtocolName,
5685 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005686}
5687
5688void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005689 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005690 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005691 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005692
Douglas Gregor70c23352010-12-09 21:44:02 +00005693 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5694 Results.EnterNewScope();
5695
5696 // Add all protocols.
5697 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5698 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005699
Douglas Gregor70c23352010-12-09 21:44:02 +00005700 Results.ExitScope();
5701 }
5702
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005703 HandleCodeCompleteResults(this, CodeCompleter,
5704 CodeCompletionContext::CCC_ObjCProtocolName,
5705 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005706}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005707
5708/// \brief Add all of the Objective-C interface declarations that we find in
5709/// the given (translation unit) context.
5710static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5711 bool OnlyForwardDeclarations,
5712 bool OnlyUnimplemented,
5713 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005714 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005715
5716 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5717 DEnd = Ctx->decls_end();
5718 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005719 // Record any interfaces we find.
5720 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005721 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005722 (!OnlyUnimplemented || !Class->getImplementation()))
5723 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005724 }
5725}
5726
5727void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005728 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005729 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005730 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005731 Results.EnterNewScope();
5732
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005733 if (CodeCompleter->includeGlobals()) {
5734 // Add all classes.
5735 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5736 false, Results);
5737 }
5738
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005739 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005740
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005741 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005742 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005743 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005744}
5745
Douglas Gregorc83c6872010-04-15 22:33:43 +00005746void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5747 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005748 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005749 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005750 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005751 Results.EnterNewScope();
5752
5753 // Make sure that we ignore the class we're currently defining.
5754 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005755 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005756 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005757 Results.Ignore(CurClass);
5758
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005759 if (CodeCompleter->includeGlobals()) {
5760 // Add all classes.
5761 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5762 false, Results);
5763 }
5764
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005765 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005766
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005767 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005768 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005769 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005770}
5771
5772void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005773 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005774 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005775 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005776 Results.EnterNewScope();
5777
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005778 if (CodeCompleter->includeGlobals()) {
5779 // Add all unimplemented classes.
5780 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5781 true, Results);
5782 }
5783
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005784 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005785
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005786 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005787 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005788 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005789}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005790
5791void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005792 IdentifierInfo *ClassName,
5793 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005794 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005795
Douglas Gregor218937c2011-02-01 19:23:04 +00005796 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005797 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005798 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005799
5800 // Ignore any categories we find that have already been implemented by this
5801 // interface.
5802 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5803 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005804 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005805 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5806 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5807 Category = Category->getNextClassCategory())
5808 CategoryNames.insert(Category->getIdentifier());
5809
5810 // Add all of the categories we know about.
5811 Results.EnterNewScope();
5812 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5813 for (DeclContext::decl_iterator D = TU->decls_begin(),
5814 DEnd = TU->decls_end();
5815 D != DEnd; ++D)
5816 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5817 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005818 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005819 Results.ExitScope();
5820
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005821 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005822 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005823 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005824}
5825
5826void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005827 IdentifierInfo *ClassName,
5828 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005829 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005830
5831 // Find the corresponding interface. If we couldn't find the interface, the
5832 // program itself is ill-formed. However, we'll try to be helpful still by
5833 // providing the list of all of the categories we know about.
5834 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005835 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005836 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5837 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005838 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005839
Douglas Gregor218937c2011-02-01 19:23:04 +00005840 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005841 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005842 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005843
5844 // Add all of the categories that have have corresponding interface
5845 // declarations in this class and any of its superclasses, except for
5846 // already-implemented categories in the class itself.
5847 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5848 Results.EnterNewScope();
5849 bool IgnoreImplemented = true;
5850 while (Class) {
5851 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5852 Category = Category->getNextClassCategory())
5853 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5854 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005855 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005856
5857 Class = Class->getSuperClass();
5858 IgnoreImplemented = false;
5859 }
5860 Results.ExitScope();
5861
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005862 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005863 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005864 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005865}
Douglas Gregor322328b2009-11-18 22:32:06 +00005866
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005867void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005868 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005869 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005870 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005871 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005872
5873 // Figure out where this @synthesize lives.
5874 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005875 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005876 if (!Container ||
5877 (!isa<ObjCImplementationDecl>(Container) &&
5878 !isa<ObjCCategoryImplDecl>(Container)))
5879 return;
5880
5881 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005882 Container = getContainerDef(Container);
5883 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005884 DEnd = Container->decls_end();
5885 D != DEnd; ++D)
5886 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5887 Results.Ignore(PropertyImpl->getPropertyDecl());
5888
5889 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005890 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005891 Results.EnterNewScope();
5892 if (ObjCImplementationDecl *ClassImpl
5893 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005894 AddObjCProperties(ClassImpl->getClassInterface(), false,
5895 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005896 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005897 else
5898 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005899 false, /*AllowNullaryMethods=*/false, CurContext,
5900 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005901 Results.ExitScope();
5902
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005903 HandleCodeCompleteResults(this, CodeCompleter,
5904 CodeCompletionContext::CCC_Other,
5905 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005906}
5907
5908void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005909 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005910 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005911 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005912 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005913 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005914
5915 // Figure out where this @synthesize lives.
5916 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005917 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005918 if (!Container ||
5919 (!isa<ObjCImplementationDecl>(Container) &&
5920 !isa<ObjCCategoryImplDecl>(Container)))
5921 return;
5922
5923 // Figure out which interface we're looking into.
5924 ObjCInterfaceDecl *Class = 0;
5925 if (ObjCImplementationDecl *ClassImpl
5926 = dyn_cast<ObjCImplementationDecl>(Container))
5927 Class = ClassImpl->getClassInterface();
5928 else
5929 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5930 ->getClassInterface();
5931
Douglas Gregore8426052011-04-18 14:40:46 +00005932 // Determine the type of the property we're synthesizing.
5933 QualType PropertyType = Context.getObjCIdType();
5934 if (Class) {
5935 if (ObjCPropertyDecl *Property
5936 = Class->FindPropertyDeclaration(PropertyName)) {
5937 PropertyType
5938 = Property->getType().getNonReferenceType().getUnqualifiedType();
5939
5940 // Give preference to ivars
5941 Results.setPreferredType(PropertyType);
5942 }
5943 }
5944
Douglas Gregor322328b2009-11-18 22:32:06 +00005945 // Add all of the instance variables in this class and its superclasses.
5946 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005947 bool SawSimilarlyNamedIvar = false;
5948 std::string NameWithPrefix;
5949 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005950 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005951 std::string NameWithSuffix = PropertyName->getName().str();
5952 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005953 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005954 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5955 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005956 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5957
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005958 // Determine whether we've seen an ivar with a name similar to the
5959 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005960 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005961 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00005962 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005963 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00005964
5965 // Reduce the priority of this result by one, to give it a slight
5966 // advantage over other results whose names don't match so closely.
5967 if (Results.size() &&
5968 Results.data()[Results.size() - 1].Kind
5969 == CodeCompletionResult::RK_Declaration &&
5970 Results.data()[Results.size() - 1].Declaration == Ivar)
5971 Results.data()[Results.size() - 1].Priority--;
5972 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005973 }
Douglas Gregor322328b2009-11-18 22:32:06 +00005974 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005975
5976 if (!SawSimilarlyNamedIvar) {
5977 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00005978 // an ivar of the appropriate type.
5979 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005980 typedef CodeCompletionResult Result;
5981 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005982 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
5983 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005984
Douglas Gregor8987b232011-09-27 23:30:47 +00005985 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00005986 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00005987 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005988 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
5989 Results.AddResult(Result(Builder.TakeString(), Priority,
5990 CXCursor_ObjCIvarDecl));
5991 }
5992
Douglas Gregor322328b2009-11-18 22:32:06 +00005993 Results.ExitScope();
5994
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005995 HandleCodeCompleteResults(this, CodeCompleter,
5996 CodeCompletionContext::CCC_Other,
5997 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005998}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005999
Douglas Gregor408be5a2010-08-25 01:08:01 +00006000// Mapping from selectors to the methods that implement that selector, along
6001// with the "in original class" flag.
6002typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
6003 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006004
6005/// \brief Find all of the methods that reside in the given container
6006/// (and its superclasses, protocols, etc.) that meet the given
6007/// criteria. Insert those methods into the map of known methods,
6008/// indexed by selector so they can be easily found.
6009static void FindImplementableMethods(ASTContext &Context,
6010 ObjCContainerDecl *Container,
6011 bool WantInstanceMethods,
6012 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006013 KnownMethodsMap &KnownMethods,
6014 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006015 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006016 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006017 if (!IFace->hasDefinition())
6018 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006019
6020 IFace = IFace->getDefinition();
6021 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006022
Douglas Gregore8f5a172010-04-07 00:21:17 +00006023 const ObjCList<ObjCProtocolDecl> &Protocols
6024 = IFace->getReferencedProtocols();
6025 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006026 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006027 I != E; ++I)
6028 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006029 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006030
Douglas Gregorea766182010-10-18 18:21:28 +00006031 // Add methods from any class extensions and categories.
6032 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
6033 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00006034 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
6035 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006036 KnownMethods, false);
6037
6038 // Visit the superclass.
6039 if (IFace->getSuperClass())
6040 FindImplementableMethods(Context, IFace->getSuperClass(),
6041 WantInstanceMethods, ReturnType,
6042 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006043 }
6044
6045 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6046 // Recurse into protocols.
6047 const ObjCList<ObjCProtocolDecl> &Protocols
6048 = Category->getReferencedProtocols();
6049 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006050 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006051 I != E; ++I)
6052 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006053 KnownMethods, InOriginalClass);
6054
6055 // If this category is the original class, jump to the interface.
6056 if (InOriginalClass && Category->getClassInterface())
6057 FindImplementableMethods(Context, Category->getClassInterface(),
6058 WantInstanceMethods, ReturnType, KnownMethods,
6059 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006060 }
6061
6062 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006063 // Make sure we have a definition; that's what we'll walk.
6064 if (!Protocol->hasDefinition())
6065 return;
6066 Protocol = Protocol->getDefinition();
6067 Container = Protocol;
6068
6069 // Recurse into protocols.
6070 const ObjCList<ObjCProtocolDecl> &Protocols
6071 = Protocol->getReferencedProtocols();
6072 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6073 E = Protocols.end();
6074 I != E; ++I)
6075 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6076 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006077 }
6078
6079 // Add methods in this container. This operation occurs last because
6080 // we want the methods from this container to override any methods
6081 // we've previously seen with the same selector.
6082 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6083 MEnd = Container->meth_end();
6084 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006085 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006086 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006087 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006088 continue;
6089
David Blaikie581deb32012-06-06 20:45:41 +00006090 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006091 }
6092 }
6093}
6094
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006095/// \brief Add the parenthesized return or parameter type chunk to a code
6096/// completion string.
6097static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006098 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006099 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006100 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006101 CodeCompletionBuilder &Builder) {
6102 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006103 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6104 if (!Quals.empty())
6105 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006106 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006107 Builder.getAllocator()));
6108 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6109}
6110
6111/// \brief Determine whether the given class is or inherits from a class by
6112/// the given name.
6113static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006114 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006115 if (!Class)
6116 return false;
6117
6118 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6119 return true;
6120
6121 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6122}
6123
6124/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6125/// Key-Value Observing (KVO).
6126static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6127 bool IsInstanceMethod,
6128 QualType ReturnType,
6129 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006130 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006131 ResultBuilder &Results) {
6132 IdentifierInfo *PropName = Property->getIdentifier();
6133 if (!PropName || PropName->getLength() == 0)
6134 return;
6135
Douglas Gregor8987b232011-09-27 23:30:47 +00006136 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6137
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006138 // Builder that will create each code completion.
6139 typedef CodeCompletionResult Result;
6140 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006141 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006142
6143 // The selector table.
6144 SelectorTable &Selectors = Context.Selectors;
6145
6146 // The property name, copied into the code completion allocation region
6147 // on demand.
6148 struct KeyHolder {
6149 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006150 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006151 const char *CopiedKey;
6152
Chris Lattner5f9e2722011-07-23 10:55:15 +00006153 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006154 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6155
6156 operator const char *() {
6157 if (CopiedKey)
6158 return CopiedKey;
6159
6160 return CopiedKey = Allocator.CopyString(Key);
6161 }
6162 } Key(Allocator, PropName->getName());
6163
6164 // The uppercased name of the property name.
6165 std::string UpperKey = PropName->getName();
6166 if (!UpperKey.empty())
6167 UpperKey[0] = toupper(UpperKey[0]);
6168
6169 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6170 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6171 Property->getType());
6172 bool ReturnTypeMatchesVoid
6173 = ReturnType.isNull() || ReturnType->isVoidType();
6174
6175 // Add the normal accessor -(type)key.
6176 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006177 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006178 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6179 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006180 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6181 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006182
6183 Builder.AddTypedTextChunk(Key);
6184 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6185 CXCursor_ObjCInstanceMethodDecl));
6186 }
6187
6188 // If we have an integral or boolean property (or the user has provided
6189 // an integral or boolean return type), add the accessor -(type)isKey.
6190 if (IsInstanceMethod &&
6191 ((!ReturnType.isNull() &&
6192 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6193 (ReturnType.isNull() &&
6194 (Property->getType()->isIntegerType() ||
6195 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006196 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006197 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006198 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006199 if (ReturnType.isNull()) {
6200 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6201 Builder.AddTextChunk("BOOL");
6202 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6203 }
6204
6205 Builder.AddTypedTextChunk(
6206 Allocator.CopyString(SelectorId->getName()));
6207 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6208 CXCursor_ObjCInstanceMethodDecl));
6209 }
6210 }
6211
6212 // Add the normal mutator.
6213 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6214 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006215 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006216 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006217 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006218 if (ReturnType.isNull()) {
6219 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6220 Builder.AddTextChunk("void");
6221 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6222 }
6223
6224 Builder.AddTypedTextChunk(
6225 Allocator.CopyString(SelectorId->getName()));
6226 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006227 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6228 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006229 Builder.AddTextChunk(Key);
6230 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6231 CXCursor_ObjCInstanceMethodDecl));
6232 }
6233 }
6234
6235 // Indexed and unordered accessors
6236 unsigned IndexedGetterPriority = CCP_CodePattern;
6237 unsigned IndexedSetterPriority = CCP_CodePattern;
6238 unsigned UnorderedGetterPriority = CCP_CodePattern;
6239 unsigned UnorderedSetterPriority = CCP_CodePattern;
6240 if (const ObjCObjectPointerType *ObjCPointer
6241 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6242 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6243 // If this interface type is not provably derived from a known
6244 // collection, penalize the corresponding completions.
6245 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6246 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6247 if (!InheritsFromClassNamed(IFace, "NSArray"))
6248 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6249 }
6250
6251 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6252 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6253 if (!InheritsFromClassNamed(IFace, "NSSet"))
6254 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6255 }
6256 }
6257 } else {
6258 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6259 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6260 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6261 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6262 }
6263
6264 // Add -(NSUInteger)countOf<key>
6265 if (IsInstanceMethod &&
6266 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006267 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006268 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006269 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006270 if (ReturnType.isNull()) {
6271 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6272 Builder.AddTextChunk("NSUInteger");
6273 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6274 }
6275
6276 Builder.AddTypedTextChunk(
6277 Allocator.CopyString(SelectorId->getName()));
6278 Results.AddResult(Result(Builder.TakeString(),
6279 std::min(IndexedGetterPriority,
6280 UnorderedGetterPriority),
6281 CXCursor_ObjCInstanceMethodDecl));
6282 }
6283 }
6284
6285 // Indexed getters
6286 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6287 if (IsInstanceMethod &&
6288 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006289 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006290 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006291 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006292 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006293 if (ReturnType.isNull()) {
6294 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6295 Builder.AddTextChunk("id");
6296 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6297 }
6298
6299 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6300 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6301 Builder.AddTextChunk("NSUInteger");
6302 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6303 Builder.AddTextChunk("index");
6304 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6305 CXCursor_ObjCInstanceMethodDecl));
6306 }
6307 }
6308
6309 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6310 if (IsInstanceMethod &&
6311 (ReturnType.isNull() ||
6312 (ReturnType->isObjCObjectPointerType() &&
6313 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6314 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6315 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006316 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006317 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006318 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006319 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006320 if (ReturnType.isNull()) {
6321 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6322 Builder.AddTextChunk("NSArray *");
6323 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6324 }
6325
6326 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6327 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6328 Builder.AddTextChunk("NSIndexSet *");
6329 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6330 Builder.AddTextChunk("indexes");
6331 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6332 CXCursor_ObjCInstanceMethodDecl));
6333 }
6334 }
6335
6336 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6337 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006338 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006339 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006340 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006341 &Context.Idents.get("range")
6342 };
6343
Douglas Gregore74c25c2011-05-04 23:50:46 +00006344 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006345 if (ReturnType.isNull()) {
6346 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6347 Builder.AddTextChunk("void");
6348 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6349 }
6350
6351 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6352 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6353 Builder.AddPlaceholderChunk("object-type");
6354 Builder.AddTextChunk(" **");
6355 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6356 Builder.AddTextChunk("buffer");
6357 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6358 Builder.AddTypedTextChunk("range:");
6359 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6360 Builder.AddTextChunk("NSRange");
6361 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6362 Builder.AddTextChunk("inRange");
6363 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6364 CXCursor_ObjCInstanceMethodDecl));
6365 }
6366 }
6367
6368 // Mutable indexed accessors
6369
6370 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6371 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006372 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006373 IdentifierInfo *SelectorIds[2] = {
6374 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006375 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006376 };
6377
Douglas Gregore74c25c2011-05-04 23:50:46 +00006378 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006379 if (ReturnType.isNull()) {
6380 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6381 Builder.AddTextChunk("void");
6382 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6383 }
6384
6385 Builder.AddTypedTextChunk("insertObject:");
6386 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6387 Builder.AddPlaceholderChunk("object-type");
6388 Builder.AddTextChunk(" *");
6389 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6390 Builder.AddTextChunk("object");
6391 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6392 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6393 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6394 Builder.AddPlaceholderChunk("NSUInteger");
6395 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6396 Builder.AddTextChunk("index");
6397 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6398 CXCursor_ObjCInstanceMethodDecl));
6399 }
6400 }
6401
6402 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6403 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006404 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006405 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006406 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006407 &Context.Idents.get("atIndexes")
6408 };
6409
Douglas Gregore74c25c2011-05-04 23:50:46 +00006410 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006411 if (ReturnType.isNull()) {
6412 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6413 Builder.AddTextChunk("void");
6414 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6415 }
6416
6417 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6418 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6419 Builder.AddTextChunk("NSArray *");
6420 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6421 Builder.AddTextChunk("array");
6422 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6423 Builder.AddTypedTextChunk("atIndexes:");
6424 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6425 Builder.AddPlaceholderChunk("NSIndexSet *");
6426 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6427 Builder.AddTextChunk("indexes");
6428 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6429 CXCursor_ObjCInstanceMethodDecl));
6430 }
6431 }
6432
6433 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6434 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006435 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006436 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006437 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006438 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006439 if (ReturnType.isNull()) {
6440 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6441 Builder.AddTextChunk("void");
6442 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6443 }
6444
6445 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6446 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6447 Builder.AddTextChunk("NSUInteger");
6448 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6449 Builder.AddTextChunk("index");
6450 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6451 CXCursor_ObjCInstanceMethodDecl));
6452 }
6453 }
6454
6455 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6456 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006457 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006458 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006459 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006460 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006461 if (ReturnType.isNull()) {
6462 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6463 Builder.AddTextChunk("void");
6464 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6465 }
6466
6467 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6468 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6469 Builder.AddTextChunk("NSIndexSet *");
6470 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6471 Builder.AddTextChunk("indexes");
6472 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6473 CXCursor_ObjCInstanceMethodDecl));
6474 }
6475 }
6476
6477 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6478 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006479 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006480 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006481 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006482 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006483 &Context.Idents.get("withObject")
6484 };
6485
Douglas Gregore74c25c2011-05-04 23:50:46 +00006486 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006487 if (ReturnType.isNull()) {
6488 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6489 Builder.AddTextChunk("void");
6490 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6491 }
6492
6493 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6494 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6495 Builder.AddPlaceholderChunk("NSUInteger");
6496 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6497 Builder.AddTextChunk("index");
6498 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6499 Builder.AddTypedTextChunk("withObject:");
6500 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6501 Builder.AddTextChunk("id");
6502 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6503 Builder.AddTextChunk("object");
6504 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6505 CXCursor_ObjCInstanceMethodDecl));
6506 }
6507 }
6508
6509 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6510 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006511 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006512 = (Twine("replace") + UpperKey + "AtIndexes").str();
6513 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006514 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006515 &Context.Idents.get(SelectorName1),
6516 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006517 };
6518
Douglas Gregore74c25c2011-05-04 23:50:46 +00006519 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006520 if (ReturnType.isNull()) {
6521 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6522 Builder.AddTextChunk("void");
6523 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6524 }
6525
6526 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6527 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6528 Builder.AddPlaceholderChunk("NSIndexSet *");
6529 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6530 Builder.AddTextChunk("indexes");
6531 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6532 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6533 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6534 Builder.AddTextChunk("NSArray *");
6535 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6536 Builder.AddTextChunk("array");
6537 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6538 CXCursor_ObjCInstanceMethodDecl));
6539 }
6540 }
6541
6542 // Unordered getters
6543 // - (NSEnumerator *)enumeratorOfKey
6544 if (IsInstanceMethod &&
6545 (ReturnType.isNull() ||
6546 (ReturnType->isObjCObjectPointerType() &&
6547 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6548 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6549 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006550 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006551 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006552 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006553 if (ReturnType.isNull()) {
6554 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6555 Builder.AddTextChunk("NSEnumerator *");
6556 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6557 }
6558
6559 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6560 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6561 CXCursor_ObjCInstanceMethodDecl));
6562 }
6563 }
6564
6565 // - (type *)memberOfKey:(type *)object
6566 if (IsInstanceMethod &&
6567 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006568 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006569 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006570 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006571 if (ReturnType.isNull()) {
6572 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6573 Builder.AddPlaceholderChunk("object-type");
6574 Builder.AddTextChunk(" *");
6575 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6576 }
6577
6578 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6579 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6580 if (ReturnType.isNull()) {
6581 Builder.AddPlaceholderChunk("object-type");
6582 Builder.AddTextChunk(" *");
6583 } else {
6584 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006585 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006586 Builder.getAllocator()));
6587 }
6588 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6589 Builder.AddTextChunk("object");
6590 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6591 CXCursor_ObjCInstanceMethodDecl));
6592 }
6593 }
6594
6595 // Mutable unordered accessors
6596 // - (void)addKeyObject:(type *)object
6597 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006598 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006599 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006600 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006601 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006602 if (ReturnType.isNull()) {
6603 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6604 Builder.AddTextChunk("void");
6605 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6606 }
6607
6608 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6609 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6610 Builder.AddPlaceholderChunk("object-type");
6611 Builder.AddTextChunk(" *");
6612 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6613 Builder.AddTextChunk("object");
6614 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6615 CXCursor_ObjCInstanceMethodDecl));
6616 }
6617 }
6618
6619 // - (void)addKey:(NSSet *)objects
6620 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006621 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006622 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006623 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006624 if (ReturnType.isNull()) {
6625 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6626 Builder.AddTextChunk("void");
6627 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6628 }
6629
6630 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6631 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6632 Builder.AddTextChunk("NSSet *");
6633 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6634 Builder.AddTextChunk("objects");
6635 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6636 CXCursor_ObjCInstanceMethodDecl));
6637 }
6638 }
6639
6640 // - (void)removeKeyObject:(type *)object
6641 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006642 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006643 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006644 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006645 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006646 if (ReturnType.isNull()) {
6647 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6648 Builder.AddTextChunk("void");
6649 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6650 }
6651
6652 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6653 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6654 Builder.AddPlaceholderChunk("object-type");
6655 Builder.AddTextChunk(" *");
6656 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6657 Builder.AddTextChunk("object");
6658 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6659 CXCursor_ObjCInstanceMethodDecl));
6660 }
6661 }
6662
6663 // - (void)removeKey:(NSSet *)objects
6664 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006665 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006666 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006667 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006668 if (ReturnType.isNull()) {
6669 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6670 Builder.AddTextChunk("void");
6671 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6672 }
6673
6674 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6675 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6676 Builder.AddTextChunk("NSSet *");
6677 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6678 Builder.AddTextChunk("objects");
6679 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6680 CXCursor_ObjCInstanceMethodDecl));
6681 }
6682 }
6683
6684 // - (void)intersectKey:(NSSet *)objects
6685 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006686 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006687 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006688 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006689 if (ReturnType.isNull()) {
6690 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6691 Builder.AddTextChunk("void");
6692 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6693 }
6694
6695 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6696 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6697 Builder.AddTextChunk("NSSet *");
6698 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6699 Builder.AddTextChunk("objects");
6700 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6701 CXCursor_ObjCInstanceMethodDecl));
6702 }
6703 }
6704
6705 // Key-Value Observing
6706 // + (NSSet *)keyPathsForValuesAffectingKey
6707 if (!IsInstanceMethod &&
6708 (ReturnType.isNull() ||
6709 (ReturnType->isObjCObjectPointerType() &&
6710 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6711 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6712 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006713 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006714 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006715 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006716 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006717 if (ReturnType.isNull()) {
6718 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6719 Builder.AddTextChunk("NSSet *");
6720 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6721 }
6722
6723 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6724 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006725 CXCursor_ObjCClassMethodDecl));
6726 }
6727 }
6728
6729 // + (BOOL)automaticallyNotifiesObserversForKey
6730 if (!IsInstanceMethod &&
6731 (ReturnType.isNull() ||
6732 ReturnType->isIntegerType() ||
6733 ReturnType->isBooleanType())) {
6734 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006735 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006736 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6737 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6738 if (ReturnType.isNull()) {
6739 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6740 Builder.AddTextChunk("BOOL");
6741 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6742 }
6743
6744 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6745 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6746 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006747 }
6748 }
6749}
6750
Douglas Gregore8f5a172010-04-07 00:21:17 +00006751void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6752 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006753 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006754 // Determine the return type of the method we're declaring, if
6755 // provided.
6756 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006757 Decl *IDecl = 0;
6758 if (CurContext->isObjCContainer()) {
6759 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6760 IDecl = cast<Decl>(OCD);
6761 }
Douglas Gregorea766182010-10-18 18:21:28 +00006762 // Determine where we should start searching for methods.
6763 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006764 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006765 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006766 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6767 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006768 IsInImplementation = true;
6769 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006770 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006771 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006772 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006773 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006774 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006775 }
6776
6777 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006778 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006779 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006780 }
6781
Douglas Gregorea766182010-10-18 18:21:28 +00006782 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006783 HandleCodeCompleteResults(this, CodeCompleter,
6784 CodeCompletionContext::CCC_Other,
6785 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006786 return;
6787 }
6788
6789 // Find all of the methods that we could declare/implement here.
6790 KnownMethodsMap KnownMethods;
6791 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006792 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006793
Douglas Gregore8f5a172010-04-07 00:21:17 +00006794 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006795 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006796 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006797 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006798 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006799 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006800 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006801 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6802 MEnd = KnownMethods.end();
6803 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006804 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006805 CodeCompletionBuilder Builder(Results.getAllocator(),
6806 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006807
6808 // If the result type was not already provided, add it to the
6809 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006810 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006811 AddObjCPassingTypeChunk(Method->getResultType(),
6812 Method->getObjCDeclQualifier(),
6813 Context, Policy,
6814 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006815
6816 Selector Sel = Method->getSelector();
6817
6818 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006819 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006820 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006821
6822 // Add parameters to the pattern.
6823 unsigned I = 0;
6824 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6825 PEnd = Method->param_end();
6826 P != PEnd; (void)++P, ++I) {
6827 // Add the part of the selector name.
6828 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006829 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006830 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006831 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6832 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006833 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006834 } else
6835 break;
6836
6837 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006838 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6839 (*P)->getObjCDeclQualifier(),
6840 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006841 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006842
6843 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006844 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006845 }
6846
6847 if (Method->isVariadic()) {
6848 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006849 Builder.AddChunk(CodeCompletionString::CK_Comma);
6850 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006851 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006852
Douglas Gregor447107d2010-05-28 00:57:46 +00006853 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006854 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006855 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6856 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6857 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006858 if (!Method->getResultType()->isVoidType()) {
6859 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006860 Builder.AddTextChunk("return");
6861 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6862 Builder.AddPlaceholderChunk("expression");
6863 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006864 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006865 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006866
Douglas Gregor218937c2011-02-01 19:23:04 +00006867 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6868 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006869 }
6870
Douglas Gregor408be5a2010-08-25 01:08:01 +00006871 unsigned Priority = CCP_CodePattern;
6872 if (!M->second.second)
6873 Priority += CCD_InBaseClass;
6874
Douglas Gregorba103062012-03-27 23:34:16 +00006875 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006876 }
6877
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006878 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6879 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006880 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006881 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006882 Containers.push_back(SearchDecl);
6883
Douglas Gregore74c25c2011-05-04 23:50:46 +00006884 VisitedSelectorSet KnownSelectors;
6885 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6886 MEnd = KnownMethods.end();
6887 M != MEnd; ++M)
6888 KnownSelectors.insert(M->first);
6889
6890
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006891 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6892 if (!IFace)
6893 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6894 IFace = Category->getClassInterface();
6895
6896 if (IFace) {
6897 for (ObjCCategoryDecl *Category = IFace->getCategoryList(); Category;
6898 Category = Category->getNextClassCategory())
6899 Containers.push_back(Category);
6900 }
6901
6902 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6903 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6904 PEnd = Containers[I]->prop_end();
6905 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00006906 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006907 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006908 }
6909 }
6910 }
6911
Douglas Gregore8f5a172010-04-07 00:21:17 +00006912 Results.ExitScope();
6913
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006914 HandleCodeCompleteResults(this, CodeCompleter,
6915 CodeCompletionContext::CCC_Other,
6916 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006917}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006918
6919void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6920 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006921 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006922 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006923 IdentifierInfo **SelIdents,
6924 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006925 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006926 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006927 if (ExternalSource) {
6928 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6929 I != N; ++I) {
6930 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006931 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006932 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006933
6934 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006935 }
6936 }
6937
6938 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006939 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006940 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006941 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006942 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006943
6944 if (ReturnTy)
6945 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006946
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006947 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006948 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6949 MEnd = MethodPool.end();
6950 M != MEnd; ++M) {
6951 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6952 &M->second.second;
6953 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006954 MethList = MethList->Next) {
6955 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6956 NumSelIdents))
6957 continue;
6958
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006959 if (AtParameterName) {
6960 // Suggest parameter names we've seen before.
6961 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
6962 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
6963 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006964 CodeCompletionBuilder Builder(Results.getAllocator(),
6965 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00006966 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00006967 Param->getIdentifier()->getName()));
6968 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006969 }
6970 }
6971
6972 continue;
6973 }
6974
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006975 Result R(MethList->Method, 0);
6976 R.StartParameter = NumSelIdents;
6977 R.AllParametersAreInformative = false;
6978 R.DeclaringEntity = true;
6979 Results.MaybeAddResult(R, CurContext);
6980 }
6981 }
6982
6983 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006984 HandleCodeCompleteResults(this, CodeCompleter,
6985 CodeCompletionContext::CCC_Other,
6986 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006987}
Douglas Gregor87c08a52010-08-13 22:48:40 +00006988
Douglas Gregorf29c5232010-08-24 22:20:20 +00006989void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006990 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006991 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00006992 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00006993 Results.EnterNewScope();
6994
6995 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006996 CodeCompletionBuilder Builder(Results.getAllocator(),
6997 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00006998 Builder.AddTypedTextChunk("if");
6999 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7000 Builder.AddPlaceholderChunk("condition");
7001 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007002
7003 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007004 Builder.AddTypedTextChunk("ifdef");
7005 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7006 Builder.AddPlaceholderChunk("macro");
7007 Results.AddResult(Builder.TakeString());
7008
Douglas Gregorf44e8542010-08-24 19:08:16 +00007009 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007010 Builder.AddTypedTextChunk("ifndef");
7011 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7012 Builder.AddPlaceholderChunk("macro");
7013 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007014
7015 if (InConditional) {
7016 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007017 Builder.AddTypedTextChunk("elif");
7018 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7019 Builder.AddPlaceholderChunk("condition");
7020 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007021
7022 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007023 Builder.AddTypedTextChunk("else");
7024 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007025
7026 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007027 Builder.AddTypedTextChunk("endif");
7028 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007029 }
7030
7031 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007032 Builder.AddTypedTextChunk("include");
7033 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7034 Builder.AddTextChunk("\"");
7035 Builder.AddPlaceholderChunk("header");
7036 Builder.AddTextChunk("\"");
7037 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007038
7039 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007040 Builder.AddTypedTextChunk("include");
7041 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7042 Builder.AddTextChunk("<");
7043 Builder.AddPlaceholderChunk("header");
7044 Builder.AddTextChunk(">");
7045 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007046
7047 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007048 Builder.AddTypedTextChunk("define");
7049 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7050 Builder.AddPlaceholderChunk("macro");
7051 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007052
7053 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007054 Builder.AddTypedTextChunk("define");
7055 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7056 Builder.AddPlaceholderChunk("macro");
7057 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7058 Builder.AddPlaceholderChunk("args");
7059 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7060 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007061
7062 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007063 Builder.AddTypedTextChunk("undef");
7064 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7065 Builder.AddPlaceholderChunk("macro");
7066 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007067
7068 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007069 Builder.AddTypedTextChunk("line");
7070 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7071 Builder.AddPlaceholderChunk("number");
7072 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007073
7074 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007075 Builder.AddTypedTextChunk("line");
7076 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7077 Builder.AddPlaceholderChunk("number");
7078 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7079 Builder.AddTextChunk("\"");
7080 Builder.AddPlaceholderChunk("filename");
7081 Builder.AddTextChunk("\"");
7082 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007083
7084 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007085 Builder.AddTypedTextChunk("error");
7086 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7087 Builder.AddPlaceholderChunk("message");
7088 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007089
7090 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007091 Builder.AddTypedTextChunk("pragma");
7092 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7093 Builder.AddPlaceholderChunk("arguments");
7094 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007095
David Blaikie4e4d0842012-03-11 07:00:24 +00007096 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007097 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007098 Builder.AddTypedTextChunk("import");
7099 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7100 Builder.AddTextChunk("\"");
7101 Builder.AddPlaceholderChunk("header");
7102 Builder.AddTextChunk("\"");
7103 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007104
7105 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007106 Builder.AddTypedTextChunk("import");
7107 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7108 Builder.AddTextChunk("<");
7109 Builder.AddPlaceholderChunk("header");
7110 Builder.AddTextChunk(">");
7111 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007112 }
7113
7114 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007115 Builder.AddTypedTextChunk("include_next");
7116 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7117 Builder.AddTextChunk("\"");
7118 Builder.AddPlaceholderChunk("header");
7119 Builder.AddTextChunk("\"");
7120 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007121
7122 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007123 Builder.AddTypedTextChunk("include_next");
7124 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7125 Builder.AddTextChunk("<");
7126 Builder.AddPlaceholderChunk("header");
7127 Builder.AddTextChunk(">");
7128 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007129
7130 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007131 Builder.AddTypedTextChunk("warning");
7132 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7133 Builder.AddPlaceholderChunk("message");
7134 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007135
7136 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7137 // completions for them. And __include_macros is a Clang-internal extension
7138 // that we don't want to encourage anyone to use.
7139
7140 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7141 Results.ExitScope();
7142
Douglas Gregorf44e8542010-08-24 19:08:16 +00007143 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007144 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007145 Results.data(), Results.size());
7146}
7147
7148void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007149 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007150 S->getFnParent()? Sema::PCC_RecoveryInFunction
7151 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007152}
7153
Douglas Gregorf29c5232010-08-24 22:20:20 +00007154void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007155 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007156 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007157 IsDefinition? CodeCompletionContext::CCC_MacroName
7158 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007159 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7160 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007161 CodeCompletionBuilder Builder(Results.getAllocator(),
7162 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007163 Results.EnterNewScope();
7164 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7165 MEnd = PP.macro_end();
7166 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007167 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007168 M->first->getName()));
7169 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007170 }
7171 Results.ExitScope();
7172 } else if (IsDefinition) {
7173 // FIXME: Can we detect when the user just wrote an include guard above?
7174 }
7175
Douglas Gregor52779fb2010-09-23 23:01:17 +00007176 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007177 Results.data(), Results.size());
7178}
7179
Douglas Gregorf29c5232010-08-24 22:20:20 +00007180void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007181 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007182 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007183 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007184
7185 if (!CodeCompleter || CodeCompleter->includeMacros())
7186 AddMacroResults(PP, Results);
7187
7188 // defined (<macro>)
7189 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007190 CodeCompletionBuilder Builder(Results.getAllocator(),
7191 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007192 Builder.AddTypedTextChunk("defined");
7193 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7194 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7195 Builder.AddPlaceholderChunk("macro");
7196 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7197 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007198 Results.ExitScope();
7199
7200 HandleCodeCompleteResults(this, CodeCompleter,
7201 CodeCompletionContext::CCC_PreprocessorExpression,
7202 Results.data(), Results.size());
7203}
7204
7205void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7206 IdentifierInfo *Macro,
7207 MacroInfo *MacroInfo,
7208 unsigned Argument) {
7209 // FIXME: In the future, we could provide "overload" results, much like we
7210 // do for function calls.
7211
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007212 // Now just ignore this. There will be another code-completion callback
7213 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007214}
7215
Douglas Gregor55817af2010-08-25 17:04:25 +00007216void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007217 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007218 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007219 0, 0);
7220}
7221
Douglas Gregordae68752011-02-01 22:57:45 +00007222void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007223 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007224 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007225 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7226 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007227 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7228 CodeCompletionDeclConsumer Consumer(Builder,
7229 Context.getTranslationUnitDecl());
7230 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7231 Consumer);
7232 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007233
7234 if (!CodeCompleter || CodeCompleter->includeMacros())
7235 AddMacroResults(PP, Builder);
7236
7237 Results.clear();
7238 Results.insert(Results.end(),
7239 Builder.data(), Builder.data() + Builder.size());
7240}