blob: 0bd73f3c237ef906d2cbdbc086d1d11a851fdba8 [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"
John McCall7cd088e2010-08-24 07:21:54 +000014#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000015#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000016#include "clang/AST/ExprObjC.h"
Douglas Gregorc5b2e582012-01-29 18:15:03 +000017#include "clang/Lex/HeaderSearch.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000018#include "clang/Lex/MacroInfo.h"
19#include "clang/Lex/Preprocessor.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000020#include "clang/Sema/CodeCompleteConsumer.h"
21#include "clang/Sema/ExternalSemaSource.h"
22#include "clang/Sema/Lookup.h"
23#include "clang/Sema/Overload.h"
24#include "clang/Sema/Scope.h"
25#include "clang/Sema/ScopeInfo.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).
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000048 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +000049
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.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000059 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Douglas Gregor86d9a522009-09-21 16:56:56 +000060
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000061 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000062
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.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000071 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000072
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
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000080 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000081 if (DeclOrVector.isNull()) {
82 // 0 - > 1 elements: just set the single element information.
83 DeclOrVector = ND;
84 SingleDeclIndex = Index;
85 return;
86 }
87
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000088 if (const NamedDecl *PrevND =
89 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000090 // 1 -> 2 elements: create the vector of results and push in the
91 // existing declaration.
92 DeclIndexPairVector *Vec = new DeclIndexPairVector;
93 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
94 DeclOrVector = Vec;
95 }
96
97 // Add the new element to the end of the vector.
98 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
99 DeclIndexPair(ND, Index));
100 }
101
102 void Destroy() {
103 if (DeclIndexPairVector *Vec
104 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
105 delete Vec;
106 DeclOrVector = ((NamedDecl *)0);
107 }
108 }
109
110 // Iteration.
111 class iterator;
112 iterator begin() const;
113 iterator end() const;
114 };
115
Douglas Gregor86d9a522009-09-21 16:56:56 +0000116 /// \brief A mapping from declaration names to the declarations that have
117 /// this name within a particular scope and their index within the list of
118 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000119 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000120
121 /// \brief The semantic analysis object for which results are being
122 /// produced.
123 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000124
125 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000126 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000127
128 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000129
130 /// \brief If non-NULL, a filter function used to remove any code-completion
131 /// results that are not desirable.
132 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000133
134 /// \brief Whether we should allow declarations as
135 /// nested-name-specifiers that would otherwise be filtered out.
136 bool AllowNestedNameSpecifiers;
137
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000138 /// \brief If set, the type that we would prefer our resulting value
139 /// declarations to have.
140 ///
141 /// Closely matching the preferred type gives a boost to a result's
142 /// priority.
143 CanQualType PreferredType;
144
Douglas Gregor86d9a522009-09-21 16:56:56 +0000145 /// \brief A list of shadow maps, which is used to model name hiding at
146 /// different levels of, e.g., the inheritance hierarchy.
147 std::list<ShadowMap> ShadowMaps;
148
Douglas Gregor3cdee122010-08-26 16:36:48 +0000149 /// \brief If we're potentially referring to a C++ member function, the set
150 /// of qualifiers applied to the object type.
151 Qualifiers ObjectTypeQualifiers;
152
153 /// \brief Whether the \p ObjectTypeQualifiers field is active.
154 bool HasObjectTypeQualifiers;
155
Douglas Gregor265f7492010-08-27 15:29:55 +0000156 /// \brief The selector that we prefer.
157 Selector PreferredSelector;
158
Douglas Gregorca45da02010-11-02 20:36:02 +0000159 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000160 CodeCompletionContext CompletionContext;
161
James Dennetta40f7922012-06-14 03:11:41 +0000162 /// \brief If we are in an instance method definition, the \@implementation
Douglas Gregorca45da02010-11-02 20:36:02 +0000163 /// object.
164 ObjCImplementationDecl *ObjCImplementation;
165
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000166 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000167
Douglas Gregor6f942b22010-09-21 16:06:22 +0000168 void MaybeAddConstructorResults(Result R);
169
Douglas Gregor86d9a522009-09-21 16:56:56 +0000170 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000171 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000172 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000173 const CodeCompletionContext &CompletionContext,
174 LookupFilter Filter = 0)
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000175 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
176 Filter(Filter),
Douglas Gregor218937c2011-02-01 19:23:04 +0000177 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000178 CompletionContext(CompletionContext),
179 ObjCImplementation(0)
180 {
181 // If this is an Objective-C instance method definition, dig out the
182 // corresponding implementation.
183 switch (CompletionContext.getKind()) {
184 case CodeCompletionContext::CCC_Expression:
185 case CodeCompletionContext::CCC_ObjCMessageReceiver:
186 case CodeCompletionContext::CCC_ParenthesizedExpression:
187 case CodeCompletionContext::CCC_Statement:
188 case CodeCompletionContext::CCC_Recovery:
189 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
190 if (Method->isInstanceMethod())
191 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
192 ObjCImplementation = Interface->getImplementation();
193 break;
194
195 default:
196 break;
197 }
198 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000199
Douglas Gregord8e8a582010-05-25 21:41:55 +0000200 /// \brief Whether we should include code patterns in the completion
201 /// results.
202 bool includeCodePatterns() const {
203 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000204 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000205 }
206
Douglas Gregor86d9a522009-09-21 16:56:56 +0000207 /// \brief Set the filter used for code-completion results.
208 void setFilter(LookupFilter Filter) {
209 this->Filter = Filter;
210 }
211
Douglas Gregor86d9a522009-09-21 16:56:56 +0000212 Result *data() { return Results.empty()? 0 : &Results.front(); }
213 unsigned size() const { return Results.size(); }
214 bool empty() const { return Results.empty(); }
215
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000216 /// \brief Specify the preferred type.
217 void setPreferredType(QualType T) {
218 PreferredType = SemaRef.Context.getCanonicalType(T);
219 }
220
Douglas Gregor3cdee122010-08-26 16:36:48 +0000221 /// \brief Set the cv-qualifiers on the object type, for us in filtering
222 /// calls to member functions.
223 ///
224 /// When there are qualifiers in this set, they will be used to filter
225 /// out member functions that aren't available (because there will be a
226 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
227 /// match.
228 void setObjectTypeQualifiers(Qualifiers Quals) {
229 ObjectTypeQualifiers = Quals;
230 HasObjectTypeQualifiers = true;
231 }
232
Douglas Gregor265f7492010-08-27 15:29:55 +0000233 /// \brief Set the preferred selector.
234 ///
235 /// When an Objective-C method declaration result is added, and that
236 /// method's selector matches this preferred selector, we give that method
237 /// a slight priority boost.
238 void setPreferredSelector(Selector Sel) {
239 PreferredSelector = Sel;
240 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000241
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000242 /// \brief Retrieve the code-completion context for which results are
243 /// being collected.
244 const CodeCompletionContext &getCompletionContext() const {
245 return CompletionContext;
246 }
247
Douglas Gregor45bcd432010-01-14 03:21:49 +0000248 /// \brief Specify whether nested-name-specifiers are allowed.
249 void allowNestedNameSpecifiers(bool Allow = true) {
250 AllowNestedNameSpecifiers = Allow;
251 }
252
Douglas Gregorb9d77572010-09-21 00:03:25 +0000253 /// \brief Return the semantic analysis object for which we are collecting
254 /// code completion results.
255 Sema &getSema() const { return SemaRef; }
256
Douglas Gregor218937c2011-02-01 19:23:04 +0000257 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000258 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000259
260 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000261
Douglas Gregore495b7f2010-01-14 00:20:49 +0000262 /// \brief Determine whether the given declaration is at all interesting
263 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000264 ///
265 /// \param ND the declaration that we are inspecting.
266 ///
267 /// \param AsNestedNameSpecifier will be set true if this declaration is
268 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000269 bool isInterestingDecl(const NamedDecl *ND,
270 bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000271
272 /// \brief Check whether the result is hidden by the Hiding declaration.
273 ///
274 /// \returns true if the result is hidden and cannot be found, false if
275 /// the hidden result could still be found. When false, \p R may be
276 /// modified to describe how the result can be found (e.g., via extra
277 /// qualification).
278 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000279 const NamedDecl *Hiding);
Douglas Gregor6660d842010-01-14 00:41:07 +0000280
Douglas Gregor86d9a522009-09-21 16:56:56 +0000281 /// \brief Add a new result to this result set (if it isn't already in one
282 /// of the shadow maps), or replace an existing result (for, e.g., a
283 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000284 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000285 /// \param R the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000286 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000287 /// \param CurContext the context in which this result will be named.
Douglas Gregor456c4a12009-09-21 20:12:40 +0000288 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000289
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000290 /// \brief Add a new result to this result set, where we already know
291 /// the hiding declation (if any).
292 ///
293 /// \param R the result to add (if it is unique).
294 ///
295 /// \param CurContext the context in which this result will be named.
296 ///
297 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000298 ///
299 /// \param InBaseClass whether the result was found in a base
300 /// class of the searched context.
301 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
302 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000303
Douglas Gregora4477812010-01-14 16:01:26 +0000304 /// \brief Add a new non-declaration result to this result set.
305 void AddResult(Result R);
306
Douglas Gregor86d9a522009-09-21 16:56:56 +0000307 /// \brief Enter into a new scope.
308 void EnterNewScope();
309
310 /// \brief Exit from the current scope.
311 void ExitScope();
312
Douglas Gregor55385fe2009-11-18 04:19:12 +0000313 /// \brief Ignore this declaration, if it is seen again.
314 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
315
Douglas Gregor86d9a522009-09-21 16:56:56 +0000316 /// \name Name lookup predicates
317 ///
318 /// These predicates can be passed to the name lookup functions to filter the
319 /// results of name lookup. All of the predicates have the same type, so that
320 ///
321 //@{
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000322 bool IsOrdinaryName(const NamedDecl *ND) const;
323 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
324 bool IsIntegralConstantValue(const NamedDecl *ND) const;
325 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
326 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
327 bool IsEnum(const NamedDecl *ND) const;
328 bool IsClassOrStruct(const NamedDecl *ND) const;
329 bool IsUnion(const NamedDecl *ND) const;
330 bool IsNamespace(const NamedDecl *ND) const;
331 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
332 bool IsType(const NamedDecl *ND) const;
333 bool IsMember(const NamedDecl *ND) const;
334 bool IsObjCIvar(const NamedDecl *ND) const;
335 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
336 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
337 bool IsObjCCollection(const NamedDecl *ND) const;
338 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000339 //@}
340 };
341}
342
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000343class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000344 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000345 unsigned SingleDeclIndex;
346
347public:
348 typedef DeclIndexPair value_type;
349 typedef value_type reference;
350 typedef std::ptrdiff_t difference_type;
351 typedef std::input_iterator_tag iterator_category;
352
353 class pointer {
354 DeclIndexPair Value;
355
356 public:
357 pointer(const DeclIndexPair &Value) : Value(Value) { }
358
359 const DeclIndexPair *operator->() const {
360 return &Value;
361 }
362 };
363
364 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
365
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000366 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000367 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
368
369 iterator(const DeclIndexPair *Iterator)
370 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
371
372 iterator &operator++() {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000373 if (DeclOrIterator.is<const NamedDecl *>()) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000374 DeclOrIterator = (NamedDecl *)0;
375 SingleDeclIndex = 0;
376 return *this;
377 }
378
379 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
380 ++I;
381 DeclOrIterator = I;
382 return *this;
383 }
384
Chris Lattner66392d42010-09-04 18:12:20 +0000385 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000386 iterator tmp(*this);
387 ++(*this);
388 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000389 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000390
391 reference operator*() const {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000392 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000393 return reference(ND, SingleDeclIndex);
394
Douglas Gregord490f952009-12-06 21:27:58 +0000395 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000396 }
397
398 pointer operator->() const {
399 return pointer(**this);
400 }
401
402 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000403 return X.DeclOrIterator.getOpaqueValue()
404 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000405 X.SingleDeclIndex == Y.SingleDeclIndex;
406 }
407
408 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000409 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000410 }
411};
412
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000413ResultBuilder::ShadowMapEntry::iterator
414ResultBuilder::ShadowMapEntry::begin() const {
415 if (DeclOrVector.isNull())
416 return iterator();
417
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000418 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000419 return iterator(ND, SingleDeclIndex);
420
421 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
422}
423
424ResultBuilder::ShadowMapEntry::iterator
425ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000426 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000427 return iterator();
428
429 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
430}
431
Douglas Gregor456c4a12009-09-21 20:12:40 +0000432/// \brief Compute the qualification required to get from the current context
433/// (\p CurContext) to the target context (\p TargetContext).
434///
435/// \param Context the AST context in which the qualification will be used.
436///
437/// \param CurContext the context where an entity is being named, which is
438/// typically based on the current scope.
439///
440/// \param TargetContext the context in which the named entity actually
441/// resides.
442///
443/// \returns a nested name specifier that refers into the target context, or
444/// NULL if no qualification is needed.
445static NestedNameSpecifier *
446getRequiredQualification(ASTContext &Context,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000447 const DeclContext *CurContext,
448 const DeclContext *TargetContext) {
449 SmallVector<const DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000450
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000451 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000452 CommonAncestor && !CommonAncestor->Encloses(CurContext);
453 CommonAncestor = CommonAncestor->getLookupParent()) {
454 if (CommonAncestor->isTransparentContext() ||
455 CommonAncestor->isFunctionOrMethod())
456 continue;
457
458 TargetParents.push_back(CommonAncestor);
459 }
460
461 NestedNameSpecifier *Result = 0;
462 while (!TargetParents.empty()) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000463 const DeclContext *Parent = TargetParents.back();
Douglas Gregor456c4a12009-09-21 20:12:40 +0000464 TargetParents.pop_back();
465
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000466 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregorfb629412010-08-23 21:17:50 +0000467 if (!Namespace->getIdentifier())
468 continue;
469
Douglas Gregor456c4a12009-09-21 20:12:40 +0000470 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000471 }
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000472 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor456c4a12009-09-21 20:12:40 +0000473 Result = NestedNameSpecifier::Create(Context, Result,
474 false,
475 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000476 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000477 return Result;
478}
479
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000480bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000481 bool &AsNestedNameSpecifier) const {
482 AsNestedNameSpecifier = false;
483
Douglas Gregore495b7f2010-01-14 00:20:49 +0000484 ND = ND->getUnderlyingDecl();
485 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000486
487 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000488 if (!ND->getDeclName())
489 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000490
491 // Friend declarations and declarations introduced due to friends are never
492 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000493 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000494 return false;
495
Douglas Gregor76282942009-12-11 17:31:05 +0000496 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000497 if (isa<ClassTemplateSpecializationDecl>(ND) ||
498 isa<ClassTemplatePartialSpecializationDecl>(ND))
499 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000500
Douglas Gregor76282942009-12-11 17:31:05 +0000501 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000502 if (isa<UsingDecl>(ND))
503 return false;
504
505 // Some declarations have reserved names that we don't want to ever show.
506 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000507 // __va_list_tag is a freak of nature. Find it and skip it.
508 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000509 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000510
Douglas Gregorf52cede2009-10-09 22:16:47 +0000511 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000512 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000513 //
514 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000515 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000516 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000517 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000518 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
519 (ND->getLocation().isInvalid() ||
520 SemaRef.SourceMgr.isInSystemHeader(
521 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000522 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000523 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000524 }
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000525
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000526 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
527 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
528 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000529 Filter != &ResultBuilder::IsNamespaceOrAlias &&
530 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000531 AsNestedNameSpecifier = true;
532
Douglas Gregor86d9a522009-09-21 16:56:56 +0000533 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000534 if (Filter && !(this->*Filter)(ND)) {
535 // Check whether it is interesting as a nested-name-specifier.
David Blaikie4e4d0842012-03-11 07:00:24 +0000536 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor45bcd432010-01-14 03:21:49 +0000537 IsNestedNameSpecifier(ND) &&
538 (Filter != &ResultBuilder::IsMember ||
539 (isa<CXXRecordDecl>(ND) &&
540 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
541 AsNestedNameSpecifier = true;
542 return true;
543 }
544
Douglas Gregore495b7f2010-01-14 00:20:49 +0000545 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000546 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000547 // ... then it must be interesting!
548 return true;
549}
550
Douglas Gregor6660d842010-01-14 00:41:07 +0000551bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000552 const NamedDecl *Hiding) {
Douglas Gregor6660d842010-01-14 00:41:07 +0000553 // In C, there is no way to refer to a hidden name.
554 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
555 // name if we introduce the tag type.
David Blaikie4e4d0842012-03-11 07:00:24 +0000556 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor6660d842010-01-14 00:41:07 +0000557 return true;
558
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000559 const DeclContext *HiddenCtx =
560 R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000561
562 // There is no way to qualify a name declared in a function or method.
563 if (HiddenCtx->isFunctionOrMethod())
564 return true;
565
Sebastian Redl7a126a42010-08-31 00:36:30 +0000566 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000567 return true;
568
569 // We can refer to the result with the appropriate qualification. Do it.
570 R.Hidden = true;
571 R.QualifierIsInformative = false;
572
573 if (!R.Qualifier)
574 R.Qualifier = getRequiredQualification(SemaRef.Context,
575 CurContext,
576 R.Declaration->getDeclContext());
577 return false;
578}
579
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000580/// \brief A simplified classification of types used to determine whether two
581/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000582SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000583 switch (T->getTypeClass()) {
584 case Type::Builtin:
585 switch (cast<BuiltinType>(T)->getKind()) {
586 case BuiltinType::Void:
587 return STC_Void;
588
589 case BuiltinType::NullPtr:
590 return STC_Pointer;
591
592 case BuiltinType::Overload:
593 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000594 return STC_Other;
595
596 case BuiltinType::ObjCId:
597 case BuiltinType::ObjCClass:
598 case BuiltinType::ObjCSel:
599 return STC_ObjectiveC;
600
601 default:
602 return STC_Arithmetic;
603 }
David Blaikie7530c032012-01-17 06:56:22 +0000604
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000605 case Type::Complex:
606 return STC_Arithmetic;
607
608 case Type::Pointer:
609 return STC_Pointer;
610
611 case Type::BlockPointer:
612 return STC_Block;
613
614 case Type::LValueReference:
615 case Type::RValueReference:
616 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
617
618 case Type::ConstantArray:
619 case Type::IncompleteArray:
620 case Type::VariableArray:
621 case Type::DependentSizedArray:
622 return STC_Array;
623
624 case Type::DependentSizedExtVector:
625 case Type::Vector:
626 case Type::ExtVector:
627 return STC_Arithmetic;
628
629 case Type::FunctionProto:
630 case Type::FunctionNoProto:
631 return STC_Function;
632
633 case Type::Record:
634 return STC_Record;
635
636 case Type::Enum:
637 return STC_Arithmetic;
638
639 case Type::ObjCObject:
640 case Type::ObjCInterface:
641 case Type::ObjCObjectPointer:
642 return STC_ObjectiveC;
643
644 default:
645 return STC_Other;
646 }
647}
648
649/// \brief Get the type that a given expression will have if this declaration
650/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000651QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000652 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
653
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000654 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000655 return C.getTypeDeclType(Type);
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000656 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000657 return C.getObjCInterfaceType(Iface);
658
659 QualType T;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000660 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000661 T = Function->getCallResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000662 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000663 T = Method->getSendResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000664 else if (const FunctionTemplateDecl *FunTmpl =
665 dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000666 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000667 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000668 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000669 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000670 T = Property->getType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000671 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000672 T = Value->getType();
673 else
674 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000675
676 // Dig through references, function pointers, and block pointers to
677 // get down to the likely type of an expression when the entity is
678 // used.
679 do {
680 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
681 T = Ref->getPointeeType();
682 continue;
683 }
684
685 if (const PointerType *Pointer = T->getAs<PointerType>()) {
686 if (Pointer->getPointeeType()->isFunctionType()) {
687 T = Pointer->getPointeeType();
688 continue;
689 }
690
691 break;
692 }
693
694 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
695 T = Block->getPointeeType();
696 continue;
697 }
698
699 if (const FunctionType *Function = T->getAs<FunctionType>()) {
700 T = Function->getResultType();
701 continue;
702 }
703
704 break;
705 } while (true);
706
707 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000708}
709
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000710void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
711 // If this is an Objective-C method declaration whose selector matches our
712 // preferred selector, give it a priority boost.
713 if (!PreferredSelector.isNull())
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000714 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000715 if (PreferredSelector == Method->getSelector())
716 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000717
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000718 // If we have a preferred type, adjust the priority for results with exactly-
719 // matching or nearly-matching types.
720 if (!PreferredType.isNull()) {
721 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
722 if (!T.isNull()) {
723 CanQualType TC = SemaRef.Context.getCanonicalType(T);
724 // Check for exactly-matching types (modulo qualifiers).
725 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
726 R.Priority /= CCF_ExactTypeMatch;
727 // Check for nearly-matching types, based on classification of each.
728 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000729 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000730 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
731 R.Priority /= CCF_SimilarTypeMatch;
732 }
733 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000734}
735
Douglas Gregor6f942b22010-09-21 16:06:22 +0000736void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000737 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor6f942b22010-09-21 16:06:22 +0000738 !CompletionContext.wantConstructorResults())
739 return;
740
741 ASTContext &Context = SemaRef.Context;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000742 const NamedDecl *D = R.Declaration;
743 const CXXRecordDecl *Record = 0;
744 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor6f942b22010-09-21 16:06:22 +0000745 Record = ClassTemplate->getTemplatedDecl();
746 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
747 // Skip specializations and partial specializations.
748 if (isa<ClassTemplateSpecializationDecl>(Record))
749 return;
750 } else {
751 // There are no constructors here.
752 return;
753 }
754
755 Record = Record->getDefinition();
756 if (!Record)
757 return;
758
759
760 QualType RecordTy = Context.getTypeDeclType(Record);
761 DeclarationName ConstructorName
762 = Context.DeclarationNames.getCXXConstructorName(
763 Context.getCanonicalType(RecordTy));
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000764 DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName);
765 for (DeclContext::lookup_const_iterator I = Ctors.begin(),
766 E = Ctors.end();
767 I != E; ++I) {
David Blaikie3bc93e32012-12-19 00:45:41 +0000768 R.Declaration = *I;
Douglas Gregor6f942b22010-09-21 16:06:22 +0000769 R.CursorKind = getCursorKindForDecl(R.Declaration);
770 Results.push_back(R);
771 }
772}
773
Douglas Gregore495b7f2010-01-14 00:20:49 +0000774void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
775 assert(!ShadowMaps.empty() && "Must enter into a results scope");
776
777 if (R.Kind != Result::RK_Declaration) {
778 // For non-declaration results, just add the result.
779 Results.push_back(R);
780 return;
781 }
782
783 // Look through using declarations.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000784 if (const UsingShadowDecl *Using =
785 dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregore495b7f2010-01-14 00:20:49 +0000786 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
787 return;
788 }
789
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000790 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregore495b7f2010-01-14 00:20:49 +0000791 unsigned IDNS = CanonDecl->getIdentifierNamespace();
792
Douglas Gregor45bcd432010-01-14 03:21:49 +0000793 bool AsNestedNameSpecifier = false;
794 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000795 return;
796
Douglas Gregor6f942b22010-09-21 16:06:22 +0000797 // C++ constructors are never found by name lookup.
798 if (isa<CXXConstructorDecl>(R.Declaration))
799 return;
800
Douglas Gregor86d9a522009-09-21 16:56:56 +0000801 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000802 ShadowMapEntry::iterator I, IEnd;
803 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
804 if (NamePos != SMap.end()) {
805 I = NamePos->second.begin();
806 IEnd = NamePos->second.end();
807 }
808
809 for (; I != IEnd; ++I) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000810 const NamedDecl *ND = I->first;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000811 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000812 if (ND->getCanonicalDecl() == CanonDecl) {
813 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000814 Results[Index].Declaration = R.Declaration;
815
Douglas Gregor86d9a522009-09-21 16:56:56 +0000816 // We're done.
817 return;
818 }
819 }
820
821 // This is a new declaration in this scope. However, check whether this
822 // declaration name is hidden by a similarly-named declaration in an outer
823 // scope.
824 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
825 --SMEnd;
826 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000827 ShadowMapEntry::iterator I, IEnd;
828 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
829 if (NamePos != SM->end()) {
830 I = NamePos->second.begin();
831 IEnd = NamePos->second.end();
832 }
833 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000834 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000835 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000836 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
837 Decl::IDNS_ObjCProtocol)))
838 continue;
839
840 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000841 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000842 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000843 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000844 continue;
845
846 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000847 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000848 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000849
850 break;
851 }
852 }
853
854 // Make sure that any given declaration only shows up in the result set once.
855 if (!AllDeclsFound.insert(CanonDecl))
856 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000857
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000858 // If the filter is for nested-name-specifiers, then this result starts a
859 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000860 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000861 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000862 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000863 } else
864 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000865
Douglas Gregor0563c262009-09-22 23:15:58 +0000866 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000867 if (R.QualifierIsInformative && !R.Qualifier &&
868 !R.StartsNestedNameSpecifier) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000869 const DeclContext *Ctx = R.Declaration->getDeclContext();
870 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Douglas Gregor0563c262009-09-22 23:15:58 +0000871 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000872 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Douglas Gregor0563c262009-09-22 23:15:58 +0000873 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
874 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
875 else
876 R.QualifierIsInformative = false;
877 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000878
Douglas Gregor86d9a522009-09-21 16:56:56 +0000879 // Insert this result into the set of results and into the current shadow
880 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000881 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000882 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000883
884 if (!AsNestedNameSpecifier)
885 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000886}
887
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000888void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000889 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000890 if (R.Kind != Result::RK_Declaration) {
891 // For non-declaration results, just add the result.
892 Results.push_back(R);
893 return;
894 }
895
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000896 // Look through using declarations.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000897 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000898 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
899 return;
900 }
901
Douglas Gregor45bcd432010-01-14 03:21:49 +0000902 bool AsNestedNameSpecifier = false;
903 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000904 return;
905
Douglas Gregor6f942b22010-09-21 16:06:22 +0000906 // C++ constructors are never found by name lookup.
907 if (isa<CXXConstructorDecl>(R.Declaration))
908 return;
909
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000910 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
911 return;
Nick Lewycky173a37a2012-04-03 21:44:08 +0000912
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000913 // Make sure that any given declaration only shows up in the result set once.
914 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
915 return;
916
917 // If the filter is for nested-name-specifiers, then this result starts a
918 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000919 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000920 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000921 R.Priority = CCP_NestedNameSpecifier;
922 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000923 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
924 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000925 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000926 R.QualifierIsInformative = true;
927
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000928 // If this result is supposed to have an informative qualifier, add one.
929 if (R.QualifierIsInformative && !R.Qualifier &&
930 !R.StartsNestedNameSpecifier) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000931 const DeclContext *Ctx = R.Declaration->getDeclContext();
932 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000933 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000934 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000935 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000936 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000937 else
938 R.QualifierIsInformative = false;
939 }
940
Douglas Gregor12e13132010-05-26 22:00:08 +0000941 // Adjust the priority if this result comes from a base class.
942 if (InBaseClass)
943 R.Priority += CCD_InBaseClass;
944
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000945 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000946
Douglas Gregor3cdee122010-08-26 16:36:48 +0000947 if (HasObjectTypeQualifiers)
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000948 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor3cdee122010-08-26 16:36:48 +0000949 if (Method->isInstance()) {
950 Qualifiers MethodQuals
951 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
952 if (ObjectTypeQualifiers == MethodQuals)
953 R.Priority += CCD_ObjectQualifierMatch;
954 else if (ObjectTypeQualifiers - MethodQuals) {
955 // The method cannot be invoked, because doing so would drop
956 // qualifiers.
957 return;
958 }
959 }
960
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000961 // Insert this result into the set of results.
962 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000963
964 if (!AsNestedNameSpecifier)
965 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000966}
967
Douglas Gregora4477812010-01-14 16:01:26 +0000968void ResultBuilder::AddResult(Result R) {
969 assert(R.Kind != Result::RK_Declaration &&
970 "Declaration results need more context");
971 Results.push_back(R);
972}
973
Douglas Gregor86d9a522009-09-21 16:56:56 +0000974/// \brief Enter into a new scope.
975void ResultBuilder::EnterNewScope() {
976 ShadowMaps.push_back(ShadowMap());
977}
978
979/// \brief Exit from the current scope.
980void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000981 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
982 EEnd = ShadowMaps.back().end();
983 E != EEnd;
984 ++E)
985 E->second.Destroy();
986
Douglas Gregor86d9a522009-09-21 16:56:56 +0000987 ShadowMaps.pop_back();
988}
989
Douglas Gregor791215b2009-09-21 20:51:25 +0000990/// \brief Determines whether this given declaration will be found by
991/// ordinary name lookup.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000992bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000993 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
994
Douglas Gregor791215b2009-09-21 20:51:25 +0000995 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +0000996 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000997 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +0000998 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +0000999 if (isa<ObjCIvarDecl>(ND))
1000 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001001 }
1002
Douglas Gregor791215b2009-09-21 20:51:25 +00001003 return ND->getIdentifierNamespace() & IDNS;
1004}
1005
Douglas Gregor01dfea02010-01-10 23:08:15 +00001006/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001007/// ordinary name lookup but is not a type name.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001008bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001009 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1010 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1011 return false;
1012
1013 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001014 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001015 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001016 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001017 if (isa<ObjCIvarDecl>(ND))
1018 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001019 }
1020
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001021 return ND->getIdentifierNamespace() & IDNS;
1022}
1023
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001024bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregorf9578432010-07-28 21:50:18 +00001025 if (!IsOrdinaryNonTypeName(ND))
1026 return 0;
1027
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001028 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregorf9578432010-07-28 21:50:18 +00001029 if (VD->getType()->isIntegralOrEnumerationType())
1030 return true;
1031
1032 return false;
1033}
1034
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001035/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001036/// ordinary name lookup.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001037bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001038 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1039
Douglas Gregor01dfea02010-01-10 23:08:15 +00001040 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001041 if (SemaRef.getLangOpts().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001042 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001043
1044 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001045 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1046 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001047}
1048
Douglas Gregor86d9a522009-09-21 16:56:56 +00001049/// \brief Determines whether the given declaration is suitable as the
1050/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001051bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001052 // Allow us to find class templates, too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001053 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor86d9a522009-09-21 16:56:56 +00001054 ND = ClassTemplate->getTemplatedDecl();
1055
1056 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1057}
1058
1059/// \brief Determines whether the given declaration is an enumeration.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001060bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001061 return isa<EnumDecl>(ND);
1062}
1063
1064/// \brief Determines whether the given declaration is a class or struct.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001065bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001066 // Allow us to find class templates, too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001067 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor86d9a522009-09-21 16:56:56 +00001068 ND = ClassTemplate->getTemplatedDecl();
Joao Matos6666ed42012-08-31 18:45:21 +00001069
1070 // For purposes of this check, interfaces match too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001071 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001072 return RD->getTagKind() == TTK_Class ||
Joao Matos6666ed42012-08-31 18:45:21 +00001073 RD->getTagKind() == TTK_Struct ||
1074 RD->getTagKind() == TTK_Interface;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001075
1076 return false;
1077}
1078
1079/// \brief Determines whether the given declaration is a union.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001080bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001081 // Allow us to find class templates, too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001082 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor86d9a522009-09-21 16:56:56 +00001083 ND = ClassTemplate->getTemplatedDecl();
1084
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001085 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001086 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001087
1088 return false;
1089}
1090
1091/// \brief Determines whether the given declaration is a namespace.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001092bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001093 return isa<NamespaceDecl>(ND);
1094}
1095
1096/// \brief Determines whether the given declaration is a namespace or
1097/// namespace alias.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001098bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001099 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1100}
1101
Douglas Gregor76282942009-12-11 17:31:05 +00001102/// \brief Determines whether the given declaration is a type.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001103bool ResultBuilder::IsType(const NamedDecl *ND) const {
1104 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
Douglas Gregord32b0222010-08-24 01:06:58 +00001105 ND = Using->getTargetDecl();
1106
1107 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001108}
1109
Douglas Gregor76282942009-12-11 17:31:05 +00001110/// \brief Determines which members of a class should be visible via
1111/// "." or "->". Only value declarations, nested name specifiers, and
1112/// using declarations thereof should show up.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001113bool ResultBuilder::IsMember(const NamedDecl *ND) const {
1114 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
Douglas Gregor76282942009-12-11 17:31:05 +00001115 ND = Using->getTargetDecl();
1116
Douglas Gregorce821962009-12-11 18:14:22 +00001117 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1118 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001119}
1120
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001121static bool isObjCReceiverType(ASTContext &C, QualType T) {
1122 T = C.getCanonicalType(T);
1123 switch (T->getTypeClass()) {
1124 case Type::ObjCObject:
1125 case Type::ObjCInterface:
1126 case Type::ObjCObjectPointer:
1127 return true;
1128
1129 case Type::Builtin:
1130 switch (cast<BuiltinType>(T)->getKind()) {
1131 case BuiltinType::ObjCId:
1132 case BuiltinType::ObjCClass:
1133 case BuiltinType::ObjCSel:
1134 return true;
1135
1136 default:
1137 break;
1138 }
1139 return false;
1140
1141 default:
1142 break;
1143 }
1144
David Blaikie4e4d0842012-03-11 07:00:24 +00001145 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001146 return false;
1147
1148 // FIXME: We could perform more analysis here to determine whether a
1149 // particular class type has any conversions to Objective-C types. For now,
1150 // just accept all class types.
1151 return T->isDependentType() || T->isRecordType();
1152}
1153
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001154bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001155 QualType T = getDeclUsageType(SemaRef.Context, ND);
1156 if (T.isNull())
1157 return false;
1158
1159 T = SemaRef.Context.getBaseElementType(T);
1160 return isObjCReceiverType(SemaRef.Context, T);
1161}
1162
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001163bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001164 if (IsObjCMessageReceiver(ND))
1165 return true;
1166
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001167 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001168 if (!Var)
1169 return false;
1170
1171 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1172}
1173
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001174bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001175 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1176 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001177 return false;
1178
1179 QualType T = getDeclUsageType(SemaRef.Context, ND);
1180 if (T.isNull())
1181 return false;
1182
1183 T = SemaRef.Context.getBaseElementType(T);
1184 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1185 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001186 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001187}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001188
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001189bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor52779fb2010-09-23 23:01:17 +00001190 return false;
1191}
1192
James Dennettde23c7e2012-06-17 05:33:25 +00001193/// \brief Determines whether the given declaration is an Objective-C
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001194/// instance variable.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001195bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001196 return isa<ObjCIvarDecl>(ND);
1197}
1198
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001199namespace {
1200 /// \brief Visible declaration consumer that adds a code-completion result
1201 /// for each visible declaration.
1202 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1203 ResultBuilder &Results;
1204 DeclContext *CurContext;
1205
1206 public:
1207 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1208 : Results(Results), CurContext(CurContext) { }
1209
Erik Verbruggend1205962011-10-06 07:27:49 +00001210 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1211 bool InBaseClass) {
1212 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001213 if (Ctx)
1214 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1215
Erik Verbruggend1205962011-10-06 07:27:49 +00001216 ResultBuilder::Result Result(ND, 0, false, Accessible);
1217 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001218 }
1219 };
1220}
1221
Douglas Gregor86d9a522009-09-21 16:56:56 +00001222/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001223static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001224 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001225 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001226 Results.AddResult(Result("short", CCP_Type));
1227 Results.AddResult(Result("long", CCP_Type));
1228 Results.AddResult(Result("signed", CCP_Type));
1229 Results.AddResult(Result("unsigned", CCP_Type));
1230 Results.AddResult(Result("void", CCP_Type));
1231 Results.AddResult(Result("char", CCP_Type));
1232 Results.AddResult(Result("int", CCP_Type));
1233 Results.AddResult(Result("float", CCP_Type));
1234 Results.AddResult(Result("double", CCP_Type));
1235 Results.AddResult(Result("enum", CCP_Type));
1236 Results.AddResult(Result("struct", CCP_Type));
1237 Results.AddResult(Result("union", CCP_Type));
1238 Results.AddResult(Result("const", CCP_Type));
1239 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001240
Douglas Gregor86d9a522009-09-21 16:56:56 +00001241 if (LangOpts.C99) {
1242 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001243 Results.AddResult(Result("_Complex", CCP_Type));
1244 Results.AddResult(Result("_Imaginary", CCP_Type));
1245 Results.AddResult(Result("_Bool", CCP_Type));
1246 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001247 }
1248
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001249 CodeCompletionBuilder Builder(Results.getAllocator(),
1250 Results.getCodeCompletionTUInfo());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001251 if (LangOpts.CPlusPlus) {
1252 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001253 Results.AddResult(Result("bool", CCP_Type +
1254 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001255 Results.AddResult(Result("class", CCP_Type));
1256 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001257
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001258 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001259 Builder.AddTypedTextChunk("typename");
1260 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1261 Builder.AddPlaceholderChunk("qualifier");
1262 Builder.AddTextChunk("::");
1263 Builder.AddPlaceholderChunk("name");
1264 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001265
Richard Smith80ad52f2013-01-02 11:42:31 +00001266 if (LangOpts.CPlusPlus11) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001267 Results.AddResult(Result("auto", CCP_Type));
1268 Results.AddResult(Result("char16_t", CCP_Type));
1269 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001270
Douglas Gregor218937c2011-02-01 19:23:04 +00001271 Builder.AddTypedTextChunk("decltype");
1272 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1273 Builder.AddPlaceholderChunk("expression");
1274 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1275 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001276 }
1277 }
1278
1279 // GNU extensions
1280 if (LangOpts.GNUMode) {
1281 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001282 // Results.AddResult(Result("_Decimal32"));
1283 // Results.AddResult(Result("_Decimal64"));
1284 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001285
Douglas Gregor218937c2011-02-01 19:23:04 +00001286 Builder.AddTypedTextChunk("typeof");
1287 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1288 Builder.AddPlaceholderChunk("expression");
1289 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001290
Douglas Gregor218937c2011-02-01 19:23:04 +00001291 Builder.AddTypedTextChunk("typeof");
1292 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1293 Builder.AddPlaceholderChunk("type");
1294 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1295 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001296 }
1297}
1298
John McCallf312b1e2010-08-26 23:41:50 +00001299static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001300 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001301 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001302 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001303 // Note: we don't suggest either "auto" or "register", because both
1304 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1305 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001306 Results.AddResult(Result("extern"));
1307 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001308}
1309
John McCallf312b1e2010-08-26 23:41:50 +00001310static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001311 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001312 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001313 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001314 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001315 case Sema::PCC_Class:
1316 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001317 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001318 Results.AddResult(Result("explicit"));
1319 Results.AddResult(Result("friend"));
1320 Results.AddResult(Result("mutable"));
1321 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001322 }
1323 // Fall through
1324
John McCallf312b1e2010-08-26 23:41:50 +00001325 case Sema::PCC_ObjCInterface:
1326 case Sema::PCC_ObjCImplementation:
1327 case Sema::PCC_Namespace:
1328 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001329 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001330 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001331 break;
1332
John McCallf312b1e2010-08-26 23:41:50 +00001333 case Sema::PCC_ObjCInstanceVariableList:
1334 case Sema::PCC_Expression:
1335 case Sema::PCC_Statement:
1336 case Sema::PCC_ForInit:
1337 case Sema::PCC_Condition:
1338 case Sema::PCC_RecoveryInFunction:
1339 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001340 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001341 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001342 break;
1343 }
1344}
1345
Douglas Gregorbca403c2010-01-13 23:51:12 +00001346static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1347static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1348static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001349 ResultBuilder &Results,
1350 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001351static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001352 ResultBuilder &Results,
1353 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001354static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001355 ResultBuilder &Results,
1356 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001357static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001358
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001359static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001360 CodeCompletionBuilder Builder(Results.getAllocator(),
1361 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00001362 Builder.AddTypedTextChunk("typedef");
1363 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1364 Builder.AddPlaceholderChunk("type");
1365 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1366 Builder.AddPlaceholderChunk("name");
1367 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001368}
1369
John McCallf312b1e2010-08-26 23:41:50 +00001370static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001371 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001372 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001373 case Sema::PCC_Namespace:
1374 case Sema::PCC_Class:
1375 case Sema::PCC_ObjCInstanceVariableList:
1376 case Sema::PCC_Template:
1377 case Sema::PCC_MemberTemplate:
1378 case Sema::PCC_Statement:
1379 case Sema::PCC_RecoveryInFunction:
1380 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001381 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001382 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001383 return true;
1384
John McCallf312b1e2010-08-26 23:41:50 +00001385 case Sema::PCC_Expression:
1386 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001387 return LangOpts.CPlusPlus;
1388
1389 case Sema::PCC_ObjCInterface:
1390 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001391 return false;
1392
John McCallf312b1e2010-08-26 23:41:50 +00001393 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001394 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001395 }
David Blaikie7530c032012-01-17 06:56:22 +00001396
1397 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001398}
1399
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001400static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1401 const Preprocessor &PP) {
1402 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001403 Policy.AnonymousTagLocations = false;
1404 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001405 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001406 return Policy;
1407}
1408
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001409/// \brief Retrieve a printing policy suitable for code completion.
1410static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1411 return getCompletionPrintingPolicy(S.Context, S.PP);
1412}
1413
Douglas Gregor8ca72082011-10-18 21:20:17 +00001414/// \brief Retrieve the string representation of the given type as a string
1415/// that has the appropriate lifetime for code completion.
1416///
1417/// This routine provides a fast path where we provide constant strings for
1418/// common type names.
1419static const char *GetCompletionTypeString(QualType T,
1420 ASTContext &Context,
1421 const PrintingPolicy &Policy,
1422 CodeCompletionAllocator &Allocator) {
1423 if (!T.getLocalQualifiers()) {
1424 // Built-in type names are constant strings.
1425 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidis27a00972012-05-05 04:20:28 +00001426 return BT->getNameAsCString(Policy);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001427
1428 // Anonymous tag types are constant strings.
1429 if (const TagType *TagT = dyn_cast<TagType>(T))
1430 if (TagDecl *Tag = TagT->getDecl())
1431 if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
1432 switch (Tag->getTagKind()) {
1433 case TTK_Struct: return "struct <anonymous>";
Joao Matos6666ed42012-08-31 18:45:21 +00001434 case TTK_Interface: return "__interface <anonymous>";
1435 case TTK_Class: return "class <anonymous>";
Douglas Gregor8ca72082011-10-18 21:20:17 +00001436 case TTK_Union: return "union <anonymous>";
1437 case TTK_Enum: return "enum <anonymous>";
1438 }
1439 }
1440 }
1441
1442 // Slow path: format the type as a string.
1443 std::string Result;
1444 T.getAsStringInternal(Result, Policy);
1445 return Allocator.CopyString(Result);
1446}
1447
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001448/// \brief Add a completion for "this", if we're in a member function.
1449static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1450 QualType ThisTy = S.getCurrentThisType();
1451 if (ThisTy.isNull())
1452 return;
1453
1454 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001455 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001456 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1457 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1458 S.Context,
1459 Policy,
1460 Allocator));
1461 Builder.AddTypedTextChunk("this");
Joao Matos6666ed42012-08-31 18:45:21 +00001462 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001463}
1464
Douglas Gregor01dfea02010-01-10 23:08:15 +00001465/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001466static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001467 Scope *S,
1468 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001469 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001470 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001471 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor8ca72082011-10-18 21:20:17 +00001472 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001473
John McCall0a2c5e22010-08-25 06:19:51 +00001474 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001475 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001476 case Sema::PCC_Namespace:
David Blaikie4e4d0842012-03-11 07:00:24 +00001477 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001478 if (Results.includeCodePatterns()) {
1479 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001480 Builder.AddTypedTextChunk("namespace");
1481 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1482 Builder.AddPlaceholderChunk("identifier");
1483 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1484 Builder.AddPlaceholderChunk("declarations");
1485 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1486 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1487 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001488 }
1489
Douglas Gregor01dfea02010-01-10 23:08:15 +00001490 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001491 Builder.AddTypedTextChunk("namespace");
1492 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1493 Builder.AddPlaceholderChunk("name");
1494 Builder.AddChunk(CodeCompletionString::CK_Equal);
1495 Builder.AddPlaceholderChunk("namespace");
1496 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001497
1498 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001499 Builder.AddTypedTextChunk("using");
1500 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1501 Builder.AddTextChunk("namespace");
1502 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1503 Builder.AddPlaceholderChunk("identifier");
1504 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001505
1506 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001507 Builder.AddTypedTextChunk("asm");
1508 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1509 Builder.AddPlaceholderChunk("string-literal");
1510 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1511 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001512
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001513 if (Results.includeCodePatterns()) {
1514 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001515 Builder.AddTypedTextChunk("template");
1516 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1517 Builder.AddPlaceholderChunk("declaration");
1518 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001519 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001520 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001521
David Blaikie4e4d0842012-03-11 07:00:24 +00001522 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001523 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001524
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001525 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001526 // Fall through
1527
John McCallf312b1e2010-08-26 23:41:50 +00001528 case Sema::PCC_Class:
David Blaikie4e4d0842012-03-11 07:00:24 +00001529 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001530 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001531 Builder.AddTypedTextChunk("using");
1532 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1533 Builder.AddPlaceholderChunk("qualifier");
1534 Builder.AddTextChunk("::");
1535 Builder.AddPlaceholderChunk("name");
1536 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001537
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001538 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001539 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001540 Builder.AddTypedTextChunk("using");
1541 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1542 Builder.AddTextChunk("typename");
1543 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1544 Builder.AddPlaceholderChunk("qualifier");
1545 Builder.AddTextChunk("::");
1546 Builder.AddPlaceholderChunk("name");
1547 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001548 }
1549
John McCallf312b1e2010-08-26 23:41:50 +00001550 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001551 AddTypedefResult(Results);
1552
Douglas Gregor01dfea02010-01-10 23:08:15 +00001553 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001554 Builder.AddTypedTextChunk("public");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001555 if (Results.includeCodePatterns())
1556 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001557 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001558
1559 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001560 Builder.AddTypedTextChunk("protected");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001561 if (Results.includeCodePatterns())
1562 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001563 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001564
1565 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001566 Builder.AddTypedTextChunk("private");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001567 if (Results.includeCodePatterns())
1568 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001569 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001570 }
1571 }
1572 // Fall through
1573
John McCallf312b1e2010-08-26 23:41:50 +00001574 case Sema::PCC_Template:
1575 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001576 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001577 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001578 Builder.AddTypedTextChunk("template");
1579 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1580 Builder.AddPlaceholderChunk("parameters");
1581 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1582 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001583 }
1584
David Blaikie4e4d0842012-03-11 07:00:24 +00001585 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1586 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001587 break;
1588
John McCallf312b1e2010-08-26 23:41:50 +00001589 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001590 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1591 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1592 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001593 break;
1594
John McCallf312b1e2010-08-26 23:41:50 +00001595 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001596 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1597 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1598 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001599 break;
1600
John McCallf312b1e2010-08-26 23:41:50 +00001601 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001602 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001603 break;
1604
John McCallf312b1e2010-08-26 23:41:50 +00001605 case Sema::PCC_RecoveryInFunction:
1606 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001607 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001608
David Blaikie4e4d0842012-03-11 07:00:24 +00001609 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1610 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001611 Builder.AddTypedTextChunk("try");
1612 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1613 Builder.AddPlaceholderChunk("statements");
1614 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1615 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1616 Builder.AddTextChunk("catch");
1617 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1618 Builder.AddPlaceholderChunk("declaration");
1619 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1620 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1621 Builder.AddPlaceholderChunk("statements");
1622 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1623 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1624 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001625 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001626 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001627 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001628
Douglas Gregord8e8a582010-05-25 21:41:55 +00001629 if (Results.includeCodePatterns()) {
1630 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001631 Builder.AddTypedTextChunk("if");
1632 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001633 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001634 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001635 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001636 Builder.AddPlaceholderChunk("expression");
1637 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1638 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1639 Builder.AddPlaceholderChunk("statements");
1640 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1641 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1642 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001643
Douglas Gregord8e8a582010-05-25 21:41:55 +00001644 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001645 Builder.AddTypedTextChunk("switch");
1646 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001647 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001648 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001649 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001650 Builder.AddPlaceholderChunk("expression");
1651 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1652 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1653 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1654 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1655 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001656 }
1657
Douglas Gregor01dfea02010-01-10 23:08:15 +00001658 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001659 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001660 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001661 Builder.AddTypedTextChunk("case");
1662 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1663 Builder.AddPlaceholderChunk("expression");
1664 Builder.AddChunk(CodeCompletionString::CK_Colon);
1665 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001666
1667 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001668 Builder.AddTypedTextChunk("default");
1669 Builder.AddChunk(CodeCompletionString::CK_Colon);
1670 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001671 }
1672
Douglas Gregord8e8a582010-05-25 21:41:55 +00001673 if (Results.includeCodePatterns()) {
1674 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001675 Builder.AddTypedTextChunk("while");
1676 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001677 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001678 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001679 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001680 Builder.AddPlaceholderChunk("expression");
1681 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1682 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1683 Builder.AddPlaceholderChunk("statements");
1684 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1685 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1686 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001687
1688 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001689 Builder.AddTypedTextChunk("do");
1690 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1691 Builder.AddPlaceholderChunk("statements");
1692 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1693 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1694 Builder.AddTextChunk("while");
1695 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1696 Builder.AddPlaceholderChunk("expression");
1697 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1698 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001699
Douglas Gregord8e8a582010-05-25 21:41:55 +00001700 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001701 Builder.AddTypedTextChunk("for");
1702 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001703 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001704 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001705 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001706 Builder.AddPlaceholderChunk("init-expression");
1707 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1708 Builder.AddPlaceholderChunk("condition");
1709 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1710 Builder.AddPlaceholderChunk("inc-expression");
1711 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1712 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1713 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1714 Builder.AddPlaceholderChunk("statements");
1715 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1716 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1717 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001718 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001719
1720 if (S->getContinueParent()) {
1721 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001722 Builder.AddTypedTextChunk("continue");
1723 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001724 }
1725
1726 if (S->getBreakParent()) {
1727 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001728 Builder.AddTypedTextChunk("break");
1729 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001730 }
1731
1732 // "return expression ;" or "return ;", depending on whether we
1733 // know the function is void or not.
1734 bool isVoid = false;
1735 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1736 isVoid = Function->getResultType()->isVoidType();
1737 else if (ObjCMethodDecl *Method
1738 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1739 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001740 else if (SemaRef.getCurBlock() &&
1741 !SemaRef.getCurBlock()->ReturnType.isNull())
1742 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001743 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001744 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001745 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1746 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001747 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001748 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001749
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001750 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001751 Builder.AddTypedTextChunk("goto");
1752 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1753 Builder.AddPlaceholderChunk("label");
1754 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001755
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001756 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001757 Builder.AddTypedTextChunk("using");
1758 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1759 Builder.AddTextChunk("namespace");
1760 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1761 Builder.AddPlaceholderChunk("identifier");
1762 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001763 }
1764
1765 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001766 case Sema::PCC_ForInit:
1767 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001768 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001769 // Fall through: conditions and statements can have expressions.
1770
Douglas Gregor02688102010-09-14 23:59:36 +00001771 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001772 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001773 CCC == Sema::PCC_ParenthesizedExpression) {
1774 // (__bridge <type>)<expression>
1775 Builder.AddTypedTextChunk("__bridge");
1776 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1777 Builder.AddPlaceholderChunk("type");
1778 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1779 Builder.AddPlaceholderChunk("expression");
1780 Results.AddResult(Result(Builder.TakeString()));
1781
1782 // (__bridge_transfer <Objective-C type>)<expression>
1783 Builder.AddTypedTextChunk("__bridge_transfer");
1784 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1785 Builder.AddPlaceholderChunk("Objective-C type");
1786 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1787 Builder.AddPlaceholderChunk("expression");
1788 Results.AddResult(Result(Builder.TakeString()));
1789
1790 // (__bridge_retained <CF type>)<expression>
1791 Builder.AddTypedTextChunk("__bridge_retained");
1792 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1793 Builder.AddPlaceholderChunk("CF type");
1794 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1795 Builder.AddPlaceholderChunk("expression");
1796 Results.AddResult(Result(Builder.TakeString()));
1797 }
1798 // Fall through
1799
John McCallf312b1e2010-08-26 23:41:50 +00001800 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001801 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001802 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001803 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001804
Douglas Gregor8ca72082011-10-18 21:20:17 +00001805 // true
1806 Builder.AddResultTypeChunk("bool");
1807 Builder.AddTypedTextChunk("true");
1808 Results.AddResult(Result(Builder.TakeString()));
1809
1810 // false
1811 Builder.AddResultTypeChunk("bool");
1812 Builder.AddTypedTextChunk("false");
1813 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001814
David Blaikie4e4d0842012-03-11 07:00:24 +00001815 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001816 // dynamic_cast < type-id > ( expression )
1817 Builder.AddTypedTextChunk("dynamic_cast");
1818 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1819 Builder.AddPlaceholderChunk("type");
1820 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1821 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1822 Builder.AddPlaceholderChunk("expression");
1823 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1824 Results.AddResult(Result(Builder.TakeString()));
1825 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001826
1827 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001828 Builder.AddTypedTextChunk("static_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 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001838 Builder.AddTypedTextChunk("reinterpret_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
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001847 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001848 Builder.AddTypedTextChunk("const_cast");
1849 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1850 Builder.AddPlaceholderChunk("type");
1851 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1852 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1853 Builder.AddPlaceholderChunk("expression");
1854 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1855 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001856
David Blaikie4e4d0842012-03-11 07:00:24 +00001857 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001858 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001859 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001860 Builder.AddTypedTextChunk("typeid");
1861 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1862 Builder.AddPlaceholderChunk("expression-or-type");
1863 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1864 Results.AddResult(Result(Builder.TakeString()));
1865 }
1866
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001867 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001868 Builder.AddTypedTextChunk("new");
1869 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1870 Builder.AddPlaceholderChunk("type");
1871 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1872 Builder.AddPlaceholderChunk("expressions");
1873 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1874 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001875
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001876 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001877 Builder.AddTypedTextChunk("new");
1878 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1879 Builder.AddPlaceholderChunk("type");
1880 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1881 Builder.AddPlaceholderChunk("size");
1882 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1883 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1884 Builder.AddPlaceholderChunk("expressions");
1885 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1886 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001887
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001888 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001889 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001890 Builder.AddTypedTextChunk("delete");
1891 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1892 Builder.AddPlaceholderChunk("expression");
1893 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001894
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001895 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001896 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001897 Builder.AddTypedTextChunk("delete");
1898 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1899 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1900 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1901 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1902 Builder.AddPlaceholderChunk("expression");
1903 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001904
David Blaikie4e4d0842012-03-11 07:00:24 +00001905 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001906 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001907 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001908 Builder.AddTypedTextChunk("throw");
1909 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1910 Builder.AddPlaceholderChunk("expression");
1911 Results.AddResult(Result(Builder.TakeString()));
1912 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001913
Douglas Gregor12e13132010-05-26 22:00:08 +00001914 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001915
Richard Smith80ad52f2013-01-02 11:42:31 +00001916 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001917 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001918 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001919 Builder.AddTypedTextChunk("nullptr");
1920 Results.AddResult(Result(Builder.TakeString()));
1921
1922 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001923 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001924 Builder.AddTypedTextChunk("alignof");
1925 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1926 Builder.AddPlaceholderChunk("type");
1927 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1928 Results.AddResult(Result(Builder.TakeString()));
1929
1930 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001931 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001932 Builder.AddTypedTextChunk("noexcept");
1933 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1934 Builder.AddPlaceholderChunk("expression");
1935 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1936 Results.AddResult(Result(Builder.TakeString()));
1937
1938 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001939 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001940 Builder.AddTypedTextChunk("sizeof...");
1941 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1942 Builder.AddPlaceholderChunk("parameter-pack");
1943 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1944 Results.AddResult(Result(Builder.TakeString()));
1945 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001946 }
1947
David Blaikie4e4d0842012-03-11 07:00:24 +00001948 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001949 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001950 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1951 // The interface can be NULL.
1952 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00001953 if (ID->getSuperClass()) {
1954 std::string SuperType;
1955 SuperType = ID->getSuperClass()->getNameAsString();
1956 if (Method->isInstanceMethod())
1957 SuperType += " *";
1958
1959 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
1960 Builder.AddTypedTextChunk("super");
1961 Results.AddResult(Result(Builder.TakeString()));
1962 }
Ted Kremenek681e2562010-05-31 21:43:10 +00001963 }
1964
Douglas Gregorbca403c2010-01-13 23:51:12 +00001965 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001966 }
1967
Jordan Rosef70a8862012-06-30 21:33:57 +00001968 if (SemaRef.getLangOpts().C11) {
1969 // _Alignof
1970 Builder.AddResultTypeChunk("size_t");
1971 if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition())
1972 Builder.AddTypedTextChunk("alignof");
1973 else
1974 Builder.AddTypedTextChunk("_Alignof");
1975 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1976 Builder.AddPlaceholderChunk("type");
1977 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1978 Results.AddResult(Result(Builder.TakeString()));
1979 }
1980
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001981 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001982 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00001983 Builder.AddTypedTextChunk("sizeof");
1984 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1985 Builder.AddPlaceholderChunk("expression-or-type");
1986 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1987 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001988 break;
1989 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001990
John McCallf312b1e2010-08-26 23:41:50 +00001991 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001992 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00001993 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001994 }
1995
David Blaikie4e4d0842012-03-11 07:00:24 +00001996 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
1997 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001998
David Blaikie4e4d0842012-03-11 07:00:24 +00001999 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00002000 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00002001}
2002
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002003/// \brief If the given declaration has an associated type, add it as a result
2004/// type chunk.
2005static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002006 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002007 const NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00002008 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002009 if (!ND)
2010 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00002011
2012 // Skip constructors and conversion functions, which have their return types
2013 // built into their names.
2014 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
2015 return;
2016
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002017 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00002018 QualType T;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002019 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002020 T = Function->getResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002021 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002022 T = Method->getResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002023 else if (const FunctionTemplateDecl *FunTmpl =
2024 dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002025 T = FunTmpl->getTemplatedDecl()->getResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002026 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002027 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2028 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2029 /* Do nothing: ignore unresolved using declarations*/
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002030 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002031 T = Value->getType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002032 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002033 T = Property->getType();
2034
2035 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2036 return;
2037
Douglas Gregor8987b232011-09-27 23:30:47 +00002038 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002039 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002040}
2041
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002042static void MaybeAddSentinel(ASTContext &Context,
2043 const NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002044 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002045 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2046 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002047 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002048 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002049 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002050 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002051 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002052 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002053 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002054 }
2055}
2056
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002057static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2058 std::string Result;
2059 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002060 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002061 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002062 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002063 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002064 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002065 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002066 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002067 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002068 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002069 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002070 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002071 return Result;
2072}
2073
Douglas Gregor83482d12010-08-24 16:15:59 +00002074static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002075 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002076 const ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002077 bool SuppressName = false,
2078 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002079 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2080 if (Param->getType()->isDependentType() ||
2081 !Param->getType()->isBlockPointerType()) {
2082 // The argument for a dependent or non-block parameter is a placeholder
2083 // containing that parameter's type.
2084 std::string Result;
2085
Douglas Gregoraba48082010-08-29 19:47:46 +00002086 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002087 Result = Param->getIdentifier()->getName();
2088
John McCallf85e1932011-06-15 23:02:42 +00002089 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002090
2091 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002092 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2093 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002094 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002095 Result += Param->getIdentifier()->getName();
2096 }
2097 return Result;
2098 }
2099
2100 // The argument for a block pointer parameter is a block literal with
2101 // the appropriate type.
Douglas Gregor830072c2011-02-15 22:37:09 +00002102 FunctionTypeLoc *Block = 0;
2103 FunctionProtoTypeLoc *BlockProto = 0;
Douglas Gregor83482d12010-08-24 16:15:59 +00002104 TypeLoc TL;
2105 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2106 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2107 while (true) {
2108 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002109 if (!SuppressBlock) {
2110 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
2111 if (TypeSourceInfo *InnerTSInfo
2112 = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) {
2113 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2114 continue;
2115 }
2116 }
2117
2118 // Look through qualified types
2119 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
2120 TL = QualifiedTL->getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002121 continue;
2122 }
2123 }
2124
Douglas Gregor83482d12010-08-24 16:15:59 +00002125 // Try to get the function prototype behind the block pointer type,
2126 // then we're done.
2127 if (BlockPointerTypeLoc *BlockPtr
2128 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00002129 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor830072c2011-02-15 22:37:09 +00002130 Block = dyn_cast<FunctionTypeLoc>(&TL);
2131 BlockProto = dyn_cast<FunctionProtoTypeLoc>(&TL);
Douglas Gregor83482d12010-08-24 16:15:59 +00002132 }
2133 break;
2134 }
2135 }
2136
2137 if (!Block) {
2138 // We were unable to find a FunctionProtoTypeLoc with parameter names
2139 // for the block; just use the parameter type as a placeholder.
2140 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002141 if (!ObjCMethodParam && Param->getIdentifier())
2142 Result = Param->getIdentifier()->getName();
2143
John McCallf85e1932011-06-15 23:02:42 +00002144 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002145
2146 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002147 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2148 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002149 if (Param->getIdentifier())
2150 Result += Param->getIdentifier()->getName();
2151 }
2152
2153 return Result;
2154 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002155
Douglas Gregor83482d12010-08-24 16:15:59 +00002156 // We have the function prototype behind the block pointer type, as it was
2157 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002158 std::string Result;
2159 QualType ResultType = Block->getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002160 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002161 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002162
2163 // Format the parameter list.
2164 std::string Params;
Douglas Gregor830072c2011-02-15 22:37:09 +00002165 if (!BlockProto || Block->getNumArgs() == 0) {
2166 if (BlockProto && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002167 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002168 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002169 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002170 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002171 Params += "(";
Douglas Gregor38276252010-09-08 22:47:51 +00002172 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
2173 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002174 Params += ", ";
2175 Params += FormatFunctionParameter(Context, Policy, Block->getArg(I),
2176 /*SuppressName=*/false,
2177 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002178
Douglas Gregor830072c2011-02-15 22:37:09 +00002179 if (I == N - 1 && BlockProto->getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002180 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002181 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002182 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002183 }
Douglas Gregor38276252010-09-08 22:47:51 +00002184
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002185 if (SuppressBlock) {
2186 // Format as a parameter.
2187 Result = Result + " (^";
2188 if (Param->getIdentifier())
2189 Result += Param->getIdentifier()->getName();
2190 Result += ")";
2191 Result += Params;
2192 } else {
2193 // Format as a block literal argument.
2194 Result = '^' + Result;
2195 Result += Params;
2196
2197 if (Param->getIdentifier())
2198 Result += Param->getIdentifier()->getName();
2199 }
2200
Douglas Gregor83482d12010-08-24 16:15:59 +00002201 return Result;
2202}
2203
Douglas Gregor86d9a522009-09-21 16:56:56 +00002204/// \brief Add function parameter chunks to the given code completion string.
2205static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002206 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002207 const FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002208 CodeCompletionBuilder &Result,
2209 unsigned Start = 0,
2210 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002211 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002212
Douglas Gregor218937c2011-02-01 19:23:04 +00002213 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002214 const ParmVarDecl *Param = Function->getParamDecl(P);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002215
Douglas Gregor218937c2011-02-01 19:23:04 +00002216 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002217 // When we see an optional default argument, put that argument and
2218 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002219 CodeCompletionBuilder Opt(Result.getAllocator(),
2220 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002221 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002222 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002223 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002224 Result.AddOptionalChunk(Opt.TakeString());
2225 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002226 }
2227
Douglas Gregor218937c2011-02-01 19:23:04 +00002228 if (FirstParameter)
2229 FirstParameter = false;
2230 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002231 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002232
2233 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002234
2235 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002236 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2237 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002238
Douglas Gregore17794f2010-08-31 05:13:43 +00002239 if (Function->isVariadic() && P == N - 1)
2240 PlaceholderStr += ", ...";
2241
Douglas Gregor86d9a522009-09-21 16:56:56 +00002242 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002243 Result.AddPlaceholderChunk(
2244 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002245 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002246
2247 if (const FunctionProtoType *Proto
2248 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002249 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002250 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002251 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002252
Douglas Gregor218937c2011-02-01 19:23:04 +00002253 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002254 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002255}
2256
2257/// \brief Add template parameter chunks to the given code completion string.
2258static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002259 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002260 const TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002261 CodeCompletionBuilder &Result,
2262 unsigned MaxParameters = 0,
2263 unsigned Start = 0,
2264 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002265 bool FirstParameter = true;
2266
2267 TemplateParameterList *Params = Template->getTemplateParameters();
2268 TemplateParameterList::iterator PEnd = Params->end();
2269 if (MaxParameters)
2270 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002271 for (TemplateParameterList::iterator P = Params->begin() + Start;
2272 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002273 bool HasDefaultArg = false;
2274 std::string PlaceholderStr;
2275 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2276 if (TTP->wasDeclaredWithTypename())
2277 PlaceholderStr = "typename";
2278 else
2279 PlaceholderStr = "class";
2280
2281 if (TTP->getIdentifier()) {
2282 PlaceholderStr += ' ';
2283 PlaceholderStr += TTP->getIdentifier()->getName();
2284 }
2285
2286 HasDefaultArg = TTP->hasDefaultArgument();
2287 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002288 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002289 if (NTTP->getIdentifier())
2290 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002291 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002292 HasDefaultArg = NTTP->hasDefaultArgument();
2293 } else {
2294 assert(isa<TemplateTemplateParmDecl>(*P));
2295 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2296
2297 // Since putting the template argument list into the placeholder would
2298 // be very, very long, we just use an abbreviation.
2299 PlaceholderStr = "template<...> class";
2300 if (TTP->getIdentifier()) {
2301 PlaceholderStr += ' ';
2302 PlaceholderStr += TTP->getIdentifier()->getName();
2303 }
2304
2305 HasDefaultArg = TTP->hasDefaultArgument();
2306 }
2307
Douglas Gregor218937c2011-02-01 19:23:04 +00002308 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002309 // When we see an optional default argument, put that argument and
2310 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002311 CodeCompletionBuilder Opt(Result.getAllocator(),
2312 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002313 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002314 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002315 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002316 P - Params->begin(), true);
2317 Result.AddOptionalChunk(Opt.TakeString());
2318 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002319 }
2320
Douglas Gregor218937c2011-02-01 19:23:04 +00002321 InDefaultArg = false;
2322
Douglas Gregor86d9a522009-09-21 16:56:56 +00002323 if (FirstParameter)
2324 FirstParameter = false;
2325 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002326 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002327
2328 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002329 Result.AddPlaceholderChunk(
2330 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002331 }
2332}
2333
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002334/// \brief Add a qualifier to the given code-completion string, if the
2335/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002336static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002337AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002338 NestedNameSpecifier *Qualifier,
2339 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002340 ASTContext &Context,
2341 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002342 if (!Qualifier)
2343 return;
2344
2345 std::string PrintedNNS;
2346 {
2347 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002348 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002349 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002350 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002351 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002352 else
Douglas Gregordae68752011-02-01 22:57:45 +00002353 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002354}
2355
Douglas Gregor218937c2011-02-01 19:23:04 +00002356static void
2357AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002358 const FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002359 const FunctionProtoType *Proto
2360 = Function->getType()->getAs<FunctionProtoType>();
2361 if (!Proto || !Proto->getTypeQuals())
2362 return;
2363
Douglas Gregora63f6de2011-02-01 21:15:40 +00002364 // FIXME: Add ref-qualifier!
2365
2366 // Handle single qualifiers without copying
2367 if (Proto->getTypeQuals() == Qualifiers::Const) {
2368 Result.AddInformativeChunk(" const");
2369 return;
2370 }
2371
2372 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2373 Result.AddInformativeChunk(" volatile");
2374 return;
2375 }
2376
2377 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2378 Result.AddInformativeChunk(" restrict");
2379 return;
2380 }
2381
2382 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002383 std::string QualsStr;
David Blaikie4ef832f2012-08-10 00:55:35 +00002384 if (Proto->isConst())
Douglas Gregora61a8792009-12-11 18:44:16 +00002385 QualsStr += " const";
David Blaikie4ef832f2012-08-10 00:55:35 +00002386 if (Proto->isVolatile())
Douglas Gregora61a8792009-12-11 18:44:16 +00002387 QualsStr += " volatile";
David Blaikie4ef832f2012-08-10 00:55:35 +00002388 if (Proto->isRestrict())
Douglas Gregora61a8792009-12-11 18:44:16 +00002389 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002390 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002391}
2392
Douglas Gregor6f942b22010-09-21 16:06:22 +00002393/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002394static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002395 const NamedDecl *ND,
2396 CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002397 DeclarationName Name = ND->getDeclName();
2398 if (!Name)
2399 return;
2400
2401 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002402 case DeclarationName::CXXOperatorName: {
2403 const char *OperatorName = 0;
2404 switch (Name.getCXXOverloadedOperator()) {
2405 case OO_None:
2406 case OO_Conditional:
2407 case NUM_OVERLOADED_OPERATORS:
2408 OperatorName = "operator";
2409 break;
2410
2411#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2412 case OO_##Name: OperatorName = "operator" Spelling; break;
2413#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2414#include "clang/Basic/OperatorKinds.def"
2415
2416 case OO_New: OperatorName = "operator new"; break;
2417 case OO_Delete: OperatorName = "operator delete"; break;
2418 case OO_Array_New: OperatorName = "operator new[]"; break;
2419 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2420 case OO_Call: OperatorName = "operator()"; break;
2421 case OO_Subscript: OperatorName = "operator[]"; break;
2422 }
2423 Result.AddTypedTextChunk(OperatorName);
2424 break;
2425 }
2426
Douglas Gregor6f942b22010-09-21 16:06:22 +00002427 case DeclarationName::Identifier:
2428 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002429 case DeclarationName::CXXDestructorName:
2430 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002431 Result.AddTypedTextChunk(
2432 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002433 break;
2434
2435 case DeclarationName::CXXUsingDirective:
2436 case DeclarationName::ObjCZeroArgSelector:
2437 case DeclarationName::ObjCOneArgSelector:
2438 case DeclarationName::ObjCMultiArgSelector:
2439 break;
2440
2441 case DeclarationName::CXXConstructorName: {
2442 CXXRecordDecl *Record = 0;
2443 QualType Ty = Name.getCXXNameType();
2444 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2445 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2446 else if (const InjectedClassNameType *InjectedTy
2447 = Ty->getAs<InjectedClassNameType>())
2448 Record = InjectedTy->getDecl();
2449 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002450 Result.AddTypedTextChunk(
2451 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002452 break;
2453 }
2454
Douglas Gregordae68752011-02-01 22:57:45 +00002455 Result.AddTypedTextChunk(
2456 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002457 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002458 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002459 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002460 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002461 }
2462 break;
2463 }
2464 }
2465}
2466
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002467CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002468 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002469 CodeCompletionTUInfo &CCTUInfo,
2470 bool IncludeBriefComments) {
2471 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo,
2472 IncludeBriefComments);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002473}
2474
Douglas Gregor86d9a522009-09-21 16:56:56 +00002475/// \brief If possible, create a new code completion string for the given
2476/// result.
2477///
2478/// \returns Either a new, heap-allocated code completion string describing
2479/// how to use this result, or NULL to indicate that the string or name of the
2480/// result is all that is needed.
2481CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002482CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2483 Preprocessor &PP,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002484 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002485 CodeCompletionTUInfo &CCTUInfo,
2486 bool IncludeBriefComments) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002487 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002488
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002489 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002490 if (Kind == RK_Pattern) {
2491 Pattern->Priority = Priority;
2492 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002493
2494 if (Declaration) {
2495 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregorba103062012-03-27 23:34:16 +00002496 Pattern->ParentName = Result.getParentName();
2497 }
2498
Douglas Gregor218937c2011-02-01 19:23:04 +00002499 return Pattern;
2500 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002501
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002502 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002503 Result.AddTypedTextChunk(Keyword);
2504 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002505 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002506
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002507 if (Kind == RK_Macro) {
Douglas Gregor3644d972012-10-09 16:01:50 +00002508 MacroInfo *MI = PP.getMacroInfoHistory(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002509 assert(MI && "Not a macro?");
2510
Douglas Gregordae68752011-02-01 22:57:45 +00002511 Result.AddTypedTextChunk(
2512 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002513
2514 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002515 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002516
2517 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002518 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002519 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002520
2521 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2522 if (MI->isC99Varargs()) {
2523 --AEnd;
2524
2525 if (A == AEnd) {
2526 Result.AddPlaceholderChunk("...");
2527 }
Douglas Gregore4244702011-07-30 08:17:44 +00002528 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002529
Douglas Gregore4244702011-07-30 08:17:44 +00002530 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002531 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002532 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002533
2534 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002535 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002536 if (MI->isC99Varargs())
2537 Arg += ", ...";
2538 else
2539 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002540 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002541 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002542 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002543
2544 // Non-variadic macros are simple.
2545 Result.AddPlaceholderChunk(
2546 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002547 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002548 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002549 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002550 }
2551
Douglas Gregord8e8a582010-05-25 21:41:55 +00002552 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002553 const NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002554 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002555
2556 if (IncludeBriefComments) {
2557 // Add documentation comment, if it exists.
Dmitri Gribenkof50555e2012-08-11 00:51:43 +00002558 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002559 Result.addBriefComment(RC->getBriefText(Ctx));
2560 }
2561 }
2562
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002563 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002564 Result.AddTypedTextChunk(
2565 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002566 Result.AddTextChunk("::");
2567 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002568 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002569
2570 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2571 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2572 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2573 }
2574 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002575
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002576 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002577
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002578 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002579 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002580 Ctx, Policy);
2581 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002582 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002583 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002584 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002585 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002586 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002587 }
2588
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002589 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002590 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002591 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002592 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002593 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002594
Douglas Gregor86d9a522009-09-21 16:56:56 +00002595 // Figure out which template parameters are deduced (or have default
2596 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002597 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002598 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002599 unsigned LastDeducibleArgument;
2600 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2601 --LastDeducibleArgument) {
2602 if (!Deduced[LastDeducibleArgument - 1]) {
2603 // C++0x: Figure out if the template argument has a default. If so,
2604 // the user doesn't need to type this argument.
2605 // FIXME: We need to abstract template parameters better!
2606 bool HasDefaultArg = false;
2607 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002608 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002609 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2610 HasDefaultArg = TTP->hasDefaultArgument();
2611 else if (NonTypeTemplateParmDecl *NTTP
2612 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2613 HasDefaultArg = NTTP->hasDefaultArgument();
2614 else {
2615 assert(isa<TemplateTemplateParmDecl>(Param));
2616 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002617 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002618 }
2619
2620 if (!HasDefaultArg)
2621 break;
2622 }
2623 }
2624
2625 if (LastDeducibleArgument) {
2626 // Some of the function template arguments cannot be deduced from a
2627 // function call, so we introduce an explicit template argument list
2628 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002629 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002630 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002631 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002632 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002633 }
2634
2635 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002636 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002637 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002638 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002639 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002640 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002641 }
2642
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002643 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002644 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002645 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002646 Result.AddTypedTextChunk(
2647 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002648 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002649 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002650 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002651 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002652 }
2653
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002654 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002655 Selector Sel = Method->getSelector();
2656 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002657 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002658 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002659 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002660 }
2661
Douglas Gregor813d8342011-02-18 22:29:55 +00002662 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002663 SelName += ':';
2664 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002665 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002666 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002667 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002668
2669 // If there is only one parameter, and we're past it, add an empty
2670 // typed-text chunk since there is nothing to type.
2671 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002672 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002673 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002674 unsigned Idx = 0;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002675 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2676 PEnd = Method->param_end();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002677 P != PEnd; (void)++P, ++Idx) {
2678 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002679 std::string Keyword;
2680 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002681 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002682 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002683 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002684 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002685 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002686 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002687 else
Douglas Gregordae68752011-02-01 22:57:45 +00002688 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002689 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002690
2691 // If we're before the starting parameter, skip the placeholder.
2692 if (Idx < StartParameter)
2693 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002694
2695 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002696
2697 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002698 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002699 else {
John McCallf85e1932011-06-15 23:02:42 +00002700 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002701 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2702 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002703 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002704 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002705 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002706 }
2707
Douglas Gregore17794f2010-08-31 05:13:43 +00002708 if (Method->isVariadic() && (P + 1) == PEnd)
2709 Arg += ", ...";
2710
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002711 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002712 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002713 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002714 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002715 else
Douglas Gregordae68752011-02-01 22:57:45 +00002716 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002717 }
2718
Douglas Gregor2a17af02009-12-23 00:21:46 +00002719 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002720 if (Method->param_size() == 0) {
2721 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002722 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002723 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002724 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002725 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002726 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002727 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002728
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002729 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002730 }
2731
Douglas Gregor218937c2011-02-01 19:23:04 +00002732 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002733 }
2734
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002735 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002736 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002737 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002738
Douglas Gregordae68752011-02-01 22:57:45 +00002739 Result.AddTypedTextChunk(
2740 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002741 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002742}
2743
Douglas Gregor86d802e2009-09-23 00:34:09 +00002744CodeCompletionString *
2745CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2746 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002747 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002748 CodeCompletionAllocator &Allocator,
2749 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002750 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002751
Douglas Gregor218937c2011-02-01 19:23:04 +00002752 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002753 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002754 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002755 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002756 const FunctionProtoType *Proto
2757 = dyn_cast<FunctionProtoType>(getFunctionType());
2758 if (!FDecl && !Proto) {
2759 // Function without a prototype. Just give the return type and a
2760 // highlighted ellipsis.
2761 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002762 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002763 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002764 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002765 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2766 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2767 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002768 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002769 }
2770
2771 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002772 Result.AddTextChunk(
2773 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002774 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002775 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002776 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002777 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002778
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002779 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002780 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2781 for (unsigned I = 0; I != NumParams; ++I) {
2782 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002783 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002784
2785 std::string ArgString;
2786 QualType ArgType;
2787
2788 if (FDecl) {
2789 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2790 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2791 } else {
2792 ArgType = Proto->getArgType(I);
2793 }
2794
John McCallf85e1932011-06-15 23:02:42 +00002795 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002796
2797 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002798 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2799 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002800 else
Douglas Gregordae68752011-02-01 22:57:45 +00002801 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002802 }
2803
2804 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002805 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002806 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002807 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002808 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002809 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002810 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002811 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002812
Douglas Gregor218937c2011-02-01 19:23:04 +00002813 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002814}
2815
Chris Lattner5f9e2722011-07-23 10:55:15 +00002816unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002817 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002818 bool PreferredTypeIsPointer) {
2819 unsigned Priority = CCP_Macro;
2820
Douglas Gregorb05496d2010-09-20 21:11:48 +00002821 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2822 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2823 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002824 Priority = CCP_Constant;
2825 if (PreferredTypeIsPointer)
2826 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002827 }
2828 // Treat "YES", "NO", "true", and "false" as constants.
2829 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2830 MacroName.equals("true") || MacroName.equals("false"))
2831 Priority = CCP_Constant;
2832 // Treat "bool" as a type.
2833 else if (MacroName.equals("bool"))
2834 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2835
Douglas Gregor1827e102010-08-16 16:18:59 +00002836
2837 return Priority;
2838}
2839
Dmitri Gribenko06d8c602013-01-11 20:32:41 +00002840CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002841 if (!D)
2842 return CXCursor_UnexposedDecl;
2843
2844 switch (D->getKind()) {
2845 case Decl::Enum: return CXCursor_EnumDecl;
2846 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2847 case Decl::Field: return CXCursor_FieldDecl;
2848 case Decl::Function:
2849 return CXCursor_FunctionDecl;
2850 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2851 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002852 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002853
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002854 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002855 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2856 case Decl::ObjCMethod:
2857 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2858 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2859 case Decl::CXXMethod: return CXCursor_CXXMethod;
2860 case Decl::CXXConstructor: return CXCursor_Constructor;
2861 case Decl::CXXDestructor: return CXCursor_Destructor;
2862 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2863 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002864 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002865 case Decl::ParmVar: return CXCursor_ParmDecl;
2866 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002867 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002868 case Decl::Var: return CXCursor_VarDecl;
2869 case Decl::Namespace: return CXCursor_Namespace;
2870 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2871 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2872 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2873 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2874 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2875 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002876 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002877 case Decl::ClassTemplatePartialSpecialization:
2878 return CXCursor_ClassTemplatePartialSpecialization;
2879 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor8e5900c2012-04-30 23:41:16 +00002880 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002881
2882 case Decl::Using:
2883 case Decl::UnresolvedUsingValue:
2884 case Decl::UnresolvedUsingTypename:
2885 return CXCursor_UsingDeclaration;
2886
Douglas Gregor352697a2011-06-03 23:08:58 +00002887 case Decl::ObjCPropertyImpl:
2888 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2889 case ObjCPropertyImplDecl::Dynamic:
2890 return CXCursor_ObjCDynamicDecl;
2891
2892 case ObjCPropertyImplDecl::Synthesize:
2893 return CXCursor_ObjCSynthesizeDecl;
2894 }
Argyrios Kyrtzidis6a010122012-10-05 00:22:24 +00002895
2896 case Decl::Import:
2897 return CXCursor_ModuleImportDecl;
Douglas Gregor352697a2011-06-03 23:08:58 +00002898
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002899 default:
Dmitri Gribenko06d8c602013-01-11 20:32:41 +00002900 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002901 switch (TD->getTagKind()) {
Joao Matos6666ed42012-08-31 18:45:21 +00002902 case TTK_Interface: // fall through
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002903 case TTK_Struct: return CXCursor_StructDecl;
2904 case TTK_Class: return CXCursor_ClassDecl;
2905 case TTK_Union: return CXCursor_UnionDecl;
2906 case TTK_Enum: return CXCursor_EnumDecl;
2907 }
2908 }
2909 }
2910
2911 return CXCursor_UnexposedDecl;
2912}
2913
Douglas Gregor590c7d52010-07-08 20:55:51 +00002914static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor3644d972012-10-09 16:01:50 +00002915 bool IncludeUndefined,
Douglas Gregor590c7d52010-07-08 20:55:51 +00002916 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002917 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002918
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002919 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002920
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002921 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2922 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002923 M != MEnd; ++M) {
Douglas Gregor3644d972012-10-09 16:01:50 +00002924 if (IncludeUndefined || M->first->hasMacroDefinition())
2925 Results.AddResult(Result(M->first,
Douglas Gregor1827e102010-08-16 16:18:59 +00002926 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00002927 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002928 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002929 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002930
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002931 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002932
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002933}
2934
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002935static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2936 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002937 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002938
2939 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002940
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002941 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2942 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith80ad52f2013-01-02 11:42:31 +00002943 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002944 Results.AddResult(Result("__func__", CCP_Constant));
2945 Results.ExitScope();
2946}
2947
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002948static void HandleCodeCompleteResults(Sema *S,
2949 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002950 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002951 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002952 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002953 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002954 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002955}
2956
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002957static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2958 Sema::ParserCompletionContext PCC) {
2959 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002960 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002961 return CodeCompletionContext::CCC_TopLevel;
2962
John McCallf312b1e2010-08-26 23:41:50 +00002963 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002964 return CodeCompletionContext::CCC_ClassStructUnion;
2965
John McCallf312b1e2010-08-26 23:41:50 +00002966 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002967 return CodeCompletionContext::CCC_ObjCInterface;
2968
John McCallf312b1e2010-08-26 23:41:50 +00002969 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002970 return CodeCompletionContext::CCC_ObjCImplementation;
2971
John McCallf312b1e2010-08-26 23:41:50 +00002972 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002973 return CodeCompletionContext::CCC_ObjCIvarList;
2974
John McCallf312b1e2010-08-26 23:41:50 +00002975 case Sema::PCC_Template:
2976 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002977 if (S.CurContext->isFileContext())
2978 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00002979 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00002980 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00002981 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00002982
John McCallf312b1e2010-08-26 23:41:50 +00002983 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002984 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002985
John McCallf312b1e2010-08-26 23:41:50 +00002986 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00002987 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
2988 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00002989 return CodeCompletionContext::CCC_ParenthesizedExpression;
2990 else
2991 return CodeCompletionContext::CCC_Expression;
2992
2993 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002994 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002995 return CodeCompletionContext::CCC_Expression;
2996
John McCallf312b1e2010-08-26 23:41:50 +00002997 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002998 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002999
John McCallf312b1e2010-08-26 23:41:50 +00003000 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00003001 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00003002
3003 case Sema::PCC_ParenthesizedExpression:
3004 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003005
3006 case Sema::PCC_LocalDeclarationSpecifiers:
3007 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003008 }
David Blaikie7530c032012-01-17 06:56:22 +00003009
3010 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003011}
3012
Douglas Gregorf6961522010-08-27 21:18:54 +00003013/// \brief If we're in a C++ virtual member function, add completion results
3014/// that invoke the functions we override, since it's common to invoke the
3015/// overridden function as well as adding new functionality.
3016///
3017/// \param S The semantic analysis object for which we are generating results.
3018///
3019/// \param InContext This context in which the nested-name-specifier preceding
3020/// the code-completion point
3021static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3022 ResultBuilder &Results) {
3023 // Look through blocks.
3024 DeclContext *CurContext = S.CurContext;
3025 while (isa<BlockDecl>(CurContext))
3026 CurContext = CurContext->getParent();
3027
3028
3029 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3030 if (!Method || !Method->isVirtual())
3031 return;
3032
3033 // We need to have names for all of the parameters, if we're going to
3034 // generate a forwarding call.
3035 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3036 PEnd = Method->param_end();
3037 P != PEnd;
3038 ++P) {
3039 if (!(*P)->getDeclName())
3040 return;
3041 }
3042
Douglas Gregor8987b232011-09-27 23:30:47 +00003043 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00003044 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3045 MEnd = Method->end_overridden_methods();
3046 M != MEnd; ++M) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003047 CodeCompletionBuilder Builder(Results.getAllocator(),
3048 Results.getCodeCompletionTUInfo());
Douglas Gregorf6961522010-08-27 21:18:54 +00003049 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
3050 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3051 continue;
3052
3053 // If we need a nested-name-specifier, add one now.
3054 if (!InContext) {
3055 NestedNameSpecifier *NNS
3056 = getRequiredQualification(S.Context, CurContext,
3057 Overridden->getDeclContext());
3058 if (NNS) {
3059 std::string Str;
3060 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003061 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003062 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003063 }
3064 } else if (!InContext->Equals(Overridden->getDeclContext()))
3065 continue;
3066
Douglas Gregordae68752011-02-01 22:57:45 +00003067 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003068 Overridden->getNameAsString()));
3069 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003070 bool FirstParam = true;
3071 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3072 PEnd = Method->param_end();
3073 P != PEnd; ++P) {
3074 if (FirstParam)
3075 FirstParam = false;
3076 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003077 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003078
Douglas Gregordae68752011-02-01 22:57:45 +00003079 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003080 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003081 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003082 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3083 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003084 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003085 CXCursor_CXXMethod,
3086 CXAvailability_Available,
3087 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003088 Results.Ignore(Overridden);
3089 }
3090}
3091
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003092void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3093 ModuleIdPath Path) {
3094 typedef CodeCompletionResult Result;
3095 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003096 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003097 CodeCompletionContext::CCC_Other);
3098 Results.EnterNewScope();
3099
3100 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003101 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003102 typedef CodeCompletionResult Result;
3103 if (Path.empty()) {
3104 // Enumerate all top-level modules.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00003105 SmallVector<Module *, 8> Modules;
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003106 PP.getHeaderSearchInfo().collectAllModules(Modules);
3107 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3108 Builder.AddTypedTextChunk(
3109 Builder.getAllocator().CopyString(Modules[I]->Name));
3110 Results.AddResult(Result(Builder.TakeString(),
3111 CCP_Declaration,
3112 CXCursor_NotImplemented,
3113 Modules[I]->isAvailable()
3114 ? CXAvailability_Available
3115 : CXAvailability_NotAvailable));
3116 }
3117 } else {
3118 // Load the named module.
3119 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3120 Module::AllVisible,
3121 /*IsInclusionDirective=*/false);
3122 // Enumerate submodules.
3123 if (Mod) {
3124 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3125 SubEnd = Mod->submodule_end();
3126 Sub != SubEnd; ++Sub) {
3127
3128 Builder.AddTypedTextChunk(
3129 Builder.getAllocator().CopyString((*Sub)->Name));
3130 Results.AddResult(Result(Builder.TakeString(),
3131 CCP_Declaration,
3132 CXCursor_NotImplemented,
3133 (*Sub)->isAvailable()
3134 ? CXAvailability_Available
3135 : CXAvailability_NotAvailable));
3136 }
3137 }
3138 }
3139 Results.ExitScope();
3140 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3141 Results.data(),Results.size());
3142}
3143
Douglas Gregor01dfea02010-01-10 23:08:15 +00003144void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003145 ParserCompletionContext CompletionContext) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003146 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003147 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003148 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003149 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003150
Douglas Gregor01dfea02010-01-10 23:08:15 +00003151 // Determine how to filter results, e.g., so that the names of
3152 // values (functions, enumerators, function templates, etc.) are
3153 // only allowed where we can have an expression.
3154 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003155 case PCC_Namespace:
3156 case PCC_Class:
3157 case PCC_ObjCInterface:
3158 case PCC_ObjCImplementation:
3159 case PCC_ObjCInstanceVariableList:
3160 case PCC_Template:
3161 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003162 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003163 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003164 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3165 break;
3166
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003167 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003168 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003169 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003170 case PCC_ForInit:
3171 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003172 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003173 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3174 else
3175 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003176
David Blaikie4e4d0842012-03-11 07:00:24 +00003177 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003178 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003179 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003180
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003181 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003182 // Unfiltered
3183 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003184 }
3185
Douglas Gregor3cdee122010-08-26 16:36:48 +00003186 // If we are in a C++ non-static member function, check the qualifiers on
3187 // the member function to filter/prioritize the results list.
3188 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3189 if (CurMethod->isInstance())
3190 Results.setObjectTypeQualifiers(
3191 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3192
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003193 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003194 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3195 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003196
Douglas Gregorbca403c2010-01-13 23:51:12 +00003197 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003198 Results.ExitScope();
3199
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003200 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003201 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003202 case PCC_Expression:
3203 case PCC_Statement:
3204 case PCC_RecoveryInFunction:
3205 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003206 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003207 break;
3208
3209 case PCC_Namespace:
3210 case PCC_Class:
3211 case PCC_ObjCInterface:
3212 case PCC_ObjCImplementation:
3213 case PCC_ObjCInstanceVariableList:
3214 case PCC_Template:
3215 case PCC_MemberTemplate:
3216 case PCC_ForInit:
3217 case PCC_Condition:
3218 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003219 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003220 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003221 }
3222
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003223 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003224 AddMacroResults(PP, Results, false);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003225
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003226 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003227 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003228}
3229
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003230static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3231 ParsedType Receiver,
3232 IdentifierInfo **SelIdents,
3233 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003234 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003235 bool IsSuper,
3236 ResultBuilder &Results);
3237
3238void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3239 bool AllowNonIdentifiers,
3240 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003241 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003242 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003243 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003244 AllowNestedNameSpecifiers
3245 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3246 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003247 Results.EnterNewScope();
3248
3249 // Type qualifiers can come after names.
3250 Results.AddResult(Result("const"));
3251 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003252 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003253 Results.AddResult(Result("restrict"));
3254
David Blaikie4e4d0842012-03-11 07:00:24 +00003255 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003256 if (AllowNonIdentifiers) {
3257 Results.AddResult(Result("operator"));
3258 }
3259
3260 // Add nested-name-specifiers.
3261 if (AllowNestedNameSpecifiers) {
3262 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003263 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003264 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3265 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3266 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003267 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003268 }
3269 }
3270 Results.ExitScope();
3271
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003272 // If we're in a context where we might have an expression (rather than a
3273 // declaration), and what we've seen so far is an Objective-C type that could
3274 // be a receiver of a class message, this may be a class message send with
3275 // the initial opening bracket '[' missing. Add appropriate completions.
3276 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
3277 DS.getTypeSpecType() == DeclSpec::TST_typename &&
3278 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
3279 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
3280 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3281 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
3282 DS.getTypeQualifiers() == 0 &&
3283 S &&
3284 (S->getFlags() & Scope::DeclScope) != 0 &&
3285 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3286 Scope::FunctionPrototypeScope |
3287 Scope::AtCatchScope)) == 0) {
3288 ParsedType T = DS.getRepAsType();
3289 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003290 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003291 }
3292
Douglas Gregor4497dd42010-08-24 04:59:56 +00003293 // Note that we intentionally suppress macro results here, since we do not
3294 // encourage using macros to produce the names of entities.
3295
Douglas Gregor52779fb2010-09-23 23:01:17 +00003296 HandleCodeCompleteResults(this, CodeCompleter,
3297 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003298 Results.data(), Results.size());
3299}
3300
Douglas Gregorfb629412010-08-23 21:17:50 +00003301struct Sema::CodeCompleteExpressionData {
3302 CodeCompleteExpressionData(QualType PreferredType = QualType())
3303 : PreferredType(PreferredType), IntegralConstantExpression(false),
3304 ObjCCollection(false) { }
3305
3306 QualType PreferredType;
3307 bool IntegralConstantExpression;
3308 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003309 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003310};
3311
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003312/// \brief Perform code-completion in an expression context when we know what
3313/// type we're looking for.
Douglas Gregorfb629412010-08-23 21:17:50 +00003314void Sema::CodeCompleteExpression(Scope *S,
3315 const CodeCompleteExpressionData &Data) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003316 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003317 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003318 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003319 if (Data.ObjCCollection)
3320 Results.setFilter(&ResultBuilder::IsObjCCollection);
3321 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003322 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003323 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003324 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3325 else
3326 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003327
3328 if (!Data.PreferredType.isNull())
3329 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3330
3331 // Ignore any declarations that we were told that we don't care about.
3332 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3333 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003334
3335 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003336 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3337 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003338
3339 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003340 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003341 Results.ExitScope();
3342
Douglas Gregor590c7d52010-07-08 20:55:51 +00003343 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003344 if (!Data.PreferredType.isNull())
3345 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3346 || Data.PreferredType->isMemberPointerType()
3347 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003348
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003349 if (S->getFnParent() &&
3350 !Data.ObjCCollection &&
3351 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003352 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003353
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003354 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003355 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003356 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003357 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3358 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003359 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003360}
3361
Douglas Gregorac5fd842010-09-18 01:28:11 +00003362void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3363 if (E.isInvalid())
3364 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003365 else if (getLangOpts().ObjC1)
Douglas Gregorac5fd842010-09-18 01:28:11 +00003366 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003367}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003368
Douglas Gregor73449212010-12-09 23:01:55 +00003369/// \brief The set of properties that have already been added, referenced by
3370/// property name.
3371typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3372
Douglas Gregorb92a4082012-06-12 13:44:08 +00003373/// \brief Retrieve the container definition, if any?
3374static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3375 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3376 if (Interface->hasDefinition())
3377 return Interface->getDefinition();
3378
3379 return Interface;
3380 }
3381
3382 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3383 if (Protocol->hasDefinition())
3384 return Protocol->getDefinition();
3385
3386 return Protocol;
3387 }
3388 return Container;
3389}
3390
3391static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003392 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003393 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003394 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003395 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003396 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003397 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003398
Douglas Gregorb92a4082012-06-12 13:44:08 +00003399 // Retrieve the definition.
3400 Container = getContainerDef(Container);
3401
Douglas Gregor95ac6552009-11-18 01:29:26 +00003402 // Add properties in this container.
3403 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3404 PEnd = Container->prop_end();
3405 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003406 ++P) {
3407 if (AddedProperties.insert(P->getIdentifier()))
David Blaikie581deb32012-06-06 20:45:41 +00003408 Results.MaybeAddResult(Result(*P, 0), CurContext);
Douglas Gregor73449212010-12-09 23:01:55 +00003409 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003410
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003411 // Add nullary methods
3412 if (AllowNullaryMethods) {
3413 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003414 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003415 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3416 MEnd = Container->meth_end();
3417 M != MEnd; ++M) {
3418 if (M->getSelector().isUnarySelector())
3419 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3420 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003421 CodeCompletionBuilder Builder(Results.getAllocator(),
3422 Results.getCodeCompletionTUInfo());
David Blaikie581deb32012-06-06 20:45:41 +00003423 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003424 Builder.AddTypedTextChunk(
3425 Results.getAllocator().CopyString(Name->getName()));
3426
David Blaikie581deb32012-06-06 20:45:41 +00003427 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregorba103062012-03-27 23:34:16 +00003428 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003429 CurContext);
3430 }
3431 }
3432 }
3433
3434
Douglas Gregor95ac6552009-11-18 01:29:26 +00003435 // Add properties in referenced protocols.
3436 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3437 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3438 PEnd = Protocol->protocol_end();
3439 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003440 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3441 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003442 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003443 if (AllowCategories) {
3444 // Look through categories.
Douglas Gregord3297242013-01-16 23:00:23 +00003445 for (ObjCInterfaceDecl::known_categories_iterator
3446 Cat = IFace->known_categories_begin(),
3447 CatEnd = IFace->known_categories_end();
3448 Cat != CatEnd; ++Cat)
3449 AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003450 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003451 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003452
3453 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003454 for (ObjCInterfaceDecl::all_protocol_iterator
3455 I = IFace->all_referenced_protocol_begin(),
3456 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003457 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3458 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003459
3460 // Look in the superclass.
3461 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003462 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3463 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003464 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003465 } else if (const ObjCCategoryDecl *Category
3466 = dyn_cast<ObjCCategoryDecl>(Container)) {
3467 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003468 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3469 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003470 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003471 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3472 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003473 }
3474}
3475
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003476void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003477 SourceLocation OpLoc,
3478 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003479 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003480 return;
3481
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003482 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3483 if (ConvertedBase.isInvalid())
3484 return;
3485 Base = ConvertedBase.get();
3486
John McCall0a2c5e22010-08-25 06:19:51 +00003487 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003488
Douglas Gregor81b747b2009-09-17 21:32:03 +00003489 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003490
3491 if (IsArrow) {
3492 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3493 BaseType = Ptr->getPointeeType();
3494 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003495 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003496 else
3497 return;
3498 }
3499
Douglas Gregor3da626b2011-07-07 16:03:39 +00003500 enum CodeCompletionContext::Kind contextKind;
3501
3502 if (IsArrow) {
3503 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3504 }
3505 else {
3506 if (BaseType->isObjCObjectPointerType() ||
3507 BaseType->isObjCObjectOrInterfaceType()) {
3508 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3509 }
3510 else {
3511 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3512 }
3513 }
3514
Douglas Gregor218937c2011-02-01 19:23:04 +00003515 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003516 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003517 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003518 BaseType),
3519 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003520 Results.EnterNewScope();
3521 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003522 // Indicate that we are performing a member access, and the cv-qualifiers
3523 // for the base object type.
3524 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3525
Douglas Gregor95ac6552009-11-18 01:29:26 +00003526 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003527 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003528 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003529 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3530 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003531
David Blaikie4e4d0842012-03-11 07:00:24 +00003532 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003533 if (!Results.empty()) {
3534 // The "template" keyword can follow "->" or "." in the grammar.
3535 // However, we only want to suggest the template keyword if something
3536 // is dependent.
3537 bool IsDependent = BaseType->isDependentType();
3538 if (!IsDependent) {
3539 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3540 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3541 IsDependent = Ctx->isDependentContext();
3542 break;
3543 }
3544 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003545
Douglas Gregor95ac6552009-11-18 01:29:26 +00003546 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003547 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003548 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003549 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003550 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3551 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003552 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003553
3554 // Add property results based on our interface.
3555 const ObjCObjectPointerType *ObjCPtr
3556 = BaseType->getAsObjCInterfacePointerType();
3557 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003558 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3559 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003560 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003561
3562 // Add properties from the protocols in a qualified interface.
3563 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3564 E = ObjCPtr->qual_end();
3565 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003566 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3567 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003568 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003569 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003570 // Objective-C instance variable access.
3571 ObjCInterfaceDecl *Class = 0;
3572 if (const ObjCObjectPointerType *ObjCPtr
3573 = BaseType->getAs<ObjCObjectPointerType>())
3574 Class = ObjCPtr->getInterfaceDecl();
3575 else
John McCallc12c5bb2010-05-15 11:32:37 +00003576 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003577
3578 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003579 if (Class) {
3580 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3581 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003582 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3583 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003584 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003585 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003586
3587 // FIXME: How do we cope with isa?
3588
3589 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003590
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003591 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003592 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003593 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003594 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003595}
3596
Douglas Gregor374929f2009-09-18 15:37:17 +00003597void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3598 if (!CodeCompleter)
3599 return;
3600
Douglas Gregor86d9a522009-09-21 16:56:56 +00003601 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003602 enum CodeCompletionContext::Kind ContextKind
3603 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003604 switch ((DeclSpec::TST)TagSpec) {
3605 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003606 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003607 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003608 break;
3609
3610 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003611 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003612 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003613 break;
3614
3615 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003616 case DeclSpec::TST_class:
Joao Matos6666ed42012-08-31 18:45:21 +00003617 case DeclSpec::TST_interface:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003618 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003619 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003620 break;
3621
3622 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003623 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003624 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003625
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003626 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3627 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003628 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003629
3630 // First pass: look for tags.
3631 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003632 LookupVisibleDecls(S, LookupTagName, Consumer,
3633 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003634
Douglas Gregor8071e422010-08-15 06:18:01 +00003635 if (CodeCompleter->includeGlobals()) {
3636 // Second pass: look for nested name specifiers.
3637 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3638 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3639 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003640
Douglas Gregor52779fb2010-09-23 23:01:17 +00003641 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003642 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003643}
3644
Douglas Gregor1a480c42010-08-27 17:35:51 +00003645void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003646 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003647 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003648 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003649 Results.EnterNewScope();
3650 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3651 Results.AddResult("const");
3652 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3653 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003654 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003655 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3656 Results.AddResult("restrict");
3657 Results.ExitScope();
3658 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003659 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003660 Results.data(), Results.size());
3661}
3662
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003663void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003664 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003665 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003666
John McCall781472f2010-08-25 08:40:02 +00003667 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003668 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3669 if (!type->isEnumeralType()) {
3670 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003671 Data.IntegralConstantExpression = true;
3672 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003673 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003674 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003675
3676 // Code-complete the cases of a switch statement over an enumeration type
3677 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003678 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003679 if (EnumDecl *Def = Enum->getDefinition())
3680 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003681
3682 // Determine which enumerators we have already seen in the switch statement.
3683 // FIXME: Ideally, we would also be able to look *past* the code-completion
3684 // token, in case we are code-completing in the middle of the switch and not
3685 // at the end. However, we aren't able to do so at the moment.
3686 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003687 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003688 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3689 SC = SC->getNextSwitchCase()) {
3690 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3691 if (!Case)
3692 continue;
3693
3694 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3695 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3696 if (EnumConstantDecl *Enumerator
3697 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3698 // We look into the AST of the case statement to determine which
3699 // enumerator was named. Alternatively, we could compute the value of
3700 // the integral constant expression, then compare it against the
3701 // values of each enumerator. However, value-based approach would not
3702 // work as well with C++ templates where enumerators declared within a
3703 // template are type- and value-dependent.
3704 EnumeratorsSeen.insert(Enumerator);
3705
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003706 // If this is a qualified-id, keep track of the nested-name-specifier
3707 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003708 //
3709 // switch (TagD.getKind()) {
3710 // case TagDecl::TK_enum:
3711 // break;
3712 // case XXX
3713 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003714 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003715 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3716 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003717 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003718 }
3719 }
3720
David Blaikie4e4d0842012-03-11 07:00:24 +00003721 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003722 // If there are no prior enumerators in C++, check whether we have to
3723 // qualify the names of the enumerators that we suggest, because they
3724 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003725 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003726 }
3727
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003728 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003729 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003730 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003731 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003732 Results.EnterNewScope();
3733 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3734 EEnd = Enum->enumerator_end();
3735 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003736 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003737 continue;
3738
David Blaikie581deb32012-06-06 20:45:41 +00003739 CodeCompletionResult R(*E, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003740 R.Priority = CCP_EnumInCase;
3741 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003742 }
3743 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003744
Douglas Gregor3da626b2011-07-07 16:03:39 +00003745 //We need to make sure we're setting the right context,
3746 //so only say we include macros if the code completer says we do
3747 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3748 if (CodeCompleter->includeMacros()) {
Douglas Gregor3644d972012-10-09 16:01:50 +00003749 AddMacroResults(PP, Results, false);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003750 kind = CodeCompletionContext::CCC_OtherWithMacros;
3751 }
3752
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003753 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003754 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003755 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003756}
3757
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003758namespace {
3759 struct IsBetterOverloadCandidate {
3760 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003761 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003762
3763 public:
John McCall5769d612010-02-08 23:07:23 +00003764 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3765 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003766
3767 bool
3768 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003769 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003770 }
3771 };
3772}
3773
Ahmed Charles13a140c2012-02-25 11:00:22 +00003774static bool anyNullArguments(llvm::ArrayRef<Expr*> Args) {
3775 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003776 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003777
3778 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003779 if (!Args[I])
3780 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003781
Douglas Gregord28dcd72010-05-30 06:10:08 +00003782 return false;
3783}
3784
Richard Trieuf81e5a92011-09-09 02:00:50 +00003785void Sema::CodeCompleteCall(Scope *S, Expr *FnIn,
Ahmed Charles13a140c2012-02-25 11:00:22 +00003786 llvm::ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003787 if (!CodeCompleter)
3788 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003789
3790 // When we're code-completing for a call, we fall back to ordinary
3791 // name code-completion whenever we can't produce specific
3792 // results. We may want to revisit this strategy in the future,
3793 // e.g., by merging the two kinds of results.
3794
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003795 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003796
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003797 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003798 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3799 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003800 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003801 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003802 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003803
John McCall3b4294e2009-12-16 12:17:52 +00003804 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003805 SourceLocation Loc = Fn->getExprLoc();
3806 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003807
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003808 // FIXME: What if we're calling something that isn't a function declaration?
3809 // FIXME: What if we're calling a pseudo-destructor?
3810 // FIXME: What if we're calling a member function?
3811
Douglas Gregorc0265402010-01-21 15:46:19 +00003812 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003813 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003814
John McCall3b4294e2009-12-16 12:17:52 +00003815 Expr *NakedFn = Fn->IgnoreParenCasts();
3816 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003817 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003818 /*PartialOverloading=*/ true);
3819 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3820 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003821 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003822 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003823 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003824 Results.push_back(ResultCandidate(FDecl));
3825 else
John McCall86820f52010-01-26 01:37:31 +00003826 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003827 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3828 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003829 }
John McCall3b4294e2009-12-16 12:17:52 +00003830 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003831
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003832 QualType ParamType;
3833
Douglas Gregorc0265402010-01-21 15:46:19 +00003834 if (!CandidateSet.empty()) {
3835 // Sort the overload candidate set by placing the best overloads first.
3836 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003837 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003838
Douglas Gregorc0265402010-01-21 15:46:19 +00003839 // Add the remaining viable overload candidates as code-completion reslults.
3840 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3841 CandEnd = CandidateSet.end();
3842 Cand != CandEnd; ++Cand) {
3843 if (Cand->Viable)
3844 Results.push_back(ResultCandidate(Cand->Function));
3845 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003846
3847 // From the viable candidates, try to determine the type of this parameter.
3848 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3849 if (const FunctionType *FType = Results[I].getFunctionType())
3850 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003851 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003852 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003853 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003854 else if (!Context.hasSameUnqualifiedType(
3855 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003856 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003857 ParamType = QualType();
3858 break;
3859 }
3860 }
3861 }
3862 } else {
3863 // Try to determine the parameter type from the type of the expression
3864 // being called.
3865 QualType FunctionType = Fn->getType();
3866 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3867 FunctionType = Ptr->getPointeeType();
3868 else if (const BlockPointerType *BlockPtr
3869 = FunctionType->getAs<BlockPointerType>())
3870 FunctionType = BlockPtr->getPointeeType();
3871 else if (const MemberPointerType *MemPtr
3872 = FunctionType->getAs<MemberPointerType>())
3873 FunctionType = MemPtr->getPointeeType();
3874
3875 if (const FunctionProtoType *Proto
3876 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003877 if (Args.size() < Proto->getNumArgs())
3878 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003879 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003880 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003881
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003882 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003883 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003884 else
3885 CodeCompleteExpression(S, ParamType);
3886
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003887 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003888 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003889 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003890}
3891
John McCalld226f652010-08-21 09:40:31 +00003892void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3893 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003894 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003895 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003896 return;
3897 }
3898
3899 CodeCompleteExpression(S, VD->getType());
3900}
3901
3902void Sema::CodeCompleteReturn(Scope *S) {
3903 QualType ResultType;
3904 if (isa<BlockDecl>(CurContext)) {
3905 if (BlockScopeInfo *BSI = getCurBlock())
3906 ResultType = BSI->ReturnType;
3907 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3908 ResultType = Function->getResultType();
3909 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3910 ResultType = Method->getResultType();
3911
3912 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003913 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003914 else
3915 CodeCompleteExpression(S, ResultType);
3916}
3917
Douglas Gregord2d8be62011-07-30 08:36:53 +00003918void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregord2d8be62011-07-30 08:36:53 +00003919 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003920 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003921 mapCodeCompletionContext(*this, PCC_Statement));
3922 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3923 Results.EnterNewScope();
3924
3925 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3926 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3927 CodeCompleter->includeGlobals());
3928
3929 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
3930
3931 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003932 CodeCompletionBuilder Builder(Results.getAllocator(),
3933 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00003934 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00003935 if (Results.includeCodePatterns()) {
3936 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3937 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3938 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3939 Builder.AddPlaceholderChunk("statements");
3940 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3941 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3942 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003943 Results.AddResult(Builder.TakeString());
3944
3945 // "else if" block
3946 Builder.AddTypedTextChunk("else");
3947 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3948 Builder.AddTextChunk("if");
3949 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3950 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00003951 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00003952 Builder.AddPlaceholderChunk("condition");
3953 else
3954 Builder.AddPlaceholderChunk("expression");
3955 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00003956 if (Results.includeCodePatterns()) {
3957 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3958 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3959 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3960 Builder.AddPlaceholderChunk("statements");
3961 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
3962 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3963 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00003964 Results.AddResult(Builder.TakeString());
3965
3966 Results.ExitScope();
3967
3968 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003969 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003970
3971 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003972 AddMacroResults(PP, Results, false);
Douglas Gregord2d8be62011-07-30 08:36:53 +00003973
3974 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3975 Results.data(),Results.size());
3976}
3977
Richard Trieuf81e5a92011-09-09 02:00:50 +00003978void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003979 if (LHS)
3980 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3981 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003982 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003983}
3984
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003985void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003986 bool EnteringContext) {
3987 if (!SS.getScopeRep() || !CodeCompleter)
3988 return;
3989
Douglas Gregor86d9a522009-09-21 16:56:56 +00003990 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3991 if (!Ctx)
3992 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003993
3994 // Try to instantiate any non-dependent declaration contexts before
3995 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003996 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003997 return;
3998
Douglas Gregor218937c2011-02-01 19:23:04 +00003999 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004000 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004001 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00004002 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00004003
Douglas Gregor86d9a522009-09-21 16:56:56 +00004004 // The "template" keyword can follow "::" in the grammar, but only
4005 // put it into the grammar if the nested-name-specifier is dependent.
4006 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
4007 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00004008 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00004009
4010 // Add calls to overridden virtual functions, if there are any.
4011 //
4012 // FIXME: This isn't wonderful, because we don't know whether we're actually
4013 // in a context that permits expressions. This is a general issue with
4014 // qualified-id completions.
4015 if (!EnteringContext)
4016 MaybeAddOverrideCalls(*this, Ctx, Results);
4017 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004018
Douglas Gregorf6961522010-08-27 21:18:54 +00004019 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4020 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4021
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004022 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00004023 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004024 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00004025}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004026
4027void Sema::CodeCompleteUsing(Scope *S) {
4028 if (!CodeCompleter)
4029 return;
4030
Douglas Gregor218937c2011-02-01 19:23:04 +00004031 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004032 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004033 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4034 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004035 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004036
4037 // If we aren't in class scope, we could see the "namespace" keyword.
4038 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00004039 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004040
4041 // After "using", we can see anything that would start a
4042 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004043 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004044 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4045 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004046 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004047
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004048 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004049 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004050 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004051}
4052
4053void Sema::CodeCompleteUsingDirective(Scope *S) {
4054 if (!CodeCompleter)
4055 return;
4056
Douglas Gregor86d9a522009-09-21 16:56:56 +00004057 // After "using namespace", we expect to see a namespace name or namespace
4058 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004059 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004060 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004061 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004062 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004063 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004064 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004065 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4066 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004067 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004068 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004069 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004070 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004071}
4072
4073void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4074 if (!CodeCompleter)
4075 return;
4076
Douglas Gregor86d9a522009-09-21 16:56:56 +00004077 DeclContext *Ctx = (DeclContext *)S->getEntity();
4078 if (!S->getParent())
4079 Ctx = Context.getTranslationUnitDecl();
4080
Douglas Gregor52779fb2010-09-23 23:01:17 +00004081 bool SuppressedGlobalResults
4082 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4083
Douglas Gregor218937c2011-02-01 19:23:04 +00004084 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004085 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004086 SuppressedGlobalResults
4087 ? CodeCompletionContext::CCC_Namespace
4088 : CodeCompletionContext::CCC_Other,
4089 &ResultBuilder::IsNamespace);
4090
4091 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004092 // We only want to see those namespaces that have already been defined
4093 // within this scope, because its likely that the user is creating an
4094 // extended namespace declaration. Keep track of the most recent
4095 // definition of each namespace.
4096 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4097 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4098 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4099 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004100 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004101
4102 // Add the most recent definition (or extended definition) of each
4103 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004104 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004105 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004106 NS = OrigToLatest.begin(),
4107 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004108 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00004109 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004110 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004111 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004112 }
4113
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004114 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004115 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004116 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004117}
4118
4119void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4120 if (!CodeCompleter)
4121 return;
4122
Douglas Gregor86d9a522009-09-21 16:56:56 +00004123 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004124 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004125 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004126 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004127 &ResultBuilder::IsNamespaceOrAlias);
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 Gregore6b1bb62010-08-11 21:23:17 +00004131 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004132 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004133 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004134}
4135
Douglas Gregored8d3222009-09-18 20:05:18 +00004136void Sema::CodeCompleteOperatorName(Scope *S) {
4137 if (!CodeCompleter)
4138 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004139
John McCall0a2c5e22010-08-25 06:19:51 +00004140 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004141 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004142 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004143 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004144 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004145 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004146
Douglas Gregor86d9a522009-09-21 16:56:56 +00004147 // Add the names of overloadable operators.
4148#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4149 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004150 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004151#include "clang/Basic/OperatorKinds.def"
4152
4153 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004154 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004155 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004156 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4157 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004158
4159 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004160 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004161 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004162
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004163 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004164 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004165 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004166}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004167
Douglas Gregor0133f522010-08-28 00:00:50 +00004168void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00004169 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00004170 unsigned NumInitializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004171 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004172 CXXConstructorDecl *Constructor
4173 = static_cast<CXXConstructorDecl *>(ConstructorD);
4174 if (!Constructor)
4175 return;
4176
Douglas Gregor218937c2011-02-01 19:23:04 +00004177 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004178 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004179 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004180 Results.EnterNewScope();
4181
4182 // Fill in any already-initialized fields or base classes.
4183 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4184 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
4185 for (unsigned I = 0; I != NumInitializers; ++I) {
4186 if (Initializers[I]->isBaseInitializer())
4187 InitializedBases.insert(
4188 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4189 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004190 InitializedFields.insert(cast<FieldDecl>(
4191 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004192 }
4193
4194 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004195 CodeCompletionBuilder Builder(Results.getAllocator(),
4196 Results.getCodeCompletionTUInfo());
Douglas Gregor0c431c82010-08-29 19:27:27 +00004197 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00004198 CXXRecordDecl *ClassDecl = Constructor->getParent();
4199 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4200 BaseEnd = ClassDecl->bases_end();
4201 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004202 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4203 SawLastInitializer
4204 = NumInitializers > 0 &&
4205 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4206 Context.hasSameUnqualifiedType(Base->getType(),
4207 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004208 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004209 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004210
Douglas Gregor218937c2011-02-01 19:23:04 +00004211 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004212 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004213 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004214 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4215 Builder.AddPlaceholderChunk("args");
4216 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4217 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004218 SawLastInitializer? CCP_NextInitializer
4219 : CCP_MemberDeclaration));
4220 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004221 }
4222
4223 // Add completions for virtual base classes.
4224 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4225 BaseEnd = ClassDecl->vbases_end();
4226 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004227 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4228 SawLastInitializer
4229 = NumInitializers > 0 &&
4230 Initializers[NumInitializers - 1]->isBaseInitializer() &&
4231 Context.hasSameUnqualifiedType(Base->getType(),
4232 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004233 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004234 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004235
Douglas Gregor218937c2011-02-01 19:23:04 +00004236 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004237 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004238 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004239 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4240 Builder.AddPlaceholderChunk("args");
4241 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4242 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004243 SawLastInitializer? CCP_NextInitializer
4244 : CCP_MemberDeclaration));
4245 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004246 }
4247
4248 // Add completions for members.
4249 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4250 FieldEnd = ClassDecl->field_end();
4251 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004252 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4253 SawLastInitializer
4254 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00004255 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
David Blaikie581deb32012-06-06 20:45:41 +00004256 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004257 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004258 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004259
4260 if (!Field->getDeclName())
4261 continue;
4262
Douglas Gregordae68752011-02-01 22:57:45 +00004263 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004264 Field->getIdentifier()->getName()));
4265 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4266 Builder.AddPlaceholderChunk("args");
4267 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4268 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004269 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004270 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004271 CXCursor_MemberRef,
4272 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004273 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004274 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004275 }
4276 Results.ExitScope();
4277
Douglas Gregor52779fb2010-09-23 23:01:17 +00004278 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004279 Results.data(), Results.size());
4280}
4281
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004282/// \brief Determine whether this scope denotes a namespace.
4283static bool isNamespaceScope(Scope *S) {
4284 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4285 if (!DC)
4286 return false;
4287
4288 return DC->isFileContext();
4289}
4290
4291void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4292 bool AfterAmpersand) {
4293 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004294 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004295 CodeCompletionContext::CCC_Other);
4296 Results.EnterNewScope();
4297
4298 // Note what has already been captured.
4299 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4300 bool IncludedThis = false;
4301 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4302 CEnd = Intro.Captures.end();
4303 C != CEnd; ++C) {
4304 if (C->Kind == LCK_This) {
4305 IncludedThis = true;
4306 continue;
4307 }
4308
4309 Known.insert(C->Id);
4310 }
4311
4312 // Look for other capturable variables.
4313 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4314 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4315 D != DEnd; ++D) {
4316 VarDecl *Var = dyn_cast<VarDecl>(*D);
4317 if (!Var ||
4318 !Var->hasLocalStorage() ||
4319 Var->hasAttr<BlocksAttr>())
4320 continue;
4321
4322 if (Known.insert(Var->getIdentifier()))
4323 Results.AddResult(CodeCompletionResult(Var), CurContext, 0, false);
4324 }
4325 }
4326
4327 // Add 'this', if it would be valid.
4328 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4329 addThisCompletion(*this, Results);
4330
4331 Results.ExitScope();
4332
4333 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4334 Results.data(), Results.size());
4335}
4336
James Dennetta40f7922012-06-14 03:11:41 +00004337/// Macro that optionally prepends an "@" to the string literal passed in via
4338/// Keyword, depending on whether NeedAt is true or false.
4339#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4340
Douglas Gregorbca403c2010-01-13 23:51:12 +00004341static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004342 ResultBuilder &Results,
4343 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004344 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004345 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004346 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004347
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004348 CodeCompletionBuilder Builder(Results.getAllocator(),
4349 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004350 if (LangOpts.ObjC2) {
4351 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004352 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004353 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4354 Builder.AddPlaceholderChunk("property");
4355 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004356
4357 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004358 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4360 Builder.AddPlaceholderChunk("property");
4361 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004362 }
4363}
4364
Douglas Gregorbca403c2010-01-13 23:51:12 +00004365static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004366 ResultBuilder &Results,
4367 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004368 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004369
4370 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004371 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004372
4373 if (LangOpts.ObjC2) {
4374 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004375 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004376
4377 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004378 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004379
4380 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004381 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004382 }
4383}
4384
Douglas Gregorbca403c2010-01-13 23:51:12 +00004385static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004386 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004387 CodeCompletionBuilder Builder(Results.getAllocator(),
4388 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004389
4390 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004391 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004392 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4393 Builder.AddPlaceholderChunk("name");
4394 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004395
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004396 if (Results.includeCodePatterns()) {
4397 // @interface name
4398 // FIXME: Could introduce the whole pattern, including superclasses and
4399 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004400 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004401 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4402 Builder.AddPlaceholderChunk("class");
4403 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004404
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004405 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004406 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004407 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4408 Builder.AddPlaceholderChunk("protocol");
4409 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004410
4411 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004412 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004413 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4414 Builder.AddPlaceholderChunk("class");
4415 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004416 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004417
4418 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004419 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004420 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4421 Builder.AddPlaceholderChunk("alias");
4422 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4423 Builder.AddPlaceholderChunk("class");
4424 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004425}
4426
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004427void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004428 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004429 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004430 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004431 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004432 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004433 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004434 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004435 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004436 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004437 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004438 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004439 HandleCodeCompleteResults(this, CodeCompleter,
4440 CodeCompletionContext::CCC_Other,
4441 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004442}
4443
Douglas Gregorbca403c2010-01-13 23:51:12 +00004444static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004445 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004446 CodeCompletionBuilder Builder(Results.getAllocator(),
4447 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004448
4449 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004450 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004451 if (Results.getSema().getLangOpts().CPlusPlus ||
4452 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004453 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004454 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004455 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004456 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4457 Builder.AddPlaceholderChunk("type-name");
4458 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4459 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004460
4461 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004462 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004463 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004464 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4465 Builder.AddPlaceholderChunk("protocol-name");
4466 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4467 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004468
4469 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004470 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004471 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004472 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4473 Builder.AddPlaceholderChunk("selector");
4474 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4475 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004476
4477 // @"string"
4478 Builder.AddResultTypeChunk("NSString *");
4479 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4480 Builder.AddPlaceholderChunk("string");
4481 Builder.AddTextChunk("\"");
4482 Results.AddResult(Result(Builder.TakeString()));
4483
Douglas Gregor79615892012-07-17 23:24:47 +00004484 // @[objects, ...]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004485 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004486 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004487 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004488 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4489 Results.AddResult(Result(Builder.TakeString()));
4490
Douglas Gregor79615892012-07-17 23:24:47 +00004491 // @{key : object, ...}
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004492 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004493 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004494 Builder.AddPlaceholderChunk("key");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004495 Builder.AddChunk(CodeCompletionString::CK_Colon);
4496 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4497 Builder.AddPlaceholderChunk("object, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004498 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4499 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004500
Douglas Gregor79615892012-07-17 23:24:47 +00004501 // @(expression)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004502 Builder.AddResultTypeChunk("id");
4503 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004504 Builder.AddPlaceholderChunk("expression");
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004505 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4506 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004507}
4508
Douglas Gregorbca403c2010-01-13 23:51:12 +00004509static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004510 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004511 CodeCompletionBuilder Builder(Results.getAllocator(),
4512 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004513
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004514 if (Results.includeCodePatterns()) {
4515 // @try { statements } @catch ( declaration ) { statements } @finally
4516 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004517 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004518 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4519 Builder.AddPlaceholderChunk("statements");
4520 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4521 Builder.AddTextChunk("@catch");
4522 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4523 Builder.AddPlaceholderChunk("parameter");
4524 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4525 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4526 Builder.AddPlaceholderChunk("statements");
4527 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4528 Builder.AddTextChunk("@finally");
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 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004536 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004537 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4538 Builder.AddPlaceholderChunk("expression");
4539 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004540
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004541 if (Results.includeCodePatterns()) {
4542 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004543 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004544 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4545 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4546 Builder.AddPlaceholderChunk("expression");
4547 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4548 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4549 Builder.AddPlaceholderChunk("statements");
4550 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4551 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004552 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004553}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004554
Douglas Gregorbca403c2010-01-13 23:51:12 +00004555static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004556 ResultBuilder &Results,
4557 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004558 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004559 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4560 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4561 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004562 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004563 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004564}
4565
4566void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004567 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004568 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004569 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004570 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004571 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004572 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004573 HandleCodeCompleteResults(this, CodeCompleter,
4574 CodeCompletionContext::CCC_Other,
4575 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004576}
4577
4578void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004579 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004580 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004581 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004582 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004583 AddObjCStatementResults(Results, false);
4584 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004585 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004586 HandleCodeCompleteResults(this, CodeCompleter,
4587 CodeCompletionContext::CCC_Other,
4588 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004589}
4590
4591void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004592 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004593 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004594 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004595 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004596 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004597 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004598 HandleCodeCompleteResults(this, CodeCompleter,
4599 CodeCompletionContext::CCC_Other,
4600 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004601}
4602
Douglas Gregor988358f2009-11-19 00:14:45 +00004603/// \brief Determine whether the addition of the given flag to an Objective-C
4604/// property's attributes will cause a conflict.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004605static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregor988358f2009-11-19 00:14:45 +00004606 // Check if we've already added this flag.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004607 if (Attributes & NewFlag)
Douglas Gregor988358f2009-11-19 00:14:45 +00004608 return true;
4609
Bill Wendlingad017fa2012-12-20 19:22:21 +00004610 Attributes |= NewFlag;
Douglas Gregor988358f2009-11-19 00:14:45 +00004611
4612 // Check for collisions with "readonly".
Bill Wendlingad017fa2012-12-20 19:22:21 +00004613 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4614 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregor988358f2009-11-19 00:14:45 +00004615 return true;
4616
Jordan Rosed7403a72012-08-20 20:01:13 +00004617 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004618 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004619 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004620 ObjCDeclSpec::DQ_PR_copy |
Jordan Rosed7403a72012-08-20 20:01:13 +00004621 ObjCDeclSpec::DQ_PR_retain |
4622 ObjCDeclSpec::DQ_PR_strong |
4623 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregor988358f2009-11-19 00:14:45 +00004624 if (AssignCopyRetMask &&
4625 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004626 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004627 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004628 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004629 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
4630 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregor988358f2009-11-19 00:14:45 +00004631 return true;
4632
4633 return false;
4634}
4635
Douglas Gregora93b1082009-11-18 23:08:07 +00004636void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004637 if (!CodeCompleter)
4638 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004639
Bill Wendlingad017fa2012-12-20 19:22:21 +00004640 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroffece8e712009-10-08 21:55:05 +00004641
Douglas Gregor218937c2011-02-01 19:23:04 +00004642 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004643 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004644 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004645 Results.EnterNewScope();
Bill Wendlingad017fa2012-12-20 19:22:21 +00004646 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004647 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004648 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004649 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004650 if (!ObjCPropertyFlagConflicts(Attributes,
John McCallf85e1932011-06-15 23:02:42 +00004651 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4652 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004653 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004654 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004655 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004656 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004657 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCallf85e1932011-06-15 23:02:42 +00004658 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004659 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004660 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004661 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004662 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004663 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004664 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rosed7403a72012-08-20 20:01:13 +00004665
4666 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall0a7dd782012-08-21 02:47:43 +00004667 if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendlingad017fa2012-12-20 19:22:21 +00004668 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rosed7403a72012-08-20 20:01:13 +00004669 Results.AddResult(CodeCompletionResult("weak"));
4670
Bill Wendlingad017fa2012-12-20 19:22:21 +00004671 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004672 CodeCompletionBuilder Setter(Results.getAllocator(),
4673 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004674 Setter.AddTypedTextChunk("setter");
4675 Setter.AddTextChunk(" = ");
4676 Setter.AddPlaceholderChunk("method");
4677 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004678 }
Bill Wendlingad017fa2012-12-20 19:22:21 +00004679 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004680 CodeCompletionBuilder Getter(Results.getAllocator(),
4681 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004682 Getter.AddTypedTextChunk("getter");
4683 Getter.AddTextChunk(" = ");
4684 Getter.AddPlaceholderChunk("method");
4685 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004686 }
Steve Naroffece8e712009-10-08 21:55:05 +00004687 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004688 HandleCodeCompleteResults(this, CodeCompleter,
4689 CodeCompletionContext::CCC_Other,
4690 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004691}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004692
James Dennettde23c7e2012-06-17 05:33:25 +00004693/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregor4ad96852009-11-19 07:41:15 +00004694/// via code completion.
4695enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004696 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4697 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4698 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004699};
4700
Douglas Gregor458433d2010-08-26 15:07:07 +00004701static bool isAcceptableObjCSelector(Selector Sel,
4702 ObjCMethodKind WantKind,
4703 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004704 unsigned NumSelIdents,
4705 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004706 if (NumSelIdents > Sel.getNumArgs())
4707 return false;
4708
4709 switch (WantKind) {
4710 case MK_Any: break;
4711 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4712 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4713 }
4714
Douglas Gregorcf544262010-11-17 21:36:08 +00004715 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4716 return false;
4717
Douglas Gregor458433d2010-08-26 15:07:07 +00004718 for (unsigned I = 0; I != NumSelIdents; ++I)
4719 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4720 return false;
4721
4722 return true;
4723}
4724
Douglas Gregor4ad96852009-11-19 07:41:15 +00004725static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4726 ObjCMethodKind WantKind,
4727 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004728 unsigned NumSelIdents,
4729 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004730 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004731 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004732}
Douglas Gregord36adf52010-09-16 16:06:31 +00004733
4734namespace {
4735 /// \brief A set of selectors, which is used to avoid introducing multiple
4736 /// completions with the same selector into the result set.
4737 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4738}
4739
Douglas Gregor36ecb042009-11-17 23:22:23 +00004740/// \brief Add all of the Objective-C methods in the given Objective-C
4741/// container to the set of results.
4742///
4743/// The container will be a class, protocol, category, or implementation of
4744/// any of the above. This mether will recurse to include methods from
4745/// the superclasses of classes along with their categories, protocols, and
4746/// implementations.
4747///
4748/// \param Container the container in which we'll look to find methods.
4749///
James Dennetta40f7922012-06-14 03:11:41 +00004750/// \param WantInstanceMethods Whether to add instance methods (only); if
4751/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004752///
4753/// \param CurContext the context in which we're performing the lookup that
4754/// finds methods.
4755///
Douglas Gregorcf544262010-11-17 21:36:08 +00004756/// \param AllowSameLength Whether we allow a method to be added to the list
4757/// when it has the same number of parameters as we have selector identifiers.
4758///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004759/// \param Results the structure into which we'll add results.
4760static void AddObjCMethods(ObjCContainerDecl *Container,
4761 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004762 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004763 IdentifierInfo **SelIdents,
4764 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004765 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004766 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004767 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004768 ResultBuilder &Results,
4769 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004770 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004771 Container = getContainerDef(Container);
Douglas Gregor5824b802013-01-30 06:58:39 +00004772 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
4773 bool isRootClass = IFace && !IFace->getSuperClass();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004774 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4775 MEnd = Container->meth_end();
4776 M != MEnd; ++M) {
Douglas Gregor5824b802013-01-30 06:58:39 +00004777 // The instance methods on the root class can be messaged via the
4778 // metaclass.
4779 if (M->isInstanceMethod() == WantInstanceMethods ||
4780 (isRootClass && !WantInstanceMethods)) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004781 // Check whether the selector identifiers we've been given are a
4782 // subset of the identifiers for this particular method.
David Blaikie581deb32012-06-06 20:45:41 +00004783 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004784 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004785 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004786
David Blaikie262bc182012-04-30 02:36:29 +00004787 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004788 continue;
4789
David Blaikie581deb32012-06-06 20:45:41 +00004790 Result R = Result(*M, 0);
Douglas Gregord3c68542009-11-19 01:08:35 +00004791 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004792 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004793 if (!InOriginalClass)
4794 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004795 Results.MaybeAddResult(R, CurContext);
4796 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004797 }
4798
Douglas Gregore396c7b2010-09-16 15:34:59 +00004799 // Visit the protocols of protocols.
4800 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004801 if (Protocol->hasDefinition()) {
4802 const ObjCList<ObjCProtocolDecl> &Protocols
4803 = Protocol->getReferencedProtocols();
4804 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4805 E = Protocols.end();
4806 I != E; ++I)
4807 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
4808 NumSelIdents, CurContext, Selectors, AllowSameLength,
4809 Results, false);
4810 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004811 }
4812
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004813 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004814 return;
4815
4816 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004817 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4818 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004819 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004820 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004821 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004822
4823 // Add methods in categories.
Douglas Gregord3297242013-01-16 23:00:23 +00004824 for (ObjCInterfaceDecl::known_categories_iterator
4825 Cat = IFace->known_categories_begin(),
4826 CatEnd = IFace->known_categories_end();
4827 Cat != CatEnd; ++Cat) {
4828 ObjCCategoryDecl *CatDecl = *Cat;
4829
4830 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004831 NumSelIdents, CurContext, Selectors, AllowSameLength,
4832 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004833
4834 // Add a categories protocol methods.
4835 const ObjCList<ObjCProtocolDecl> &Protocols
4836 = CatDecl->getReferencedProtocols();
4837 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4838 E = Protocols.end();
4839 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004840 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004841 NumSelIdents, CurContext, Selectors, AllowSameLength,
4842 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004843
4844 // Add methods in category implementations.
4845 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004846 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004847 NumSelIdents, CurContext, Selectors, AllowSameLength,
4848 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004849 }
4850
4851 // Add methods in superclass.
4852 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004853 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004854 SelIdents, NumSelIdents, CurContext, Selectors,
4855 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004856
4857 // Add methods in our implementation, if any.
4858 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004859 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004860 NumSelIdents, CurContext, Selectors, AllowSameLength,
4861 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004862}
4863
4864
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004865void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004866 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004867 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004868 if (!Class) {
4869 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004870 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004871 Class = Category->getClassInterface();
4872
4873 if (!Class)
4874 return;
4875 }
4876
4877 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004878 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004879 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004880 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004881 Results.EnterNewScope();
4882
Douglas Gregord36adf52010-09-16 16:06:31 +00004883 VisitedSelectorSet Selectors;
4884 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004885 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004886 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004887 HandleCodeCompleteResults(this, CodeCompleter,
4888 CodeCompletionContext::CCC_Other,
4889 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004890}
4891
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004892void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004893 // Try to find the interface where setters might live.
4894 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004895 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004896 if (!Class) {
4897 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004898 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004899 Class = Category->getClassInterface();
4900
4901 if (!Class)
4902 return;
4903 }
4904
4905 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004906 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004907 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004908 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004909 Results.EnterNewScope();
4910
Douglas Gregord36adf52010-09-16 16:06:31 +00004911 VisitedSelectorSet Selectors;
4912 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004913 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004914
4915 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004916 HandleCodeCompleteResults(this, CodeCompleter,
4917 CodeCompletionContext::CCC_Other,
4918 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004919}
4920
Douglas Gregorafc45782011-02-15 22:19:42 +00004921void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
4922 bool IsParameter) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004923 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004924 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004925 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004926 Results.EnterNewScope();
4927
4928 // Add context-sensitive, Objective-C parameter-passing keywords.
4929 bool AddedInOut = false;
4930 if ((DS.getObjCDeclQualifier() &
4931 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4932 Results.AddResult("in");
4933 Results.AddResult("inout");
4934 AddedInOut = true;
4935 }
4936 if ((DS.getObjCDeclQualifier() &
4937 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4938 Results.AddResult("out");
4939 if (!AddedInOut)
4940 Results.AddResult("inout");
4941 }
4942 if ((DS.getObjCDeclQualifier() &
4943 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4944 ObjCDeclSpec::DQ_Oneway)) == 0) {
4945 Results.AddResult("bycopy");
4946 Results.AddResult("byref");
4947 Results.AddResult("oneway");
4948 }
4949
Douglas Gregorafc45782011-02-15 22:19:42 +00004950 // If we're completing the return type of an Objective-C method and the
4951 // identifier IBAction refers to a macro, provide a completion item for
4952 // an action, e.g.,
4953 // IBAction)<#selector#>:(id)sender
4954 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
4955 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004956 CodeCompletionBuilder Builder(Results.getAllocator(),
4957 Results.getCodeCompletionTUInfo(),
4958 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00004959 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004960 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004961 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004962 Builder.AddChunk(CodeCompletionString::CK_Colon);
4963 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004964 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00004965 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00004966 Builder.AddTextChunk("sender");
4967 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
4968 }
Douglas Gregor31aa5772013-01-30 07:11:43 +00004969
4970 // If we're completing the return type, provide 'instancetype'.
4971 if (!IsParameter) {
4972 Results.AddResult(CodeCompletionResult("instancetype"));
4973 }
Douglas Gregorafc45782011-02-15 22:19:42 +00004974
Douglas Gregord32b0222010-08-24 01:06:58 +00004975 // Add various builtin type names and specifiers.
4976 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4977 Results.ExitScope();
4978
4979 // Add the various type names
4980 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4981 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4982 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4983 CodeCompleter->includeGlobals());
4984
4985 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00004986 AddMacroResults(PP, Results, false);
Douglas Gregord32b0222010-08-24 01:06:58 +00004987
4988 HandleCodeCompleteResults(this, CodeCompleter,
4989 CodeCompletionContext::CCC_Type,
4990 Results.data(), Results.size());
4991}
4992
Douglas Gregor22f56992010-04-06 19:22:33 +00004993/// \brief When we have an expression with type "id", we may assume
4994/// that it has some more-specific class type based on knowledge of
4995/// common uses of Objective-C. This routine returns that class type,
4996/// or NULL if no better result could be determined.
4997static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004998 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004999 if (!Msg)
5000 return 0;
5001
5002 Selector Sel = Msg->getSelector();
5003 if (Sel.isNull())
5004 return 0;
5005
5006 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5007 if (!Id)
5008 return 0;
5009
5010 ObjCMethodDecl *Method = Msg->getMethodDecl();
5011 if (!Method)
5012 return 0;
5013
5014 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00005015 ObjCInterfaceDecl *IFace = 0;
5016 switch (Msg->getReceiverKind()) {
5017 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00005018 if (const ObjCObjectType *ObjType
5019 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5020 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00005021 break;
5022
5023 case ObjCMessageExpr::Instance: {
5024 QualType T = Msg->getInstanceReceiver()->getType();
5025 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5026 IFace = Ptr->getInterfaceDecl();
5027 break;
5028 }
5029
5030 case ObjCMessageExpr::SuperInstance:
5031 case ObjCMessageExpr::SuperClass:
5032 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00005033 }
5034
5035 if (!IFace)
5036 return 0;
5037
5038 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5039 if (Method->isInstanceMethod())
5040 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5041 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005042 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005043 .Case("autorelease", IFace)
5044 .Case("copy", IFace)
5045 .Case("copyWithZone", IFace)
5046 .Case("mutableCopy", IFace)
5047 .Case("mutableCopyWithZone", IFace)
5048 .Case("awakeFromCoder", IFace)
5049 .Case("replacementObjectFromCoder", IFace)
5050 .Case("class", IFace)
5051 .Case("classForCoder", IFace)
5052 .Case("superclass", Super)
5053 .Default(0);
5054
5055 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5056 .Case("new", IFace)
5057 .Case("alloc", IFace)
5058 .Case("allocWithZone", IFace)
5059 .Case("class", IFace)
5060 .Case("superclass", Super)
5061 .Default(0);
5062}
5063
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005064// Add a special completion for a message send to "super", which fills in the
5065// most likely case of forwarding all of our arguments to the superclass
5066// function.
5067///
5068/// \param S The semantic analysis object.
5069///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00005070/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005071/// the "super" keyword. Otherwise, we just need to provide the arguments.
5072///
5073/// \param SelIdents The identifiers in the selector that have already been
5074/// provided as arguments for a send to "super".
5075///
5076/// \param NumSelIdents The number of identifiers in \p SelIdents.
5077///
5078/// \param Results The set of results to augment.
5079///
5080/// \returns the Objective-C method declaration that would be invoked by
5081/// this "super" completion. If NULL, no completion was added.
5082static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
5083 IdentifierInfo **SelIdents,
5084 unsigned NumSelIdents,
5085 ResultBuilder &Results) {
5086 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5087 if (!CurMethod)
5088 return 0;
5089
5090 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5091 if (!Class)
5092 return 0;
5093
5094 // Try to find a superclass method with the same selector.
5095 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005096 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5097 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005098 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5099 CurMethod->isInstanceMethod());
5100
Douglas Gregor78bcd912011-02-16 00:51:18 +00005101 // Check in categories or class extensions.
5102 if (!SuperMethod) {
Douglas Gregord3297242013-01-16 23:00:23 +00005103 for (ObjCInterfaceDecl::known_categories_iterator
5104 Cat = Class->known_categories_begin(),
5105 CatEnd = Class->known_categories_end();
5106 Cat != CatEnd; ++Cat) {
5107 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregor78bcd912011-02-16 00:51:18 +00005108 CurMethod->isInstanceMethod())))
5109 break;
Douglas Gregord3297242013-01-16 23:00:23 +00005110 }
Douglas Gregor78bcd912011-02-16 00:51:18 +00005111 }
5112 }
5113
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005114 if (!SuperMethod)
5115 return 0;
5116
5117 // Check whether the superclass method has the same signature.
5118 if (CurMethod->param_size() != SuperMethod->param_size() ||
5119 CurMethod->isVariadic() != SuperMethod->isVariadic())
5120 return 0;
5121
5122 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5123 CurPEnd = CurMethod->param_end(),
5124 SuperP = SuperMethod->param_begin();
5125 CurP != CurPEnd; ++CurP, ++SuperP) {
5126 // Make sure the parameter types are compatible.
5127 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5128 (*SuperP)->getType()))
5129 return 0;
5130
5131 // Make sure we have a parameter name to forward!
5132 if (!(*CurP)->getIdentifier())
5133 return 0;
5134 }
5135
5136 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005137 CodeCompletionBuilder Builder(Results.getAllocator(),
5138 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005139
5140 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005141 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5142 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005143
5144 // If we need the "super" keyword, add it (plus some spacing).
5145 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005146 Builder.AddTypedTextChunk("super");
5147 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005148 }
5149
5150 Selector Sel = CurMethod->getSelector();
5151 if (Sel.isUnarySelector()) {
5152 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005153 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005154 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005155 else
Douglas Gregordae68752011-02-01 22:57:45 +00005156 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005157 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005158 } else {
5159 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5160 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
5161 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005162 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005163
5164 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00005165 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005166 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005167 Sel.getNameForSlot(I) + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005168 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005169 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005170 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005171 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005172 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005173 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005174 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005175 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005176 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005177 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005178 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005179 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005180 }
5181 }
5182 }
5183
Douglas Gregorba103062012-03-27 23:34:16 +00005184 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5185 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005186 return SuperMethod;
5187}
5188
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005189void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005190 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005191 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005192 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005193 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith80ad52f2013-01-02 11:42:31 +00005194 getLangOpts().CPlusPlus11
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005195 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5196 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005197
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005198 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5199 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005200 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5201 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005202
5203 // If we are in an Objective-C method inside a class that has a superclass,
5204 // add "super" as an option.
5205 if (ObjCMethodDecl *Method = getCurMethodDecl())
5206 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005207 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005208 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005209
5210 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
5211 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005212
Richard Smith80ad52f2013-01-02 11:42:31 +00005213 if (getLangOpts().CPlusPlus11)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005214 addThisCompletion(*this, Results);
5215
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005216 Results.ExitScope();
5217
5218 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00005219 AddMacroResults(PP, Results, false);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005220 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005221 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005222
5223}
5224
Douglas Gregor2725ca82010-04-21 19:57:20 +00005225void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
5226 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005227 unsigned NumSelIdents,
5228 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005229 ObjCInterfaceDecl *CDecl = 0;
5230 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5231 // Figure out which interface we're in.
5232 CDecl = CurMethod->getClassInterface();
5233 if (!CDecl)
5234 return;
5235
5236 // Find the superclass of this class.
5237 CDecl = CDecl->getSuperClass();
5238 if (!CDecl)
5239 return;
5240
5241 if (CurMethod->isInstanceMethod()) {
5242 // We are inside an instance method, which means that the message
5243 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005244 // current object.
5245 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005246 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005247 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005248 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005249 }
5250
5251 // Fall through to send to the superclass in CDecl.
5252 } else {
5253 // "super" may be the name of a type or variable. Figure out which
5254 // it is.
5255 IdentifierInfo *Super = &Context.Idents.get("super");
5256 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5257 LookupOrdinaryName);
5258 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5259 // "super" names an interface. Use it.
5260 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005261 if (const ObjCObjectType *Iface
5262 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5263 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005264 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5265 // "super" names an unresolved type; we can't be more specific.
5266 } else {
5267 // Assume that "super" names some kind of value and parse that way.
5268 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005269 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005270 UnqualifiedId id;
5271 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005272 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5273 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005274 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005275 SelIdents, NumSelIdents,
5276 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005277 }
5278
5279 // Fall through
5280 }
5281
John McCallb3d87482010-08-24 05:47:05 +00005282 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005283 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005284 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005285 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005286 NumSelIdents, AtArgumentExpression,
5287 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005288}
5289
Douglas Gregorb9d77572010-09-21 00:03:25 +00005290/// \brief Given a set of code-completion results for the argument of a message
5291/// send, determine the preferred type (if any) for that argument expression.
5292static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5293 unsigned NumSelIdents) {
5294 typedef CodeCompletionResult Result;
5295 ASTContext &Context = Results.getSema().Context;
5296
5297 QualType PreferredType;
5298 unsigned BestPriority = CCP_Unlikely * 2;
5299 Result *ResultsData = Results.data();
5300 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5301 Result &R = ResultsData[I];
5302 if (R.Kind == Result::RK_Declaration &&
5303 isa<ObjCMethodDecl>(R.Declaration)) {
5304 if (R.Priority <= BestPriority) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00005305 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005306 if (NumSelIdents <= Method->param_size()) {
5307 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5308 ->getType();
5309 if (R.Priority < BestPriority || PreferredType.isNull()) {
5310 BestPriority = R.Priority;
5311 PreferredType = MyPreferredType;
5312 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5313 MyPreferredType)) {
5314 PreferredType = QualType();
5315 }
5316 }
5317 }
5318 }
5319 }
5320
5321 return PreferredType;
5322}
5323
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005324static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5325 ParsedType Receiver,
5326 IdentifierInfo **SelIdents,
5327 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005328 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005329 bool IsSuper,
5330 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005331 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005332 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005333
Douglas Gregor24a069f2009-11-17 17:59:40 +00005334 // If the given name refers to an interface type, retrieve the
5335 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005336 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005337 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005338 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005339 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5340 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005341 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005342
Douglas Gregor36ecb042009-11-17 23:22:23 +00005343 // Add all of the factory methods in this Objective-C class, its protocols,
5344 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005345 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005346
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005347 // If this is a send-to-super, try to add the special "super" send
5348 // completion.
5349 if (IsSuper) {
5350 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005351 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
5352 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005353 Results.Ignore(SuperMethod);
5354 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005355
Douglas Gregor265f7492010-08-27 15:29:55 +00005356 // If we're inside an Objective-C method definition, prefer its selector to
5357 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005358 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005359 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005360
Douglas Gregord36adf52010-09-16 16:06:31 +00005361 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005362 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005363 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005364 SemaRef.CurContext, Selectors, AtArgumentExpression,
5365 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005366 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005367 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005368
Douglas Gregor719770d2010-04-06 17:30:22 +00005369 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005370 // pool from the AST file.
Axel Naumann0ec56b72012-10-18 19:05:02 +00005371 if (SemaRef.getExternalSource()) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005372 for (uint32_t I = 0,
Axel Naumann0ec56b72012-10-18 19:05:02 +00005373 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005374 I != N; ++I) {
Axel Naumann0ec56b72012-10-18 19:05:02 +00005375 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005376 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005377 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005378
5379 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005380 }
5381 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005382
5383 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5384 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005385 M != MEnd; ++M) {
5386 for (ObjCMethodList *MethList = &M->second.second;
5387 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005388 MethList = MethList->Next) {
5389 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5390 NumSelIdents))
5391 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005392
Douglas Gregor13438f92010-04-06 16:40:00 +00005393 Result R(MethList->Method, 0);
5394 R.StartParameter = NumSelIdents;
5395 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005396 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005397 }
5398 }
5399 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005400
5401 Results.ExitScope();
5402}
Douglas Gregor13438f92010-04-06 16:40:00 +00005403
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005404void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
5405 IdentifierInfo **SelIdents,
5406 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005407 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005408 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005409
5410 QualType T = this->GetTypeFromParser(Receiver);
5411
Douglas Gregor218937c2011-02-01 19:23:04 +00005412 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005413 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005414 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005415 T, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005416
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005417 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
5418 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005419
5420 // If we're actually at the argument expression (rather than prior to the
5421 // selector), we're actually performing code completion for an expression.
5422 // Determine whether we have a single, best method. If so, we can
5423 // code-complete the expression using the corresponding parameter type as
5424 // our preferred type, improving completion results.
5425 if (AtArgumentExpression) {
5426 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Douglas Gregore081a612011-07-21 01:05:26 +00005427 NumSelIdents);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005428 if (PreferredType.isNull())
5429 CodeCompleteOrdinaryName(S, PCC_Expression);
5430 else
5431 CodeCompleteExpression(S, PreferredType);
5432 return;
5433 }
5434
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005435 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005436 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005437 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005438}
5439
Richard Trieuf81e5a92011-09-09 02:00:50 +00005440void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Douglas Gregord3c68542009-11-19 01:08:35 +00005441 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005442 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005443 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005444 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005445 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005446
5447 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005448
Douglas Gregor36ecb042009-11-17 23:22:23 +00005449 // If necessary, apply function/array conversion to the receiver.
5450 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005451 if (RecExpr) {
5452 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5453 if (Conv.isInvalid()) // conversion failed. bail.
5454 return;
5455 RecExpr = Conv.take();
5456 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005457 QualType ReceiverType = RecExpr? RecExpr->getType()
5458 : Super? Context.getObjCObjectPointerType(
5459 Context.getObjCInterfaceType(Super))
5460 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005461
Douglas Gregorda892642010-11-08 21:12:30 +00005462 // If we're messaging an expression with type "id" or "Class", check
5463 // whether we know something special about the receiver that allows
5464 // us to assume a more-specific receiver type.
5465 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5466 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5467 if (ReceiverType->isObjCClassType())
5468 return CodeCompleteObjCClassMessage(S,
5469 ParsedType::make(Context.getObjCInterfaceType(IFace)),
5470 SelIdents, NumSelIdents,
5471 AtArgumentExpression, Super);
5472
5473 ReceiverType = Context.getObjCObjectPointerType(
5474 Context.getObjCInterfaceType(IFace));
5475 }
5476
Douglas Gregor36ecb042009-11-17 23:22:23 +00005477 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005478 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005479 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005480 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Douglas Gregor0a47d692011-07-26 15:24:30 +00005481 ReceiverType, SelIdents, NumSelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005482
Douglas Gregor36ecb042009-11-17 23:22:23 +00005483 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005484
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005485 // If this is a send-to-super, try to add the special "super" send
5486 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005487 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005488 if (ObjCMethodDecl *SuperMethod
5489 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
5490 Results))
5491 Results.Ignore(SuperMethod);
5492 }
5493
Douglas Gregor265f7492010-08-27 15:29:55 +00005494 // If we're inside an Objective-C method definition, prefer its selector to
5495 // others.
5496 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5497 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005498
Douglas Gregord36adf52010-09-16 16:06:31 +00005499 // Keep track of the selectors we've already added.
5500 VisitedSelectorSet Selectors;
5501
Douglas Gregorf74a4192009-11-18 00:06:18 +00005502 // Handle messages to Class. This really isn't a message to an instance
5503 // method, so we treat it the same way we would treat a message send to a
5504 // class method.
5505 if (ReceiverType->isObjCClassType() ||
5506 ReceiverType->isObjCQualifiedClassType()) {
5507 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5508 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00005509 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005510 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005511 }
5512 }
5513 // Handle messages to a qualified ID ("id<foo>").
5514 else if (const ObjCObjectPointerType *QualID
5515 = ReceiverType->getAsObjCQualifiedIdType()) {
5516 // Search protocols for instance methods.
5517 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5518 E = QualID->qual_end();
5519 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005520 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005521 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005522 }
5523 // Handle messages to a pointer to interface type.
5524 else if (const ObjCObjectPointerType *IFacePtr
5525 = ReceiverType->getAsObjCInterfacePointerType()) {
5526 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005527 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005528 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
5529 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005530
5531 // Search protocols for instance methods.
5532 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5533 E = IFacePtr->qual_end();
5534 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00005535 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005536 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005537 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005538 // Handle messages to "id".
5539 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005540 // We're messaging "id", so provide all instance methods we know
5541 // about as code-completion results.
5542
5543 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005544 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005545 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005546 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5547 I != N; ++I) {
5548 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005549 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005550 continue;
5551
Sebastian Redldb9d2142010-08-02 23:18:59 +00005552 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005553 }
5554 }
5555
Sebastian Redldb9d2142010-08-02 23:18:59 +00005556 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5557 MEnd = MethodPool.end();
5558 M != MEnd; ++M) {
5559 for (ObjCMethodList *MethList = &M->second.first;
5560 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00005561 MethList = MethList->Next) {
5562 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5563 NumSelIdents))
5564 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005565
5566 if (!Selectors.insert(MethList->Method->getSelector()))
5567 continue;
5568
Douglas Gregor13438f92010-04-06 16:40:00 +00005569 Result R(MethList->Method, 0);
5570 R.StartParameter = NumSelIdents;
5571 R.AllParametersAreInformative = false;
5572 Results.MaybeAddResult(R, CurContext);
5573 }
5574 }
5575 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005576 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005577
5578
5579 // If we're actually at the argument expression (rather than prior to the
5580 // selector), we're actually performing code completion for an expression.
5581 // Determine whether we have a single, best method. If so, we can
5582 // code-complete the expression using the corresponding parameter type as
5583 // our preferred type, improving completion results.
5584 if (AtArgumentExpression) {
5585 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
5586 NumSelIdents);
5587 if (PreferredType.isNull())
5588 CodeCompleteOrdinaryName(S, PCC_Expression);
5589 else
5590 CodeCompleteExpression(S, PreferredType);
5591 return;
5592 }
5593
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005594 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005595 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005596 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005597}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005598
Douglas Gregorfb629412010-08-23 21:17:50 +00005599void Sema::CodeCompleteObjCForCollection(Scope *S,
5600 DeclGroupPtrTy IterationVar) {
5601 CodeCompleteExpressionData Data;
5602 Data.ObjCCollection = true;
5603
5604 if (IterationVar.getAsOpaquePtr()) {
5605 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
5606 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5607 if (*I)
5608 Data.IgnoreDecls.push_back(*I);
5609 }
5610 }
5611
5612 CodeCompleteExpression(S, Data);
5613}
5614
Douglas Gregor458433d2010-08-26 15:07:07 +00005615void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
5616 unsigned NumSelIdents) {
5617 // If we have an external source, load the entire class method
5618 // pool from the AST file.
5619 if (ExternalSource) {
5620 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5621 I != N; ++I) {
5622 Selector Sel = ExternalSource->GetExternalSelector(I);
5623 if (Sel.isNull() || MethodPool.count(Sel))
5624 continue;
5625
5626 ReadMethodPool(Sel);
5627 }
5628 }
5629
Douglas Gregor218937c2011-02-01 19:23:04 +00005630 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005631 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005632 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005633 Results.EnterNewScope();
5634 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5635 MEnd = MethodPool.end();
5636 M != MEnd; ++M) {
5637
5638 Selector Sel = M->first;
5639 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
5640 continue;
5641
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005642 CodeCompletionBuilder Builder(Results.getAllocator(),
5643 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005644 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005645 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005646 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005647 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005648 continue;
5649 }
5650
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005651 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005652 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005653 if (I == NumSelIdents) {
5654 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005655 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005656 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005657 Accumulator.clear();
5658 }
5659 }
5660
Benjamin Kramera0651c52011-07-26 16:59:25 +00005661 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005662 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005663 }
Douglas Gregordae68752011-02-01 22:57:45 +00005664 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005665 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005666 }
5667 Results.ExitScope();
5668
5669 HandleCodeCompleteResults(this, CodeCompleter,
5670 CodeCompletionContext::CCC_SelectorName,
5671 Results.data(), Results.size());
5672}
5673
Douglas Gregor55385fe2009-11-18 04:19:12 +00005674/// \brief Add all of the protocol declarations that we find in the given
5675/// (translation unit) context.
5676static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005677 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005678 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005679 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005680
5681 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5682 DEnd = Ctx->decls_end();
5683 D != DEnd; ++D) {
5684 // Record any protocols we find.
5685 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005686 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregor608300b2010-01-14 16:14:35 +00005687 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005688 }
5689}
5690
5691void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5692 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005693 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005694 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005695 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005696
Douglas Gregor70c23352010-12-09 21:44:02 +00005697 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5698 Results.EnterNewScope();
5699
5700 // Tell the result set to ignore all of the protocols we have
5701 // already seen.
5702 // FIXME: This doesn't work when caching code-completion results.
5703 for (unsigned I = 0; I != NumProtocols; ++I)
5704 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5705 Protocols[I].second))
5706 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005707
Douglas Gregor70c23352010-12-09 21:44:02 +00005708 // Add all protocols.
5709 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5710 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005711
Douglas Gregor70c23352010-12-09 21:44:02 +00005712 Results.ExitScope();
5713 }
5714
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005715 HandleCodeCompleteResults(this, CodeCompleter,
5716 CodeCompletionContext::CCC_ObjCProtocolName,
5717 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005718}
5719
5720void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005721 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005722 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005723 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005724
Douglas Gregor70c23352010-12-09 21:44:02 +00005725 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5726 Results.EnterNewScope();
5727
5728 // Add all protocols.
5729 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5730 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005731
Douglas Gregor70c23352010-12-09 21:44:02 +00005732 Results.ExitScope();
5733 }
5734
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005735 HandleCodeCompleteResults(this, CodeCompleter,
5736 CodeCompletionContext::CCC_ObjCProtocolName,
5737 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005738}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005739
5740/// \brief Add all of the Objective-C interface declarations that we find in
5741/// the given (translation unit) context.
5742static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5743 bool OnlyForwardDeclarations,
5744 bool OnlyUnimplemented,
5745 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005746 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005747
5748 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5749 DEnd = Ctx->decls_end();
5750 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005751 // Record any interfaces we find.
5752 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005753 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005754 (!OnlyUnimplemented || !Class->getImplementation()))
5755 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005756 }
5757}
5758
5759void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005760 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005761 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005762 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005763 Results.EnterNewScope();
5764
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005765 if (CodeCompleter->includeGlobals()) {
5766 // Add all classes.
5767 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5768 false, Results);
5769 }
5770
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005771 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005772
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005773 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005774 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005775 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005776}
5777
Douglas Gregorc83c6872010-04-15 22:33:43 +00005778void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5779 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005780 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005781 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005782 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005783 Results.EnterNewScope();
5784
5785 // Make sure that we ignore the class we're currently defining.
5786 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005787 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005788 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005789 Results.Ignore(CurClass);
5790
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005791 if (CodeCompleter->includeGlobals()) {
5792 // Add all classes.
5793 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5794 false, Results);
5795 }
5796
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005797 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005798
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005799 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005800 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005801 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005802}
5803
5804void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005805 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005806 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005807 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005808 Results.EnterNewScope();
5809
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005810 if (CodeCompleter->includeGlobals()) {
5811 // Add all unimplemented classes.
5812 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5813 true, Results);
5814 }
5815
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005816 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005817
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005818 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005819 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005820 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005821}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005822
5823void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005824 IdentifierInfo *ClassName,
5825 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005826 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005827
Douglas Gregor218937c2011-02-01 19:23:04 +00005828 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005829 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005830 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005831
5832 // Ignore any categories we find that have already been implemented by this
5833 // interface.
5834 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5835 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005836 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregord3297242013-01-16 23:00:23 +00005837 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
5838 for (ObjCInterfaceDecl::visible_categories_iterator
5839 Cat = Class->visible_categories_begin(),
5840 CatEnd = Class->visible_categories_end();
5841 Cat != CatEnd; ++Cat) {
5842 CategoryNames.insert(Cat->getIdentifier());
5843 }
5844 }
5845
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005846 // Add all of the categories we know about.
5847 Results.EnterNewScope();
5848 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5849 for (DeclContext::decl_iterator D = TU->decls_begin(),
5850 DEnd = TU->decls_end();
5851 D != DEnd; ++D)
5852 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5853 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005854 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005855 Results.ExitScope();
5856
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005857 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005858 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005859 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005860}
5861
5862void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005863 IdentifierInfo *ClassName,
5864 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005865 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005866
5867 // Find the corresponding interface. If we couldn't find the interface, the
5868 // program itself is ill-formed. However, we'll try to be helpful still by
5869 // providing the list of all of the categories we know about.
5870 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005871 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005872 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5873 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005874 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005875
Douglas Gregor218937c2011-02-01 19:23:04 +00005876 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005877 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005878 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005879
5880 // Add all of the categories that have have corresponding interface
5881 // declarations in this class and any of its superclasses, except for
5882 // already-implemented categories in the class itself.
5883 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5884 Results.EnterNewScope();
5885 bool IgnoreImplemented = true;
5886 while (Class) {
Douglas Gregord3297242013-01-16 23:00:23 +00005887 for (ObjCInterfaceDecl::visible_categories_iterator
5888 Cat = Class->visible_categories_begin(),
5889 CatEnd = Class->visible_categories_end();
5890 Cat != CatEnd; ++Cat) {
5891 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
5892 CategoryNames.insert(Cat->getIdentifier()))
5893 Results.AddResult(Result(*Cat, 0), CurContext, 0, false);
5894 }
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005895
5896 Class = Class->getSuperClass();
5897 IgnoreImplemented = false;
5898 }
5899 Results.ExitScope();
5900
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005901 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005902 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005903 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005904}
Douglas Gregor322328b2009-11-18 22:32:06 +00005905
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005906void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005907 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005908 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005909 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005910
5911 // Figure out where this @synthesize lives.
5912 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005913 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005914 if (!Container ||
5915 (!isa<ObjCImplementationDecl>(Container) &&
5916 !isa<ObjCCategoryImplDecl>(Container)))
5917 return;
5918
5919 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005920 Container = getContainerDef(Container);
5921 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005922 DEnd = Container->decls_end();
5923 D != DEnd; ++D)
5924 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5925 Results.Ignore(PropertyImpl->getPropertyDecl());
5926
5927 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005928 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005929 Results.EnterNewScope();
5930 if (ObjCImplementationDecl *ClassImpl
5931 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005932 AddObjCProperties(ClassImpl->getClassInterface(), false,
5933 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005934 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005935 else
5936 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00005937 false, /*AllowNullaryMethods=*/false, CurContext,
5938 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005939 Results.ExitScope();
5940
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005941 HandleCodeCompleteResults(this, CodeCompleter,
5942 CodeCompletionContext::CCC_Other,
5943 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005944}
5945
5946void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005947 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00005948 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005949 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005950 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005951 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005952
5953 // Figure out where this @synthesize lives.
5954 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005955 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005956 if (!Container ||
5957 (!isa<ObjCImplementationDecl>(Container) &&
5958 !isa<ObjCCategoryImplDecl>(Container)))
5959 return;
5960
5961 // Figure out which interface we're looking into.
5962 ObjCInterfaceDecl *Class = 0;
5963 if (ObjCImplementationDecl *ClassImpl
5964 = dyn_cast<ObjCImplementationDecl>(Container))
5965 Class = ClassImpl->getClassInterface();
5966 else
5967 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5968 ->getClassInterface();
5969
Douglas Gregore8426052011-04-18 14:40:46 +00005970 // Determine the type of the property we're synthesizing.
5971 QualType PropertyType = Context.getObjCIdType();
5972 if (Class) {
5973 if (ObjCPropertyDecl *Property
5974 = Class->FindPropertyDeclaration(PropertyName)) {
5975 PropertyType
5976 = Property->getType().getNonReferenceType().getUnqualifiedType();
5977
5978 // Give preference to ivars
5979 Results.setPreferredType(PropertyType);
5980 }
5981 }
5982
Douglas Gregor322328b2009-11-18 22:32:06 +00005983 // Add all of the instance variables in this class and its superclasses.
5984 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005985 bool SawSimilarlyNamedIvar = false;
5986 std::string NameWithPrefix;
5987 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00005988 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005989 std::string NameWithSuffix = PropertyName->getName().str();
5990 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00005991 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005992 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
5993 Ivar = Ivar->getNextIvar()) {
Douglas Gregore8426052011-04-18 14:40:46 +00005994 Results.AddResult(Result(Ivar, 0), CurContext, 0, false);
5995
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005996 // Determine whether we've seen an ivar with a name similar to the
5997 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00005998 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00005999 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00006000 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006001 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00006002
6003 // Reduce the priority of this result by one, to give it a slight
6004 // advantage over other results whose names don't match so closely.
6005 if (Results.size() &&
6006 Results.data()[Results.size() - 1].Kind
6007 == CodeCompletionResult::RK_Declaration &&
6008 Results.data()[Results.size() - 1].Declaration == Ivar)
6009 Results.data()[Results.size() - 1].Priority--;
6010 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006011 }
Douglas Gregor322328b2009-11-18 22:32:06 +00006012 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006013
6014 if (!SawSimilarlyNamedIvar) {
6015 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00006016 // an ivar of the appropriate type.
6017 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006018 typedef CodeCompletionResult Result;
6019 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006020 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6021 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006022
Douglas Gregor8987b232011-09-27 23:30:47 +00006023 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00006024 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006025 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006026 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6027 Results.AddResult(Result(Builder.TakeString(), Priority,
6028 CXCursor_ObjCIvarDecl));
6029 }
6030
Douglas Gregor322328b2009-11-18 22:32:06 +00006031 Results.ExitScope();
6032
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006033 HandleCodeCompleteResults(this, CodeCompleter,
6034 CodeCompletionContext::CCC_Other,
6035 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00006036}
Douglas Gregore8f5a172010-04-07 00:21:17 +00006037
Douglas Gregor408be5a2010-08-25 01:08:01 +00006038// Mapping from selectors to the methods that implement that selector, along
6039// with the "in original class" flag.
6040typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
6041 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006042
6043/// \brief Find all of the methods that reside in the given container
6044/// (and its superclasses, protocols, etc.) that meet the given
6045/// criteria. Insert those methods into the map of known methods,
6046/// indexed by selector so they can be easily found.
6047static void FindImplementableMethods(ASTContext &Context,
6048 ObjCContainerDecl *Container,
6049 bool WantInstanceMethods,
6050 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006051 KnownMethodsMap &KnownMethods,
6052 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006053 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006054 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006055 if (!IFace->hasDefinition())
6056 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006057
6058 IFace = IFace->getDefinition();
6059 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006060
Douglas Gregore8f5a172010-04-07 00:21:17 +00006061 const ObjCList<ObjCProtocolDecl> &Protocols
6062 = IFace->getReferencedProtocols();
6063 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006064 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006065 I != E; ++I)
6066 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006067 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006068
Douglas Gregorea766182010-10-18 18:21:28 +00006069 // Add methods from any class extensions and categories.
Douglas Gregord3297242013-01-16 23:00:23 +00006070 for (ObjCInterfaceDecl::visible_categories_iterator
6071 Cat = IFace->visible_categories_begin(),
6072 CatEnd = IFace->visible_categories_end();
6073 Cat != CatEnd; ++Cat) {
6074 FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006075 KnownMethods, false);
Douglas Gregord3297242013-01-16 23:00:23 +00006076 }
6077
Douglas Gregorea766182010-10-18 18:21:28 +00006078 // Visit the superclass.
6079 if (IFace->getSuperClass())
6080 FindImplementableMethods(Context, IFace->getSuperClass(),
6081 WantInstanceMethods, ReturnType,
6082 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006083 }
6084
6085 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6086 // Recurse into protocols.
6087 const ObjCList<ObjCProtocolDecl> &Protocols
6088 = Category->getReferencedProtocols();
6089 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006090 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006091 I != E; ++I)
6092 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006093 KnownMethods, InOriginalClass);
6094
6095 // If this category is the original class, jump to the interface.
6096 if (InOriginalClass && Category->getClassInterface())
6097 FindImplementableMethods(Context, Category->getClassInterface(),
6098 WantInstanceMethods, ReturnType, KnownMethods,
6099 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006100 }
6101
6102 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006103 // Make sure we have a definition; that's what we'll walk.
6104 if (!Protocol->hasDefinition())
6105 return;
6106 Protocol = Protocol->getDefinition();
6107 Container = Protocol;
6108
6109 // Recurse into protocols.
6110 const ObjCList<ObjCProtocolDecl> &Protocols
6111 = Protocol->getReferencedProtocols();
6112 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6113 E = Protocols.end();
6114 I != E; ++I)
6115 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6116 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006117 }
6118
6119 // Add methods in this container. This operation occurs last because
6120 // we want the methods from this container to override any methods
6121 // we've previously seen with the same selector.
6122 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6123 MEnd = Container->meth_end();
6124 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006125 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006126 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006127 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006128 continue;
6129
David Blaikie581deb32012-06-06 20:45:41 +00006130 KnownMethods[M->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006131 }
6132 }
6133}
6134
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006135/// \brief Add the parenthesized return or parameter type chunk to a code
6136/// completion string.
6137static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006138 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006139 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006140 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006141 CodeCompletionBuilder &Builder) {
6142 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006143 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6144 if (!Quals.empty())
6145 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006146 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006147 Builder.getAllocator()));
6148 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6149}
6150
6151/// \brief Determine whether the given class is or inherits from a class by
6152/// the given name.
6153static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006154 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006155 if (!Class)
6156 return false;
6157
6158 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6159 return true;
6160
6161 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6162}
6163
6164/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6165/// Key-Value Observing (KVO).
6166static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6167 bool IsInstanceMethod,
6168 QualType ReturnType,
6169 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006170 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006171 ResultBuilder &Results) {
6172 IdentifierInfo *PropName = Property->getIdentifier();
6173 if (!PropName || PropName->getLength() == 0)
6174 return;
6175
Douglas Gregor8987b232011-09-27 23:30:47 +00006176 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6177
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006178 // Builder that will create each code completion.
6179 typedef CodeCompletionResult Result;
6180 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006181 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006182
6183 // The selector table.
6184 SelectorTable &Selectors = Context.Selectors;
6185
6186 // The property name, copied into the code completion allocation region
6187 // on demand.
6188 struct KeyHolder {
6189 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006190 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006191 const char *CopiedKey;
6192
Chris Lattner5f9e2722011-07-23 10:55:15 +00006193 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006194 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6195
6196 operator const char *() {
6197 if (CopiedKey)
6198 return CopiedKey;
6199
6200 return CopiedKey = Allocator.CopyString(Key);
6201 }
6202 } Key(Allocator, PropName->getName());
6203
6204 // The uppercased name of the property name.
6205 std::string UpperKey = PropName->getName();
6206 if (!UpperKey.empty())
6207 UpperKey[0] = toupper(UpperKey[0]);
6208
6209 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6210 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6211 Property->getType());
6212 bool ReturnTypeMatchesVoid
6213 = ReturnType.isNull() || ReturnType->isVoidType();
6214
6215 // Add the normal accessor -(type)key.
6216 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006217 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006218 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6219 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006220 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6221 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006222
6223 Builder.AddTypedTextChunk(Key);
6224 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6225 CXCursor_ObjCInstanceMethodDecl));
6226 }
6227
6228 // If we have an integral or boolean property (or the user has provided
6229 // an integral or boolean return type), add the accessor -(type)isKey.
6230 if (IsInstanceMethod &&
6231 ((!ReturnType.isNull() &&
6232 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6233 (ReturnType.isNull() &&
6234 (Property->getType()->isIntegerType() ||
6235 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006236 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006237 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006238 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006239 if (ReturnType.isNull()) {
6240 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6241 Builder.AddTextChunk("BOOL");
6242 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6243 }
6244
6245 Builder.AddTypedTextChunk(
6246 Allocator.CopyString(SelectorId->getName()));
6247 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6248 CXCursor_ObjCInstanceMethodDecl));
6249 }
6250 }
6251
6252 // Add the normal mutator.
6253 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6254 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006255 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006256 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006257 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006258 if (ReturnType.isNull()) {
6259 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6260 Builder.AddTextChunk("void");
6261 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6262 }
6263
6264 Builder.AddTypedTextChunk(
6265 Allocator.CopyString(SelectorId->getName()));
6266 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006267 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6268 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006269 Builder.AddTextChunk(Key);
6270 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6271 CXCursor_ObjCInstanceMethodDecl));
6272 }
6273 }
6274
6275 // Indexed and unordered accessors
6276 unsigned IndexedGetterPriority = CCP_CodePattern;
6277 unsigned IndexedSetterPriority = CCP_CodePattern;
6278 unsigned UnorderedGetterPriority = CCP_CodePattern;
6279 unsigned UnorderedSetterPriority = CCP_CodePattern;
6280 if (const ObjCObjectPointerType *ObjCPointer
6281 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6282 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6283 // If this interface type is not provably derived from a known
6284 // collection, penalize the corresponding completions.
6285 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6286 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6287 if (!InheritsFromClassNamed(IFace, "NSArray"))
6288 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6289 }
6290
6291 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6292 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6293 if (!InheritsFromClassNamed(IFace, "NSSet"))
6294 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6295 }
6296 }
6297 } else {
6298 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6299 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6300 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6301 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6302 }
6303
6304 // Add -(NSUInteger)countOf<key>
6305 if (IsInstanceMethod &&
6306 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006307 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006308 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006309 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006310 if (ReturnType.isNull()) {
6311 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6312 Builder.AddTextChunk("NSUInteger");
6313 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6314 }
6315
6316 Builder.AddTypedTextChunk(
6317 Allocator.CopyString(SelectorId->getName()));
6318 Results.AddResult(Result(Builder.TakeString(),
6319 std::min(IndexedGetterPriority,
6320 UnorderedGetterPriority),
6321 CXCursor_ObjCInstanceMethodDecl));
6322 }
6323 }
6324
6325 // Indexed getters
6326 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6327 if (IsInstanceMethod &&
6328 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006329 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006330 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006331 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006332 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006333 if (ReturnType.isNull()) {
6334 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6335 Builder.AddTextChunk("id");
6336 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6337 }
6338
6339 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6340 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6341 Builder.AddTextChunk("NSUInteger");
6342 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6343 Builder.AddTextChunk("index");
6344 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6345 CXCursor_ObjCInstanceMethodDecl));
6346 }
6347 }
6348
6349 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6350 if (IsInstanceMethod &&
6351 (ReturnType.isNull() ||
6352 (ReturnType->isObjCObjectPointerType() &&
6353 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6354 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6355 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006356 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006357 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006358 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006359 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006360 if (ReturnType.isNull()) {
6361 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6362 Builder.AddTextChunk("NSArray *");
6363 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6364 }
6365
6366 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6367 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6368 Builder.AddTextChunk("NSIndexSet *");
6369 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6370 Builder.AddTextChunk("indexes");
6371 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6372 CXCursor_ObjCInstanceMethodDecl));
6373 }
6374 }
6375
6376 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6377 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006378 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006379 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006380 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006381 &Context.Idents.get("range")
6382 };
6383
Douglas Gregore74c25c2011-05-04 23:50:46 +00006384 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006385 if (ReturnType.isNull()) {
6386 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6387 Builder.AddTextChunk("void");
6388 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6389 }
6390
6391 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6392 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6393 Builder.AddPlaceholderChunk("object-type");
6394 Builder.AddTextChunk(" **");
6395 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6396 Builder.AddTextChunk("buffer");
6397 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6398 Builder.AddTypedTextChunk("range:");
6399 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6400 Builder.AddTextChunk("NSRange");
6401 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6402 Builder.AddTextChunk("inRange");
6403 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6404 CXCursor_ObjCInstanceMethodDecl));
6405 }
6406 }
6407
6408 // Mutable indexed accessors
6409
6410 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6411 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006412 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006413 IdentifierInfo *SelectorIds[2] = {
6414 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006415 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006416 };
6417
Douglas Gregore74c25c2011-05-04 23:50:46 +00006418 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006419 if (ReturnType.isNull()) {
6420 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6421 Builder.AddTextChunk("void");
6422 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6423 }
6424
6425 Builder.AddTypedTextChunk("insertObject:");
6426 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6427 Builder.AddPlaceholderChunk("object-type");
6428 Builder.AddTextChunk(" *");
6429 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6430 Builder.AddTextChunk("object");
6431 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6432 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6433 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6434 Builder.AddPlaceholderChunk("NSUInteger");
6435 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6436 Builder.AddTextChunk("index");
6437 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6438 CXCursor_ObjCInstanceMethodDecl));
6439 }
6440 }
6441
6442 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6443 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006444 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006445 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006446 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006447 &Context.Idents.get("atIndexes")
6448 };
6449
Douglas Gregore74c25c2011-05-04 23:50:46 +00006450 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006451 if (ReturnType.isNull()) {
6452 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6453 Builder.AddTextChunk("void");
6454 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6455 }
6456
6457 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6458 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6459 Builder.AddTextChunk("NSArray *");
6460 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6461 Builder.AddTextChunk("array");
6462 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6463 Builder.AddTypedTextChunk("atIndexes:");
6464 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6465 Builder.AddPlaceholderChunk("NSIndexSet *");
6466 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6467 Builder.AddTextChunk("indexes");
6468 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6469 CXCursor_ObjCInstanceMethodDecl));
6470 }
6471 }
6472
6473 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6474 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006475 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006476 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006477 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006478 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006479 if (ReturnType.isNull()) {
6480 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6481 Builder.AddTextChunk("void");
6482 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6483 }
6484
6485 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6486 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6487 Builder.AddTextChunk("NSUInteger");
6488 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6489 Builder.AddTextChunk("index");
6490 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6491 CXCursor_ObjCInstanceMethodDecl));
6492 }
6493 }
6494
6495 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6496 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006497 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006498 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006499 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006500 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006501 if (ReturnType.isNull()) {
6502 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6503 Builder.AddTextChunk("void");
6504 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6505 }
6506
6507 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6508 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6509 Builder.AddTextChunk("NSIndexSet *");
6510 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6511 Builder.AddTextChunk("indexes");
6512 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6513 CXCursor_ObjCInstanceMethodDecl));
6514 }
6515 }
6516
6517 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6518 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006519 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006520 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006521 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006522 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006523 &Context.Idents.get("withObject")
6524 };
6525
Douglas Gregore74c25c2011-05-04 23:50:46 +00006526 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006527 if (ReturnType.isNull()) {
6528 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6529 Builder.AddTextChunk("void");
6530 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6531 }
6532
6533 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6534 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6535 Builder.AddPlaceholderChunk("NSUInteger");
6536 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6537 Builder.AddTextChunk("index");
6538 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6539 Builder.AddTypedTextChunk("withObject:");
6540 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6541 Builder.AddTextChunk("id");
6542 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6543 Builder.AddTextChunk("object");
6544 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6545 CXCursor_ObjCInstanceMethodDecl));
6546 }
6547 }
6548
6549 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6550 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006551 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006552 = (Twine("replace") + UpperKey + "AtIndexes").str();
6553 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006554 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006555 &Context.Idents.get(SelectorName1),
6556 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006557 };
6558
Douglas Gregore74c25c2011-05-04 23:50:46 +00006559 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006560 if (ReturnType.isNull()) {
6561 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6562 Builder.AddTextChunk("void");
6563 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6564 }
6565
6566 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6567 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6568 Builder.AddPlaceholderChunk("NSIndexSet *");
6569 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6570 Builder.AddTextChunk("indexes");
6571 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6572 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6573 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6574 Builder.AddTextChunk("NSArray *");
6575 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6576 Builder.AddTextChunk("array");
6577 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6578 CXCursor_ObjCInstanceMethodDecl));
6579 }
6580 }
6581
6582 // Unordered getters
6583 // - (NSEnumerator *)enumeratorOfKey
6584 if (IsInstanceMethod &&
6585 (ReturnType.isNull() ||
6586 (ReturnType->isObjCObjectPointerType() &&
6587 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6588 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6589 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006590 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006591 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006592 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006593 if (ReturnType.isNull()) {
6594 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6595 Builder.AddTextChunk("NSEnumerator *");
6596 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6597 }
6598
6599 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6600 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6601 CXCursor_ObjCInstanceMethodDecl));
6602 }
6603 }
6604
6605 // - (type *)memberOfKey:(type *)object
6606 if (IsInstanceMethod &&
6607 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006608 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006609 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006610 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006611 if (ReturnType.isNull()) {
6612 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6613 Builder.AddPlaceholderChunk("object-type");
6614 Builder.AddTextChunk(" *");
6615 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6616 }
6617
6618 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6619 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6620 if (ReturnType.isNull()) {
6621 Builder.AddPlaceholderChunk("object-type");
6622 Builder.AddTextChunk(" *");
6623 } else {
6624 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006625 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006626 Builder.getAllocator()));
6627 }
6628 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6629 Builder.AddTextChunk("object");
6630 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6631 CXCursor_ObjCInstanceMethodDecl));
6632 }
6633 }
6634
6635 // Mutable unordered accessors
6636 // - (void)addKeyObject:(type *)object
6637 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006638 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006639 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006640 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006641 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006642 if (ReturnType.isNull()) {
6643 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6644 Builder.AddTextChunk("void");
6645 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6646 }
6647
6648 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6649 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6650 Builder.AddPlaceholderChunk("object-type");
6651 Builder.AddTextChunk(" *");
6652 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6653 Builder.AddTextChunk("object");
6654 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6655 CXCursor_ObjCInstanceMethodDecl));
6656 }
6657 }
6658
6659 // - (void)addKey:(NSSet *)objects
6660 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006661 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006662 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006663 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006664 if (ReturnType.isNull()) {
6665 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6666 Builder.AddTextChunk("void");
6667 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6668 }
6669
6670 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6671 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6672 Builder.AddTextChunk("NSSet *");
6673 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6674 Builder.AddTextChunk("objects");
6675 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6676 CXCursor_ObjCInstanceMethodDecl));
6677 }
6678 }
6679
6680 // - (void)removeKeyObject:(type *)object
6681 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006682 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006683 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006684 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006685 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006686 if (ReturnType.isNull()) {
6687 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6688 Builder.AddTextChunk("void");
6689 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6690 }
6691
6692 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6693 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6694 Builder.AddPlaceholderChunk("object-type");
6695 Builder.AddTextChunk(" *");
6696 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6697 Builder.AddTextChunk("object");
6698 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6699 CXCursor_ObjCInstanceMethodDecl));
6700 }
6701 }
6702
6703 // - (void)removeKey:(NSSet *)objects
6704 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006705 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006706 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006707 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006708 if (ReturnType.isNull()) {
6709 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6710 Builder.AddTextChunk("void");
6711 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6712 }
6713
6714 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6715 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6716 Builder.AddTextChunk("NSSet *");
6717 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6718 Builder.AddTextChunk("objects");
6719 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6720 CXCursor_ObjCInstanceMethodDecl));
6721 }
6722 }
6723
6724 // - (void)intersectKey:(NSSet *)objects
6725 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006726 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006727 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006728 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006729 if (ReturnType.isNull()) {
6730 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6731 Builder.AddTextChunk("void");
6732 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6733 }
6734
6735 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6736 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6737 Builder.AddTextChunk("NSSet *");
6738 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6739 Builder.AddTextChunk("objects");
6740 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6741 CXCursor_ObjCInstanceMethodDecl));
6742 }
6743 }
6744
6745 // Key-Value Observing
6746 // + (NSSet *)keyPathsForValuesAffectingKey
6747 if (!IsInstanceMethod &&
6748 (ReturnType.isNull() ||
6749 (ReturnType->isObjCObjectPointerType() &&
6750 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6751 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6752 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006753 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006754 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006755 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006756 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006757 if (ReturnType.isNull()) {
6758 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6759 Builder.AddTextChunk("NSSet *");
6760 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6761 }
6762
6763 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6764 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006765 CXCursor_ObjCClassMethodDecl));
6766 }
6767 }
6768
6769 // + (BOOL)automaticallyNotifiesObserversForKey
6770 if (!IsInstanceMethod &&
6771 (ReturnType.isNull() ||
6772 ReturnType->isIntegerType() ||
6773 ReturnType->isBooleanType())) {
6774 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006775 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006776 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6777 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6778 if (ReturnType.isNull()) {
6779 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6780 Builder.AddTextChunk("BOOL");
6781 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6782 }
6783
6784 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6785 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6786 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006787 }
6788 }
6789}
6790
Douglas Gregore8f5a172010-04-07 00:21:17 +00006791void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6792 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006793 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006794 // Determine the return type of the method we're declaring, if
6795 // provided.
6796 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006797 Decl *IDecl = 0;
6798 if (CurContext->isObjCContainer()) {
6799 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6800 IDecl = cast<Decl>(OCD);
6801 }
Douglas Gregorea766182010-10-18 18:21:28 +00006802 // Determine where we should start searching for methods.
6803 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006804 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006805 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006806 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6807 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006808 IsInImplementation = true;
6809 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006810 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006811 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006812 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006813 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006814 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006815 }
6816
6817 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006818 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006819 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006820 }
6821
Douglas Gregorea766182010-10-18 18:21:28 +00006822 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006823 HandleCodeCompleteResults(this, CodeCompleter,
6824 CodeCompletionContext::CCC_Other,
6825 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006826 return;
6827 }
6828
6829 // Find all of the methods that we could declare/implement here.
6830 KnownMethodsMap KnownMethods;
6831 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006832 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006833
Douglas Gregore8f5a172010-04-07 00:21:17 +00006834 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006835 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006836 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006837 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006838 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006839 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006840 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006841 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6842 MEnd = KnownMethods.end();
6843 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00006844 ObjCMethodDecl *Method = M->second.first;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006845 CodeCompletionBuilder Builder(Results.getAllocator(),
6846 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006847
6848 // If the result type was not already provided, add it to the
6849 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006850 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006851 AddObjCPassingTypeChunk(Method->getResultType(),
6852 Method->getObjCDeclQualifier(),
6853 Context, Policy,
6854 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006855
6856 Selector Sel = Method->getSelector();
6857
6858 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006859 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006860 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006861
6862 // Add parameters to the pattern.
6863 unsigned I = 0;
6864 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6865 PEnd = Method->param_end();
6866 P != PEnd; (void)++P, ++I) {
6867 // Add the part of the selector name.
6868 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006869 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006870 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006871 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6872 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006873 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006874 } else
6875 break;
6876
6877 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006878 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6879 (*P)->getObjCDeclQualifier(),
6880 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006881 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006882
6883 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006884 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006885 }
6886
6887 if (Method->isVariadic()) {
6888 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006889 Builder.AddChunk(CodeCompletionString::CK_Comma);
6890 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006891 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006892
Douglas Gregor447107d2010-05-28 00:57:46 +00006893 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006894 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006895 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6896 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6897 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006898 if (!Method->getResultType()->isVoidType()) {
6899 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006900 Builder.AddTextChunk("return");
6901 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6902 Builder.AddPlaceholderChunk("expression");
6903 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006904 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006905 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006906
Douglas Gregor218937c2011-02-01 19:23:04 +00006907 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6908 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006909 }
6910
Douglas Gregor408be5a2010-08-25 01:08:01 +00006911 unsigned Priority = CCP_CodePattern;
6912 if (!M->second.second)
6913 Priority += CCD_InBaseClass;
6914
Douglas Gregorba103062012-03-27 23:34:16 +00006915 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006916 }
6917
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006918 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6919 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006920 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006921 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006922 Containers.push_back(SearchDecl);
6923
Douglas Gregore74c25c2011-05-04 23:50:46 +00006924 VisitedSelectorSet KnownSelectors;
6925 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6926 MEnd = KnownMethods.end();
6927 M != MEnd; ++M)
6928 KnownSelectors.insert(M->first);
6929
6930
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006931 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
6932 if (!IFace)
6933 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
6934 IFace = Category->getClassInterface();
6935
6936 if (IFace) {
Douglas Gregord3297242013-01-16 23:00:23 +00006937 for (ObjCInterfaceDecl::visible_categories_iterator
6938 Cat = IFace->visible_categories_begin(),
6939 CatEnd = IFace->visible_categories_end();
6940 Cat != CatEnd; ++Cat) {
6941 Containers.push_back(*Cat);
6942 }
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006943 }
6944
6945 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
6946 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
6947 PEnd = Containers[I]->prop_end();
6948 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00006949 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006950 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006951 }
6952 }
6953 }
6954
Douglas Gregore8f5a172010-04-07 00:21:17 +00006955 Results.ExitScope();
6956
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006957 HandleCodeCompleteResults(this, CodeCompleter,
6958 CodeCompletionContext::CCC_Other,
6959 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006960}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006961
6962void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
6963 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00006964 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00006965 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006966 IdentifierInfo **SelIdents,
6967 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006968 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00006969 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006970 if (ExternalSource) {
6971 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6972 I != N; ++I) {
6973 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00006974 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006975 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00006976
6977 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006978 }
6979 }
6980
6981 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00006982 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006983 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006984 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006985 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006986
6987 if (ReturnTy)
6988 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00006989
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006990 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00006991 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6992 MEnd = MethodPool.end();
6993 M != MEnd; ++M) {
6994 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
6995 &M->second.second;
6996 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00006997 MethList = MethList->Next) {
6998 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
6999 NumSelIdents))
7000 continue;
7001
Douglas Gregor40ed9a12010-07-08 23:37:41 +00007002 if (AtParameterName) {
7003 // Suggest parameter names we've seen before.
7004 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
7005 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
7006 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007007 CodeCompletionBuilder Builder(Results.getAllocator(),
7008 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00007009 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007010 Param->getIdentifier()->getName()));
7011 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00007012 }
7013 }
7014
7015 continue;
7016 }
7017
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007018 Result R(MethList->Method, 0);
7019 R.StartParameter = NumSelIdents;
7020 R.AllParametersAreInformative = false;
7021 R.DeclaringEntity = true;
7022 Results.MaybeAddResult(R, CurContext);
7023 }
7024 }
7025
7026 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00007027 HandleCodeCompleteResults(this, CodeCompleter,
7028 CodeCompletionContext::CCC_Other,
7029 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007030}
Douglas Gregor87c08a52010-08-13 22:48:40 +00007031
Douglas Gregorf29c5232010-08-24 22:20:20 +00007032void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007033 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007034 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007035 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007036 Results.EnterNewScope();
7037
7038 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007039 CodeCompletionBuilder Builder(Results.getAllocator(),
7040 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007041 Builder.AddTypedTextChunk("if");
7042 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7043 Builder.AddPlaceholderChunk("condition");
7044 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007045
7046 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007047 Builder.AddTypedTextChunk("ifdef");
7048 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7049 Builder.AddPlaceholderChunk("macro");
7050 Results.AddResult(Builder.TakeString());
7051
Douglas Gregorf44e8542010-08-24 19:08:16 +00007052 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007053 Builder.AddTypedTextChunk("ifndef");
7054 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7055 Builder.AddPlaceholderChunk("macro");
7056 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007057
7058 if (InConditional) {
7059 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007060 Builder.AddTypedTextChunk("elif");
7061 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7062 Builder.AddPlaceholderChunk("condition");
7063 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007064
7065 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007066 Builder.AddTypedTextChunk("else");
7067 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007068
7069 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007070 Builder.AddTypedTextChunk("endif");
7071 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007072 }
7073
7074 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007075 Builder.AddTypedTextChunk("include");
7076 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7077 Builder.AddTextChunk("\"");
7078 Builder.AddPlaceholderChunk("header");
7079 Builder.AddTextChunk("\"");
7080 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007081
7082 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007083 Builder.AddTypedTextChunk("include");
7084 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7085 Builder.AddTextChunk("<");
7086 Builder.AddPlaceholderChunk("header");
7087 Builder.AddTextChunk(">");
7088 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007089
7090 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007091 Builder.AddTypedTextChunk("define");
7092 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7093 Builder.AddPlaceholderChunk("macro");
7094 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007095
7096 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007097 Builder.AddTypedTextChunk("define");
7098 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7099 Builder.AddPlaceholderChunk("macro");
7100 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7101 Builder.AddPlaceholderChunk("args");
7102 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7103 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007104
7105 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007106 Builder.AddTypedTextChunk("undef");
7107 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7108 Builder.AddPlaceholderChunk("macro");
7109 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007110
7111 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007112 Builder.AddTypedTextChunk("line");
7113 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7114 Builder.AddPlaceholderChunk("number");
7115 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007116
7117 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007118 Builder.AddTypedTextChunk("line");
7119 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7120 Builder.AddPlaceholderChunk("number");
7121 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7122 Builder.AddTextChunk("\"");
7123 Builder.AddPlaceholderChunk("filename");
7124 Builder.AddTextChunk("\"");
7125 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007126
7127 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007128 Builder.AddTypedTextChunk("error");
7129 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7130 Builder.AddPlaceholderChunk("message");
7131 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007132
7133 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007134 Builder.AddTypedTextChunk("pragma");
7135 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7136 Builder.AddPlaceholderChunk("arguments");
7137 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007138
David Blaikie4e4d0842012-03-11 07:00:24 +00007139 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007140 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007141 Builder.AddTypedTextChunk("import");
7142 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7143 Builder.AddTextChunk("\"");
7144 Builder.AddPlaceholderChunk("header");
7145 Builder.AddTextChunk("\"");
7146 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007147
7148 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007149 Builder.AddTypedTextChunk("import");
7150 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7151 Builder.AddTextChunk("<");
7152 Builder.AddPlaceholderChunk("header");
7153 Builder.AddTextChunk(">");
7154 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007155 }
7156
7157 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007158 Builder.AddTypedTextChunk("include_next");
7159 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7160 Builder.AddTextChunk("\"");
7161 Builder.AddPlaceholderChunk("header");
7162 Builder.AddTextChunk("\"");
7163 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007164
7165 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007166 Builder.AddTypedTextChunk("include_next");
7167 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7168 Builder.AddTextChunk("<");
7169 Builder.AddPlaceholderChunk("header");
7170 Builder.AddTextChunk(">");
7171 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007172
7173 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007174 Builder.AddTypedTextChunk("warning");
7175 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7176 Builder.AddPlaceholderChunk("message");
7177 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007178
7179 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7180 // completions for them. And __include_macros is a Clang-internal extension
7181 // that we don't want to encourage anyone to use.
7182
7183 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7184 Results.ExitScope();
7185
Douglas Gregorf44e8542010-08-24 19:08:16 +00007186 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007187 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007188 Results.data(), Results.size());
7189}
7190
7191void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007192 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007193 S->getFnParent()? Sema::PCC_RecoveryInFunction
7194 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007195}
7196
Douglas Gregorf29c5232010-08-24 22:20:20 +00007197void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007198 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007199 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007200 IsDefinition? CodeCompletionContext::CCC_MacroName
7201 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007202 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7203 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007204 CodeCompletionBuilder Builder(Results.getAllocator(),
7205 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007206 Results.EnterNewScope();
7207 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7208 MEnd = PP.macro_end();
7209 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007210 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007211 M->first->getName()));
Argyrios Kyrtzidisc04bb922012-09-27 00:24:09 +00007212 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7213 CCP_CodePattern,
7214 CXCursor_MacroDefinition));
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007215 }
7216 Results.ExitScope();
7217 } else if (IsDefinition) {
7218 // FIXME: Can we detect when the user just wrote an include guard above?
7219 }
7220
Douglas Gregor52779fb2010-09-23 23:01:17 +00007221 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007222 Results.data(), Results.size());
7223}
7224
Douglas Gregorf29c5232010-08-24 22:20:20 +00007225void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007226 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007227 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007228 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007229
7230 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007231 AddMacroResults(PP, Results, true);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007232
7233 // defined (<macro>)
7234 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007235 CodeCompletionBuilder Builder(Results.getAllocator(),
7236 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007237 Builder.AddTypedTextChunk("defined");
7238 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7239 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7240 Builder.AddPlaceholderChunk("macro");
7241 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7242 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007243 Results.ExitScope();
7244
7245 HandleCodeCompleteResults(this, CodeCompleter,
7246 CodeCompletionContext::CCC_PreprocessorExpression,
7247 Results.data(), Results.size());
7248}
7249
7250void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7251 IdentifierInfo *Macro,
7252 MacroInfo *MacroInfo,
7253 unsigned Argument) {
7254 // FIXME: In the future, we could provide "overload" results, much like we
7255 // do for function calls.
7256
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007257 // Now just ignore this. There will be another code-completion callback
7258 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007259}
7260
Douglas Gregor55817af2010-08-25 17:04:25 +00007261void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007262 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007263 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007264 0, 0);
7265}
7266
Douglas Gregordae68752011-02-01 22:57:45 +00007267void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007268 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007269 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007270 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7271 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007272 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7273 CodeCompletionDeclConsumer Consumer(Builder,
7274 Context.getTranslationUnitDecl());
7275 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7276 Consumer);
7277 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007278
7279 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007280 AddMacroResults(PP, Builder, true);
Douglas Gregor87c08a52010-08-13 22:48:40 +00007281
7282 Results.clear();
7283 Results.insert(Results.end(),
7284 Builder.data(), Builder.data() + Builder.size());
7285}