blob: cf088007c88072442ed6a960bbed2ca97afe82e7 [file] [log] [blame]
Douglas Gregor81b747b2009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
John McCall2d887082010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.h"
Douglas Gregore737f502010-08-12 20:07:10 +000014#include "clang/Sema/Lookup.h"
John McCall120d63c2010-08-24 20:38:10 +000015#include "clang/Sema/Overload.h"
Douglas Gregor81b747b2009-09-17 21:32:03 +000016#include "clang/Sema/CodeCompleteConsumer.h"
Douglas Gregor719770d2010-04-06 17:30:22 +000017#include "clang/Sema/ExternalSemaSource.h"
John McCall5f1e0942010-08-24 08:50:51 +000018#include "clang/Sema/Scope.h"
John McCall781472f2010-08-25 08:40:02 +000019#include "clang/Sema/ScopeInfo.h"
John McCall7cd088e2010-08-24 07:21:54 +000020#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000021#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000022#include "clang/AST/ExprObjC.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000023#include "clang/Lex/MacroInfo.h"
24#include "clang/Lex/Preprocessor.h"
Douglas Gregord36adf52010-09-16 16:06:31 +000025#include "llvm/ADT/DenseSet.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000026#include "llvm/ADT/SmallPtrSet.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000027#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000028#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000029#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000030#include <list>
31#include <map>
32#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000033
34using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000035using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000036
Douglas Gregor86d9a522009-09-21 16:56:56 +000037namespace {
38 /// \brief A container of code-completion results.
39 class ResultBuilder {
40 public:
41 /// \brief The type of a name-lookup filter, which can be provided to the
42 /// name-lookup routines to specify which declarations should be included in
43 /// the result set (when it returns true) and which declarations should be
44 /// filtered out (returns false).
45 typedef bool (ResultBuilder::*LookupFilter)(NamedDecl *) const;
46
John McCall0a2c5e22010-08-25 06:19:51 +000047 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000048
49 private:
50 /// \brief The actual results we have found.
51 std::vector<Result> Results;
52
53 /// \brief A record of all of the declarations we have found and placed
54 /// into the result set, used to ensure that no declaration ever gets into
55 /// the result set twice.
56 llvm::SmallPtrSet<Decl*, 16> AllDeclsFound;
57
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000058 typedef std::pair<NamedDecl *, unsigned> DeclIndexPair;
59
60 /// \brief An entry in the shadow map, which is optimized to store
61 /// a single (declaration, index) mapping (the common case) but
62 /// can also store a list of (declaration, index) mappings.
63 class ShadowMapEntry {
64 typedef llvm::SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
65
66 /// \brief Contains either the solitary NamedDecl * or a vector
67 /// of (declaration, index) pairs.
68 llvm::PointerUnion<NamedDecl *, DeclIndexPairVector*> DeclOrVector;
69
70 /// \brief When the entry contains a single declaration, this is
71 /// the index associated with that entry.
72 unsigned SingleDeclIndex;
73
74 public:
75 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
76
77 void Add(NamedDecl *ND, unsigned Index) {
78 if (DeclOrVector.isNull()) {
79 // 0 - > 1 elements: just set the single element information.
80 DeclOrVector = ND;
81 SingleDeclIndex = Index;
82 return;
83 }
84
85 if (NamedDecl *PrevND = DeclOrVector.dyn_cast<NamedDecl *>()) {
86 // 1 -> 2 elements: create the vector of results and push in the
87 // existing declaration.
88 DeclIndexPairVector *Vec = new DeclIndexPairVector;
89 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
90 DeclOrVector = Vec;
91 }
92
93 // Add the new element to the end of the vector.
94 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
95 DeclIndexPair(ND, Index));
96 }
97
98 void Destroy() {
99 if (DeclIndexPairVector *Vec
100 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
101 delete Vec;
102 DeclOrVector = ((NamedDecl *)0);
103 }
104 }
105
106 // Iteration.
107 class iterator;
108 iterator begin() const;
109 iterator end() const;
110 };
111
Douglas Gregor86d9a522009-09-21 16:56:56 +0000112 /// \brief A mapping from declaration names to the declarations that have
113 /// this name within a particular scope and their index within the list of
114 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000115 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000116
117 /// \brief The semantic analysis object for which results are being
118 /// produced.
119 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000120
121 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000122 CodeCompletionAllocator &Allocator;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000123
124 /// \brief If non-NULL, a filter function used to remove any code-completion
125 /// results that are not desirable.
126 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000127
128 /// \brief Whether we should allow declarations as
129 /// nested-name-specifiers that would otherwise be filtered out.
130 bool AllowNestedNameSpecifiers;
131
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000132 /// \brief If set, the type that we would prefer our resulting value
133 /// declarations to have.
134 ///
135 /// Closely matching the preferred type gives a boost to a result's
136 /// priority.
137 CanQualType PreferredType;
138
Douglas Gregor86d9a522009-09-21 16:56:56 +0000139 /// \brief A list of shadow maps, which is used to model name hiding at
140 /// different levels of, e.g., the inheritance hierarchy.
141 std::list<ShadowMap> ShadowMaps;
142
Douglas Gregor3cdee122010-08-26 16:36:48 +0000143 /// \brief If we're potentially referring to a C++ member function, the set
144 /// of qualifiers applied to the object type.
145 Qualifiers ObjectTypeQualifiers;
146
147 /// \brief Whether the \p ObjectTypeQualifiers field is active.
148 bool HasObjectTypeQualifiers;
149
Douglas Gregor265f7492010-08-27 15:29:55 +0000150 /// \brief The selector that we prefer.
151 Selector PreferredSelector;
152
Douglas Gregorca45da02010-11-02 20:36:02 +0000153 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000154 CodeCompletionContext CompletionContext;
155
Douglas Gregorca45da02010-11-02 20:36:02 +0000156 /// \brief If we are in an instance method definition, the @implementation
157 /// object.
158 ObjCImplementationDecl *ObjCImplementation;
159
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000160 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000161
Douglas Gregor6f942b22010-09-21 16:06:22 +0000162 void MaybeAddConstructorResults(Result R);
163
Douglas Gregor86d9a522009-09-21 16:56:56 +0000164 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000165 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000166 const CodeCompletionContext &CompletionContext,
167 LookupFilter Filter = 0)
Douglas Gregor218937c2011-02-01 19:23:04 +0000168 : SemaRef(SemaRef), Allocator(Allocator), Filter(Filter),
169 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000170 CompletionContext(CompletionContext),
171 ObjCImplementation(0)
172 {
173 // If this is an Objective-C instance method definition, dig out the
174 // corresponding implementation.
175 switch (CompletionContext.getKind()) {
176 case CodeCompletionContext::CCC_Expression:
177 case CodeCompletionContext::CCC_ObjCMessageReceiver:
178 case CodeCompletionContext::CCC_ParenthesizedExpression:
179 case CodeCompletionContext::CCC_Statement:
180 case CodeCompletionContext::CCC_Recovery:
181 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
182 if (Method->isInstanceMethod())
183 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
184 ObjCImplementation = Interface->getImplementation();
185 break;
186
187 default:
188 break;
189 }
190 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000191
Douglas Gregord8e8a582010-05-25 21:41:55 +0000192 /// \brief Whether we should include code patterns in the completion
193 /// results.
194 bool includeCodePatterns() const {
195 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000196 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000197 }
198
Douglas Gregor86d9a522009-09-21 16:56:56 +0000199 /// \brief Set the filter used for code-completion results.
200 void setFilter(LookupFilter Filter) {
201 this->Filter = Filter;
202 }
203
Douglas Gregor86d9a522009-09-21 16:56:56 +0000204 Result *data() { return Results.empty()? 0 : &Results.front(); }
205 unsigned size() const { return Results.size(); }
206 bool empty() const { return Results.empty(); }
207
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000208 /// \brief Specify the preferred type.
209 void setPreferredType(QualType T) {
210 PreferredType = SemaRef.Context.getCanonicalType(T);
211 }
212
Douglas Gregor3cdee122010-08-26 16:36:48 +0000213 /// \brief Set the cv-qualifiers on the object type, for us in filtering
214 /// calls to member functions.
215 ///
216 /// When there are qualifiers in this set, they will be used to filter
217 /// out member functions that aren't available (because there will be a
218 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
219 /// match.
220 void setObjectTypeQualifiers(Qualifiers Quals) {
221 ObjectTypeQualifiers = Quals;
222 HasObjectTypeQualifiers = true;
223 }
224
Douglas Gregor265f7492010-08-27 15:29:55 +0000225 /// \brief Set the preferred selector.
226 ///
227 /// When an Objective-C method declaration result is added, and that
228 /// method's selector matches this preferred selector, we give that method
229 /// a slight priority boost.
230 void setPreferredSelector(Selector Sel) {
231 PreferredSelector = Sel;
232 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000233
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000234 /// \brief Retrieve the code-completion context for which results are
235 /// being collected.
236 const CodeCompletionContext &getCompletionContext() const {
237 return CompletionContext;
238 }
239
Douglas Gregor45bcd432010-01-14 03:21:49 +0000240 /// \brief Specify whether nested-name-specifiers are allowed.
241 void allowNestedNameSpecifiers(bool Allow = true) {
242 AllowNestedNameSpecifiers = Allow;
243 }
244
Douglas Gregorb9d77572010-09-21 00:03:25 +0000245 /// \brief Return the semantic analysis object for which we are collecting
246 /// code completion results.
247 Sema &getSema() const { return SemaRef; }
248
Douglas Gregor218937c2011-02-01 19:23:04 +0000249 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000250 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000251
Douglas Gregore495b7f2010-01-14 00:20:49 +0000252 /// \brief Determine whether the given declaration is at all interesting
253 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000254 ///
255 /// \param ND the declaration that we are inspecting.
256 ///
257 /// \param AsNestedNameSpecifier will be set true if this declaration is
258 /// only interesting when it is a nested-name-specifier.
259 bool isInterestingDecl(NamedDecl *ND, bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000260
261 /// \brief Check whether the result is hidden by the Hiding declaration.
262 ///
263 /// \returns true if the result is hidden and cannot be found, false if
264 /// the hidden result could still be found. When false, \p R may be
265 /// modified to describe how the result can be found (e.g., via extra
266 /// qualification).
267 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
268 NamedDecl *Hiding);
269
Douglas Gregor86d9a522009-09-21 16:56:56 +0000270 /// \brief Add a new result to this result set (if it isn't already in one
271 /// of the shadow maps), or replace an existing result (for, e.g., a
272 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000273 ///
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000274 /// \param CurContext the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000275 ///
276 /// \param R the context in which this result will be named.
277 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000278
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000279 /// \brief Add a new result to this result set, where we already know
280 /// the hiding declation (if any).
281 ///
282 /// \param R the result to add (if it is unique).
283 ///
284 /// \param CurContext the context in which this result will be named.
285 ///
286 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000287 ///
288 /// \param InBaseClass whether the result was found in a base
289 /// class of the searched context.
290 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
291 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000292
Douglas Gregora4477812010-01-14 16:01:26 +0000293 /// \brief Add a new non-declaration result to this result set.
294 void AddResult(Result R);
295
Douglas Gregor86d9a522009-09-21 16:56:56 +0000296 /// \brief Enter into a new scope.
297 void EnterNewScope();
298
299 /// \brief Exit from the current scope.
300 void ExitScope();
301
Douglas Gregor55385fe2009-11-18 04:19:12 +0000302 /// \brief Ignore this declaration, if it is seen again.
303 void Ignore(Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
304
Douglas Gregor86d9a522009-09-21 16:56:56 +0000305 /// \name Name lookup predicates
306 ///
307 /// These predicates can be passed to the name lookup functions to filter the
308 /// results of name lookup. All of the predicates have the same type, so that
309 ///
310 //@{
Douglas Gregor791215b2009-09-21 20:51:25 +0000311 bool IsOrdinaryName(NamedDecl *ND) const;
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000312 bool IsOrdinaryNonTypeName(NamedDecl *ND) const;
Douglas Gregorf9578432010-07-28 21:50:18 +0000313 bool IsIntegralConstantValue(NamedDecl *ND) const;
Douglas Gregor01dfea02010-01-10 23:08:15 +0000314 bool IsOrdinaryNonValueName(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000315 bool IsNestedNameSpecifier(NamedDecl *ND) const;
316 bool IsEnum(NamedDecl *ND) const;
317 bool IsClassOrStruct(NamedDecl *ND) const;
318 bool IsUnion(NamedDecl *ND) const;
319 bool IsNamespace(NamedDecl *ND) const;
320 bool IsNamespaceOrAlias(NamedDecl *ND) const;
321 bool IsType(NamedDecl *ND) const;
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000322 bool IsMember(NamedDecl *ND) const;
Douglas Gregor80f4f4c2010-01-14 16:08:12 +0000323 bool IsObjCIvar(NamedDecl *ND) const;
Douglas Gregor8e254cf2010-05-27 23:06:34 +0000324 bool IsObjCMessageReceiver(NamedDecl *ND) const;
Douglas Gregorfb629412010-08-23 21:17:50 +0000325 bool IsObjCCollection(NamedDecl *ND) const;
Douglas Gregor52779fb2010-09-23 23:01:17 +0000326 bool IsImpossibleToSatisfy(NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000327 //@}
328 };
329}
330
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000331class ResultBuilder::ShadowMapEntry::iterator {
332 llvm::PointerUnion<NamedDecl*, const DeclIndexPair*> DeclOrIterator;
333 unsigned SingleDeclIndex;
334
335public:
336 typedef DeclIndexPair value_type;
337 typedef value_type reference;
338 typedef std::ptrdiff_t difference_type;
339 typedef std::input_iterator_tag iterator_category;
340
341 class pointer {
342 DeclIndexPair Value;
343
344 public:
345 pointer(const DeclIndexPair &Value) : Value(Value) { }
346
347 const DeclIndexPair *operator->() const {
348 return &Value;
349 }
350 };
351
352 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
353
354 iterator(NamedDecl *SingleDecl, unsigned Index)
355 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
356
357 iterator(const DeclIndexPair *Iterator)
358 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
359
360 iterator &operator++() {
361 if (DeclOrIterator.is<NamedDecl *>()) {
362 DeclOrIterator = (NamedDecl *)0;
363 SingleDeclIndex = 0;
364 return *this;
365 }
366
367 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
368 ++I;
369 DeclOrIterator = I;
370 return *this;
371 }
372
Chris Lattner66392d42010-09-04 18:12:20 +0000373 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000374 iterator tmp(*this);
375 ++(*this);
376 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000377 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000378
379 reference operator*() const {
380 if (NamedDecl *ND = DeclOrIterator.dyn_cast<NamedDecl *>())
381 return reference(ND, SingleDeclIndex);
382
Douglas Gregord490f952009-12-06 21:27:58 +0000383 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000384 }
385
386 pointer operator->() const {
387 return pointer(**this);
388 }
389
390 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000391 return X.DeclOrIterator.getOpaqueValue()
392 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000393 X.SingleDeclIndex == Y.SingleDeclIndex;
394 }
395
396 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000397 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000398 }
399};
400
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000401ResultBuilder::ShadowMapEntry::iterator
402ResultBuilder::ShadowMapEntry::begin() const {
403 if (DeclOrVector.isNull())
404 return iterator();
405
406 if (NamedDecl *ND = DeclOrVector.dyn_cast<NamedDecl *>())
407 return iterator(ND, SingleDeclIndex);
408
409 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
410}
411
412ResultBuilder::ShadowMapEntry::iterator
413ResultBuilder::ShadowMapEntry::end() const {
414 if (DeclOrVector.is<NamedDecl *>() || DeclOrVector.isNull())
415 return iterator();
416
417 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
418}
419
Douglas Gregor456c4a12009-09-21 20:12:40 +0000420/// \brief Compute the qualification required to get from the current context
421/// (\p CurContext) to the target context (\p TargetContext).
422///
423/// \param Context the AST context in which the qualification will be used.
424///
425/// \param CurContext the context where an entity is being named, which is
426/// typically based on the current scope.
427///
428/// \param TargetContext the context in which the named entity actually
429/// resides.
430///
431/// \returns a nested name specifier that refers into the target context, or
432/// NULL if no qualification is needed.
433static NestedNameSpecifier *
434getRequiredQualification(ASTContext &Context,
435 DeclContext *CurContext,
436 DeclContext *TargetContext) {
437 llvm::SmallVector<DeclContext *, 4> TargetParents;
438
439 for (DeclContext *CommonAncestor = TargetContext;
440 CommonAncestor && !CommonAncestor->Encloses(CurContext);
441 CommonAncestor = CommonAncestor->getLookupParent()) {
442 if (CommonAncestor->isTransparentContext() ||
443 CommonAncestor->isFunctionOrMethod())
444 continue;
445
446 TargetParents.push_back(CommonAncestor);
447 }
448
449 NestedNameSpecifier *Result = 0;
450 while (!TargetParents.empty()) {
451 DeclContext *Parent = TargetParents.back();
452 TargetParents.pop_back();
453
Douglas Gregorfb629412010-08-23 21:17:50 +0000454 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
455 if (!Namespace->getIdentifier())
456 continue;
457
Douglas Gregor456c4a12009-09-21 20:12:40 +0000458 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000459 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000460 else if (TagDecl *TD = dyn_cast<TagDecl>(Parent))
461 Result = NestedNameSpecifier::Create(Context, Result,
462 false,
463 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000464 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000465 return Result;
466}
467
Douglas Gregor45bcd432010-01-14 03:21:49 +0000468bool ResultBuilder::isInterestingDecl(NamedDecl *ND,
469 bool &AsNestedNameSpecifier) const {
470 AsNestedNameSpecifier = false;
471
Douglas Gregore495b7f2010-01-14 00:20:49 +0000472 ND = ND->getUnderlyingDecl();
473 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000474
475 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000476 if (!ND->getDeclName())
477 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000478
479 // Friend declarations and declarations introduced due to friends are never
480 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000481 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000482 return false;
483
Douglas Gregor76282942009-12-11 17:31:05 +0000484 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000485 if (isa<ClassTemplateSpecializationDecl>(ND) ||
486 isa<ClassTemplatePartialSpecializationDecl>(ND))
487 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000488
Douglas Gregor76282942009-12-11 17:31:05 +0000489 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000490 if (isa<UsingDecl>(ND))
491 return false;
492
493 // Some declarations have reserved names that we don't want to ever show.
494 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000495 // __va_list_tag is a freak of nature. Find it and skip it.
496 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000497 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000498
Douglas Gregorf52cede2009-10-09 22:16:47 +0000499 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000500 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000501 //
502 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000503 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000504 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000505 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000506 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
507 (ND->getLocation().isInvalid() ||
508 SemaRef.SourceMgr.isInSystemHeader(
509 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000510 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000511 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000512 }
Douglas Gregor6f942b22010-09-21 16:06:22 +0000513
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000514 // Skip out-of-line declarations and definitions.
515 // NOTE: Unless it's an Objective-C property, method, or ivar, where
516 // the contexts can be messy.
517 if (!ND->getDeclContext()->Equals(ND->getLexicalDeclContext()) &&
518 !(isa<ObjCPropertyDecl>(ND) || isa<ObjCIvarDecl>(ND) ||
519 isa<ObjCMethodDecl>(ND)))
520 return false;
521
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000522 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
523 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
524 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000525 Filter != &ResultBuilder::IsNamespaceOrAlias &&
526 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000527 AsNestedNameSpecifier = true;
528
Douglas Gregor86d9a522009-09-21 16:56:56 +0000529 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000530 if (Filter && !(this->*Filter)(ND)) {
531 // Check whether it is interesting as a nested-name-specifier.
532 if (AllowNestedNameSpecifiers && SemaRef.getLangOptions().CPlusPlus &&
533 IsNestedNameSpecifier(ND) &&
534 (Filter != &ResultBuilder::IsMember ||
535 (isa<CXXRecordDecl>(ND) &&
536 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
537 AsNestedNameSpecifier = true;
538 return true;
539 }
540
Douglas Gregore495b7f2010-01-14 00:20:49 +0000541 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000542 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000543 // ... then it must be interesting!
544 return true;
545}
546
Douglas Gregor6660d842010-01-14 00:41:07 +0000547bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
548 NamedDecl *Hiding) {
549 // In C, there is no way to refer to a hidden name.
550 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
551 // name if we introduce the tag type.
552 if (!SemaRef.getLangOptions().CPlusPlus)
553 return true;
554
Sebastian Redl7a126a42010-08-31 00:36:30 +0000555 DeclContext *HiddenCtx = R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000556
557 // There is no way to qualify a name declared in a function or method.
558 if (HiddenCtx->isFunctionOrMethod())
559 return true;
560
Sebastian Redl7a126a42010-08-31 00:36:30 +0000561 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000562 return true;
563
564 // We can refer to the result with the appropriate qualification. Do it.
565 R.Hidden = true;
566 R.QualifierIsInformative = false;
567
568 if (!R.Qualifier)
569 R.Qualifier = getRequiredQualification(SemaRef.Context,
570 CurContext,
571 R.Declaration->getDeclContext());
572 return false;
573}
574
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000575/// \brief A simplified classification of types used to determine whether two
576/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000577SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000578 switch (T->getTypeClass()) {
579 case Type::Builtin:
580 switch (cast<BuiltinType>(T)->getKind()) {
581 case BuiltinType::Void:
582 return STC_Void;
583
584 case BuiltinType::NullPtr:
585 return STC_Pointer;
586
587 case BuiltinType::Overload:
588 case BuiltinType::Dependent:
589 case BuiltinType::UndeducedAuto:
590 return STC_Other;
591
592 case BuiltinType::ObjCId:
593 case BuiltinType::ObjCClass:
594 case BuiltinType::ObjCSel:
595 return STC_ObjectiveC;
596
597 default:
598 return STC_Arithmetic;
599 }
600 return STC_Other;
601
602 case Type::Complex:
603 return STC_Arithmetic;
604
605 case Type::Pointer:
606 return STC_Pointer;
607
608 case Type::BlockPointer:
609 return STC_Block;
610
611 case Type::LValueReference:
612 case Type::RValueReference:
613 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
614
615 case Type::ConstantArray:
616 case Type::IncompleteArray:
617 case Type::VariableArray:
618 case Type::DependentSizedArray:
619 return STC_Array;
620
621 case Type::DependentSizedExtVector:
622 case Type::Vector:
623 case Type::ExtVector:
624 return STC_Arithmetic;
625
626 case Type::FunctionProto:
627 case Type::FunctionNoProto:
628 return STC_Function;
629
630 case Type::Record:
631 return STC_Record;
632
633 case Type::Enum:
634 return STC_Arithmetic;
635
636 case Type::ObjCObject:
637 case Type::ObjCInterface:
638 case Type::ObjCObjectPointer:
639 return STC_ObjectiveC;
640
641 default:
642 return STC_Other;
643 }
644}
645
646/// \brief Get the type that a given expression will have if this declaration
647/// is used as an expression in its "typical" code-completion form.
Douglas Gregor1827e102010-08-16 16:18:59 +0000648QualType clang::getDeclUsageType(ASTContext &C, NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000649 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
650
651 if (TypeDecl *Type = dyn_cast<TypeDecl>(ND))
652 return C.getTypeDeclType(Type);
653 if (ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
654 return C.getObjCInterfaceType(Iface);
655
656 QualType T;
657 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000658 T = Function->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000659 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000660 T = Method->getSendResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000661 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000662 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000663 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
664 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
665 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
666 T = Property->getType();
667 else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
668 T = Value->getType();
669 else
670 return QualType();
671
672 return T.getNonReferenceType();
673}
674
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000675void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
676 // If this is an Objective-C method declaration whose selector matches our
677 // preferred selector, give it a priority boost.
678 if (!PreferredSelector.isNull())
679 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
680 if (PreferredSelector == Method->getSelector())
681 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000682
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000683 // If we have a preferred type, adjust the priority for results with exactly-
684 // matching or nearly-matching types.
685 if (!PreferredType.isNull()) {
686 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
687 if (!T.isNull()) {
688 CanQualType TC = SemaRef.Context.getCanonicalType(T);
689 // Check for exactly-matching types (modulo qualifiers).
690 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
691 R.Priority /= CCF_ExactTypeMatch;
692 // Check for nearly-matching types, based on classification of each.
693 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000694 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000695 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
696 R.Priority /= CCF_SimilarTypeMatch;
697 }
698 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000699}
700
Douglas Gregor6f942b22010-09-21 16:06:22 +0000701void ResultBuilder::MaybeAddConstructorResults(Result R) {
702 if (!SemaRef.getLangOptions().CPlusPlus || !R.Declaration ||
703 !CompletionContext.wantConstructorResults())
704 return;
705
706 ASTContext &Context = SemaRef.Context;
707 NamedDecl *D = R.Declaration;
708 CXXRecordDecl *Record = 0;
709 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
710 Record = ClassTemplate->getTemplatedDecl();
711 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
712 // Skip specializations and partial specializations.
713 if (isa<ClassTemplateSpecializationDecl>(Record))
714 return;
715 } else {
716 // There are no constructors here.
717 return;
718 }
719
720 Record = Record->getDefinition();
721 if (!Record)
722 return;
723
724
725 QualType RecordTy = Context.getTypeDeclType(Record);
726 DeclarationName ConstructorName
727 = Context.DeclarationNames.getCXXConstructorName(
728 Context.getCanonicalType(RecordTy));
729 for (DeclContext::lookup_result Ctors = Record->lookup(ConstructorName);
730 Ctors.first != Ctors.second; ++Ctors.first) {
731 R.Declaration = *Ctors.first;
732 R.CursorKind = getCursorKindForDecl(R.Declaration);
733 Results.push_back(R);
734 }
735}
736
Douglas Gregore495b7f2010-01-14 00:20:49 +0000737void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
738 assert(!ShadowMaps.empty() && "Must enter into a results scope");
739
740 if (R.Kind != Result::RK_Declaration) {
741 // For non-declaration results, just add the result.
742 Results.push_back(R);
743 return;
744 }
745
746 // Look through using declarations.
747 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
748 MaybeAddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext);
749 return;
750 }
751
752 Decl *CanonDecl = R.Declaration->getCanonicalDecl();
753 unsigned IDNS = CanonDecl->getIdentifierNamespace();
754
Douglas Gregor45bcd432010-01-14 03:21:49 +0000755 bool AsNestedNameSpecifier = false;
756 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000757 return;
758
Douglas Gregor6f942b22010-09-21 16:06:22 +0000759 // C++ constructors are never found by name lookup.
760 if (isa<CXXConstructorDecl>(R.Declaration))
761 return;
762
Douglas Gregor86d9a522009-09-21 16:56:56 +0000763 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000764 ShadowMapEntry::iterator I, IEnd;
765 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
766 if (NamePos != SMap.end()) {
767 I = NamePos->second.begin();
768 IEnd = NamePos->second.end();
769 }
770
771 for (; I != IEnd; ++I) {
772 NamedDecl *ND = I->first;
773 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000774 if (ND->getCanonicalDecl() == CanonDecl) {
775 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000776 Results[Index].Declaration = R.Declaration;
777
Douglas Gregor86d9a522009-09-21 16:56:56 +0000778 // We're done.
779 return;
780 }
781 }
782
783 // This is a new declaration in this scope. However, check whether this
784 // declaration name is hidden by a similarly-named declaration in an outer
785 // scope.
786 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
787 --SMEnd;
788 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000789 ShadowMapEntry::iterator I, IEnd;
790 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
791 if (NamePos != SM->end()) {
792 I = NamePos->second.begin();
793 IEnd = NamePos->second.end();
794 }
795 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000796 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000797 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000798 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
799 Decl::IDNS_ObjCProtocol)))
800 continue;
801
802 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000803 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000804 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000805 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000806 continue;
807
808 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000809 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000810 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000811
812 break;
813 }
814 }
815
816 // Make sure that any given declaration only shows up in the result set once.
817 if (!AllDeclsFound.insert(CanonDecl))
818 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000819
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000820 // If the filter is for nested-name-specifiers, then this result starts a
821 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000822 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000823 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000824 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000825 } else
826 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000827
Douglas Gregor0563c262009-09-22 23:15:58 +0000828 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000829 if (R.QualifierIsInformative && !R.Qualifier &&
830 !R.StartsNestedNameSpecifier) {
Douglas Gregor0563c262009-09-22 23:15:58 +0000831 DeclContext *Ctx = R.Declaration->getDeclContext();
832 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
833 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
834 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
835 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
836 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
837 else
838 R.QualifierIsInformative = false;
839 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000840
Douglas Gregor86d9a522009-09-21 16:56:56 +0000841 // Insert this result into the set of results and into the current shadow
842 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000843 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000844 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000845
846 if (!AsNestedNameSpecifier)
847 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000848}
849
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000850void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000851 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000852 if (R.Kind != Result::RK_Declaration) {
853 // For non-declaration results, just add the result.
854 Results.push_back(R);
855 return;
856 }
857
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000858 // Look through using declarations.
859 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
860 AddResult(Result(Using->getTargetDecl(), R.Qualifier), CurContext, Hiding);
861 return;
862 }
863
Douglas Gregor45bcd432010-01-14 03:21:49 +0000864 bool AsNestedNameSpecifier = false;
865 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000866 return;
867
Douglas Gregor6f942b22010-09-21 16:06:22 +0000868 // C++ constructors are never found by name lookup.
869 if (isa<CXXConstructorDecl>(R.Declaration))
870 return;
871
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000872 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
873 return;
874
875 // Make sure that any given declaration only shows up in the result set once.
876 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
877 return;
878
879 // If the filter is for nested-name-specifiers, then this result starts a
880 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000881 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000882 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000883 R.Priority = CCP_NestedNameSpecifier;
884 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000885 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
886 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000887 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000888 R.QualifierIsInformative = true;
889
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000890 // If this result is supposed to have an informative qualifier, add one.
891 if (R.QualifierIsInformative && !R.Qualifier &&
892 !R.StartsNestedNameSpecifier) {
893 DeclContext *Ctx = R.Declaration->getDeclContext();
894 if (NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
895 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
896 else if (TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
897 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000898 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000899 else
900 R.QualifierIsInformative = false;
901 }
902
Douglas Gregor12e13132010-05-26 22:00:08 +0000903 // Adjust the priority if this result comes from a base class.
904 if (InBaseClass)
905 R.Priority += CCD_InBaseClass;
906
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000907 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000908
Douglas Gregor3cdee122010-08-26 16:36:48 +0000909 if (HasObjectTypeQualifiers)
910 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
911 if (Method->isInstance()) {
912 Qualifiers MethodQuals
913 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
914 if (ObjectTypeQualifiers == MethodQuals)
915 R.Priority += CCD_ObjectQualifierMatch;
916 else if (ObjectTypeQualifiers - MethodQuals) {
917 // The method cannot be invoked, because doing so would drop
918 // qualifiers.
919 return;
920 }
921 }
922
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000923 // Insert this result into the set of results.
924 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000925
926 if (!AsNestedNameSpecifier)
927 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000928}
929
Douglas Gregora4477812010-01-14 16:01:26 +0000930void ResultBuilder::AddResult(Result R) {
931 assert(R.Kind != Result::RK_Declaration &&
932 "Declaration results need more context");
933 Results.push_back(R);
934}
935
Douglas Gregor86d9a522009-09-21 16:56:56 +0000936/// \brief Enter into a new scope.
937void ResultBuilder::EnterNewScope() {
938 ShadowMaps.push_back(ShadowMap());
939}
940
941/// \brief Exit from the current scope.
942void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000943 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
944 EEnd = ShadowMaps.back().end();
945 E != EEnd;
946 ++E)
947 E->second.Destroy();
948
Douglas Gregor86d9a522009-09-21 16:56:56 +0000949 ShadowMaps.pop_back();
950}
951
Douglas Gregor791215b2009-09-21 20:51:25 +0000952/// \brief Determines whether this given declaration will be found by
953/// ordinary name lookup.
954bool ResultBuilder::IsOrdinaryName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000955 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
956
Douglas Gregor791215b2009-09-21 20:51:25 +0000957 unsigned IDNS = Decl::IDNS_Ordinary;
958 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000959 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +0000960 else if (SemaRef.getLangOptions().ObjC1) {
961 if (isa<ObjCIvarDecl>(ND))
962 return true;
963 if (isa<ObjCPropertyDecl>(ND) &&
964 SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
965 return true;
966 }
967
Douglas Gregor791215b2009-09-21 20:51:25 +0000968 return ND->getIdentifierNamespace() & IDNS;
969}
970
Douglas Gregor01dfea02010-01-10 23:08:15 +0000971/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000972/// ordinary name lookup but is not a type name.
973bool ResultBuilder::IsOrdinaryNonTypeName(NamedDecl *ND) const {
974 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
975 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
976 return false;
977
978 unsigned IDNS = Decl::IDNS_Ordinary;
979 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +0000980 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Douglas Gregorca45da02010-11-02 20:36:02 +0000981 else if (SemaRef.getLangOptions().ObjC1) {
982 if (isa<ObjCIvarDecl>(ND))
983 return true;
984 if (isa<ObjCPropertyDecl>(ND) &&
985 SemaRef.canSynthesizeProvisionalIvar(cast<ObjCPropertyDecl>(ND)))
986 return true;
987 }
988
Douglas Gregor4710e5b2010-05-28 00:49:12 +0000989 return ND->getIdentifierNamespace() & IDNS;
990}
991
Douglas Gregorf9578432010-07-28 21:50:18 +0000992bool ResultBuilder::IsIntegralConstantValue(NamedDecl *ND) const {
993 if (!IsOrdinaryNonTypeName(ND))
994 return 0;
995
996 if (ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
997 if (VD->getType()->isIntegralOrEnumerationType())
998 return true;
999
1000 return false;
1001}
1002
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001003/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001004/// ordinary name lookup.
1005bool ResultBuilder::IsOrdinaryNonValueName(NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001006 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1007
Douglas Gregor01dfea02010-01-10 23:08:15 +00001008 unsigned IDNS = Decl::IDNS_Ordinary;
1009 if (SemaRef.getLangOptions().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001010 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001011
1012 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001013 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1014 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001015}
1016
Douglas Gregor86d9a522009-09-21 16:56:56 +00001017/// \brief Determines whether the given declaration is suitable as the
1018/// start of a C++ nested-name-specifier, e.g., a class or namespace.
1019bool ResultBuilder::IsNestedNameSpecifier(NamedDecl *ND) const {
1020 // Allow us to find class templates, too.
1021 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1022 ND = ClassTemplate->getTemplatedDecl();
1023
1024 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1025}
1026
1027/// \brief Determines whether the given declaration is an enumeration.
1028bool ResultBuilder::IsEnum(NamedDecl *ND) const {
1029 return isa<EnumDecl>(ND);
1030}
1031
1032/// \brief Determines whether the given declaration is a class or struct.
1033bool ResultBuilder::IsClassOrStruct(NamedDecl *ND) const {
1034 // Allow us to find class templates, too.
1035 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1036 ND = ClassTemplate->getTemplatedDecl();
1037
1038 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001039 return RD->getTagKind() == TTK_Class ||
1040 RD->getTagKind() == TTK_Struct;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001041
1042 return false;
1043}
1044
1045/// \brief Determines whether the given declaration is a union.
1046bool ResultBuilder::IsUnion(NamedDecl *ND) const {
1047 // Allow us to find class templates, too.
1048 if (ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
1049 ND = ClassTemplate->getTemplatedDecl();
1050
1051 if (RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001052 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001053
1054 return false;
1055}
1056
1057/// \brief Determines whether the given declaration is a namespace.
1058bool ResultBuilder::IsNamespace(NamedDecl *ND) const {
1059 return isa<NamespaceDecl>(ND);
1060}
1061
1062/// \brief Determines whether the given declaration is a namespace or
1063/// namespace alias.
1064bool ResultBuilder::IsNamespaceOrAlias(NamedDecl *ND) const {
1065 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1066}
1067
Douglas Gregor76282942009-12-11 17:31:05 +00001068/// \brief Determines whether the given declaration is a type.
Douglas Gregor86d9a522009-09-21 16:56:56 +00001069bool ResultBuilder::IsType(NamedDecl *ND) const {
Douglas Gregord32b0222010-08-24 01:06:58 +00001070 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1071 ND = Using->getTargetDecl();
1072
1073 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001074}
1075
Douglas Gregor76282942009-12-11 17:31:05 +00001076/// \brief Determines which members of a class should be visible via
1077/// "." or "->". Only value declarations, nested name specifiers, and
1078/// using declarations thereof should show up.
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001079bool ResultBuilder::IsMember(NamedDecl *ND) const {
Douglas Gregor76282942009-12-11 17:31:05 +00001080 if (UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
1081 ND = Using->getTargetDecl();
1082
Douglas Gregorce821962009-12-11 18:14:22 +00001083 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1084 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001085}
1086
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001087static bool isObjCReceiverType(ASTContext &C, QualType T) {
1088 T = C.getCanonicalType(T);
1089 switch (T->getTypeClass()) {
1090 case Type::ObjCObject:
1091 case Type::ObjCInterface:
1092 case Type::ObjCObjectPointer:
1093 return true;
1094
1095 case Type::Builtin:
1096 switch (cast<BuiltinType>(T)->getKind()) {
1097 case BuiltinType::ObjCId:
1098 case BuiltinType::ObjCClass:
1099 case BuiltinType::ObjCSel:
1100 return true;
1101
1102 default:
1103 break;
1104 }
1105 return false;
1106
1107 default:
1108 break;
1109 }
1110
1111 if (!C.getLangOptions().CPlusPlus)
1112 return false;
1113
1114 // FIXME: We could perform more analysis here to determine whether a
1115 // particular class type has any conversions to Objective-C types. For now,
1116 // just accept all class types.
1117 return T->isDependentType() || T->isRecordType();
1118}
1119
1120bool ResultBuilder::IsObjCMessageReceiver(NamedDecl *ND) const {
1121 QualType T = getDeclUsageType(SemaRef.Context, ND);
1122 if (T.isNull())
1123 return false;
1124
1125 T = SemaRef.Context.getBaseElementType(T);
1126 return isObjCReceiverType(SemaRef.Context, T);
1127}
1128
Douglas Gregorfb629412010-08-23 21:17:50 +00001129bool ResultBuilder::IsObjCCollection(NamedDecl *ND) const {
1130 if ((SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryName(ND)) ||
1131 (!SemaRef.getLangOptions().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
1132 return false;
1133
1134 QualType T = getDeclUsageType(SemaRef.Context, ND);
1135 if (T.isNull())
1136 return false;
1137
1138 T = SemaRef.Context.getBaseElementType(T);
1139 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1140 T->isObjCIdType() ||
1141 (SemaRef.getLangOptions().CPlusPlus && T->isRecordType());
1142}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001143
Douglas Gregor52779fb2010-09-23 23:01:17 +00001144bool ResultBuilder::IsImpossibleToSatisfy(NamedDecl *ND) const {
1145 return false;
1146}
1147
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001148/// \rief Determines whether the given declaration is an Objective-C
1149/// instance variable.
1150bool ResultBuilder::IsObjCIvar(NamedDecl *ND) const {
1151 return isa<ObjCIvarDecl>(ND);
1152}
1153
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001154namespace {
1155 /// \brief Visible declaration consumer that adds a code-completion result
1156 /// for each visible declaration.
1157 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1158 ResultBuilder &Results;
1159 DeclContext *CurContext;
1160
1161 public:
1162 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1163 : Results(Results), CurContext(CurContext) { }
1164
Douglas Gregor0cc84042010-01-14 15:47:35 +00001165 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) {
1166 Results.AddResult(ND, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001167 }
1168 };
1169}
1170
Douglas Gregor86d9a522009-09-21 16:56:56 +00001171/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001172static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001173 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001174 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001175 Results.AddResult(Result("short", CCP_Type));
1176 Results.AddResult(Result("long", CCP_Type));
1177 Results.AddResult(Result("signed", CCP_Type));
1178 Results.AddResult(Result("unsigned", CCP_Type));
1179 Results.AddResult(Result("void", CCP_Type));
1180 Results.AddResult(Result("char", CCP_Type));
1181 Results.AddResult(Result("int", CCP_Type));
1182 Results.AddResult(Result("float", CCP_Type));
1183 Results.AddResult(Result("double", CCP_Type));
1184 Results.AddResult(Result("enum", CCP_Type));
1185 Results.AddResult(Result("struct", CCP_Type));
1186 Results.AddResult(Result("union", CCP_Type));
1187 Results.AddResult(Result("const", CCP_Type));
1188 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001189
Douglas Gregor86d9a522009-09-21 16:56:56 +00001190 if (LangOpts.C99) {
1191 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001192 Results.AddResult(Result("_Complex", CCP_Type));
1193 Results.AddResult(Result("_Imaginary", CCP_Type));
1194 Results.AddResult(Result("_Bool", CCP_Type));
1195 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001196 }
1197
Douglas Gregor218937c2011-02-01 19:23:04 +00001198 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001199 if (LangOpts.CPlusPlus) {
1200 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001201 Results.AddResult(Result("bool", CCP_Type +
1202 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001203 Results.AddResult(Result("class", CCP_Type));
1204 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001205
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001206 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001207 Builder.AddTypedTextChunk("typename");
1208 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1209 Builder.AddPlaceholderChunk("qualifier");
1210 Builder.AddTextChunk("::");
1211 Builder.AddPlaceholderChunk("name");
1212 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001213
Douglas Gregor86d9a522009-09-21 16:56:56 +00001214 if (LangOpts.CPlusPlus0x) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001215 Results.AddResult(Result("auto", CCP_Type));
1216 Results.AddResult(Result("char16_t", CCP_Type));
1217 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001218
Douglas Gregor218937c2011-02-01 19:23:04 +00001219 Builder.AddTypedTextChunk("decltype");
1220 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1221 Builder.AddPlaceholderChunk("expression");
1222 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1223 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001224 }
1225 }
1226
1227 // GNU extensions
1228 if (LangOpts.GNUMode) {
1229 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001230 // Results.AddResult(Result("_Decimal32"));
1231 // Results.AddResult(Result("_Decimal64"));
1232 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001233
Douglas Gregor218937c2011-02-01 19:23:04 +00001234 Builder.AddTypedTextChunk("typeof");
1235 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1236 Builder.AddPlaceholderChunk("expression");
1237 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001238
Douglas Gregor218937c2011-02-01 19:23:04 +00001239 Builder.AddTypedTextChunk("typeof");
1240 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1241 Builder.AddPlaceholderChunk("type");
1242 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1243 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001244 }
1245}
1246
John McCallf312b1e2010-08-26 23:41:50 +00001247static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001248 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001249 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001250 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001251 // Note: we don't suggest either "auto" or "register", because both
1252 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1253 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001254 Results.AddResult(Result("extern"));
1255 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001256}
1257
John McCallf312b1e2010-08-26 23:41:50 +00001258static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001259 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001260 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001261 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001262 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001263 case Sema::PCC_Class:
1264 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001265 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001266 Results.AddResult(Result("explicit"));
1267 Results.AddResult(Result("friend"));
1268 Results.AddResult(Result("mutable"));
1269 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001270 }
1271 // Fall through
1272
John McCallf312b1e2010-08-26 23:41:50 +00001273 case Sema::PCC_ObjCInterface:
1274 case Sema::PCC_ObjCImplementation:
1275 case Sema::PCC_Namespace:
1276 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001277 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001278 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001279 break;
1280
John McCallf312b1e2010-08-26 23:41:50 +00001281 case Sema::PCC_ObjCInstanceVariableList:
1282 case Sema::PCC_Expression:
1283 case Sema::PCC_Statement:
1284 case Sema::PCC_ForInit:
1285 case Sema::PCC_Condition:
1286 case Sema::PCC_RecoveryInFunction:
1287 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001288 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001289 break;
1290 }
1291}
1292
Douglas Gregorbca403c2010-01-13 23:51:12 +00001293static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1294static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1295static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001296 ResultBuilder &Results,
1297 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001298static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001299 ResultBuilder &Results,
1300 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001301static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001302 ResultBuilder &Results,
1303 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001304static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001305
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001306static void AddTypedefResult(ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001307 CodeCompletionBuilder Builder(Results.getAllocator());
1308 Builder.AddTypedTextChunk("typedef");
1309 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1310 Builder.AddPlaceholderChunk("type");
1311 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1312 Builder.AddPlaceholderChunk("name");
1313 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001314}
1315
John McCallf312b1e2010-08-26 23:41:50 +00001316static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001317 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001318 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001319 case Sema::PCC_Namespace:
1320 case Sema::PCC_Class:
1321 case Sema::PCC_ObjCInstanceVariableList:
1322 case Sema::PCC_Template:
1323 case Sema::PCC_MemberTemplate:
1324 case Sema::PCC_Statement:
1325 case Sema::PCC_RecoveryInFunction:
1326 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001327 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001328 return true;
1329
John McCallf312b1e2010-08-26 23:41:50 +00001330 case Sema::PCC_Expression:
1331 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001332 return LangOpts.CPlusPlus;
1333
1334 case Sema::PCC_ObjCInterface:
1335 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001336 return false;
1337
John McCallf312b1e2010-08-26 23:41:50 +00001338 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001339 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001340 }
1341
1342 return false;
1343}
1344
Douglas Gregor01dfea02010-01-10 23:08:15 +00001345/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001346static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001347 Scope *S,
1348 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001349 ResultBuilder &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001350 CodeCompletionBuilder Builder(Results.getAllocator());
1351
John McCall0a2c5e22010-08-25 06:19:51 +00001352 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001353 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001354 case Sema::PCC_Namespace:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001355 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001356 if (Results.includeCodePatterns()) {
1357 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001358 Builder.AddTypedTextChunk("namespace");
1359 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1360 Builder.AddPlaceholderChunk("identifier");
1361 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1362 Builder.AddPlaceholderChunk("declarations");
1363 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1364 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1365 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001366 }
1367
Douglas Gregor01dfea02010-01-10 23:08:15 +00001368 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001369 Builder.AddTypedTextChunk("namespace");
1370 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1371 Builder.AddPlaceholderChunk("name");
1372 Builder.AddChunk(CodeCompletionString::CK_Equal);
1373 Builder.AddPlaceholderChunk("namespace");
1374 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001375
1376 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001377 Builder.AddTypedTextChunk("using");
1378 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1379 Builder.AddTextChunk("namespace");
1380 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1381 Builder.AddPlaceholderChunk("identifier");
1382 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001383
1384 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001385 Builder.AddTypedTextChunk("asm");
1386 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1387 Builder.AddPlaceholderChunk("string-literal");
1388 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1389 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001390
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001391 if (Results.includeCodePatterns()) {
1392 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001393 Builder.AddTypedTextChunk("template");
1394 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1395 Builder.AddPlaceholderChunk("declaration");
1396 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001397 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001398 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001399
1400 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001401 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001402
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001403 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001404 // Fall through
1405
John McCallf312b1e2010-08-26 23:41:50 +00001406 case Sema::PCC_Class:
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001407 if (SemaRef.getLangOptions().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001408 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001409 Builder.AddTypedTextChunk("using");
1410 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1411 Builder.AddPlaceholderChunk("qualifier");
1412 Builder.AddTextChunk("::");
1413 Builder.AddPlaceholderChunk("name");
1414 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001415
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001416 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001417 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001418 Builder.AddTypedTextChunk("using");
1419 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1420 Builder.AddTextChunk("typename");
1421 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1422 Builder.AddPlaceholderChunk("qualifier");
1423 Builder.AddTextChunk("::");
1424 Builder.AddPlaceholderChunk("name");
1425 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001426 }
1427
John McCallf312b1e2010-08-26 23:41:50 +00001428 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001429 AddTypedefResult(Results);
1430
Douglas Gregor01dfea02010-01-10 23:08:15 +00001431 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001432 Builder.AddTypedTextChunk("public");
1433 Builder.AddChunk(CodeCompletionString::CK_Colon);
1434 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001435
1436 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001437 Builder.AddTypedTextChunk("protected");
1438 Builder.AddChunk(CodeCompletionString::CK_Colon);
1439 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001440
1441 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001442 Builder.AddTypedTextChunk("private");
1443 Builder.AddChunk(CodeCompletionString::CK_Colon);
1444 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001445 }
1446 }
1447 // Fall through
1448
John McCallf312b1e2010-08-26 23:41:50 +00001449 case Sema::PCC_Template:
1450 case Sema::PCC_MemberTemplate:
Douglas Gregord8e8a582010-05-25 21:41:55 +00001451 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001452 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001453 Builder.AddTypedTextChunk("template");
1454 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1455 Builder.AddPlaceholderChunk("parameters");
1456 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1457 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001458 }
1459
Douglas Gregorbca403c2010-01-13 23:51:12 +00001460 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1461 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001462 break;
1463
John McCallf312b1e2010-08-26 23:41:50 +00001464 case Sema::PCC_ObjCInterface:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001465 AddObjCInterfaceResults(SemaRef.getLangOptions(), Results, true);
1466 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1467 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001468 break;
1469
John McCallf312b1e2010-08-26 23:41:50 +00001470 case Sema::PCC_ObjCImplementation:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001471 AddObjCImplementationResults(SemaRef.getLangOptions(), Results, true);
1472 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
1473 AddFunctionSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001474 break;
1475
John McCallf312b1e2010-08-26 23:41:50 +00001476 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001477 AddObjCVisibilityResults(SemaRef.getLangOptions(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001478 break;
1479
John McCallf312b1e2010-08-26 23:41:50 +00001480 case Sema::PCC_RecoveryInFunction:
1481 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001482 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001483
Douglas Gregord8e8a582010-05-25 21:41:55 +00001484 if (SemaRef.getLangOptions().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001485 Builder.AddTypedTextChunk("try");
1486 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1487 Builder.AddPlaceholderChunk("statements");
1488 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1489 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1490 Builder.AddTextChunk("catch");
1491 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1492 Builder.AddPlaceholderChunk("declaration");
1493 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1494 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1495 Builder.AddPlaceholderChunk("statements");
1496 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1497 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1498 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001499 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001500 if (SemaRef.getLangOptions().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001501 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001502
Douglas Gregord8e8a582010-05-25 21:41:55 +00001503 if (Results.includeCodePatterns()) {
1504 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001505 Builder.AddTypedTextChunk("if");
1506 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001507 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001508 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001509 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001510 Builder.AddPlaceholderChunk("expression");
1511 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1512 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1513 Builder.AddPlaceholderChunk("statements");
1514 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1515 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1516 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001517
Douglas Gregord8e8a582010-05-25 21:41:55 +00001518 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001519 Builder.AddTypedTextChunk("switch");
1520 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001521 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001522 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001523 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001524 Builder.AddPlaceholderChunk("expression");
1525 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1526 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1527 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1528 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1529 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001530 }
1531
Douglas Gregor01dfea02010-01-10 23:08:15 +00001532 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001533 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001534 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001535 Builder.AddTypedTextChunk("case");
1536 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1537 Builder.AddPlaceholderChunk("expression");
1538 Builder.AddChunk(CodeCompletionString::CK_Colon);
1539 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001540
1541 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001542 Builder.AddTypedTextChunk("default");
1543 Builder.AddChunk(CodeCompletionString::CK_Colon);
1544 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001545 }
1546
Douglas Gregord8e8a582010-05-25 21:41:55 +00001547 if (Results.includeCodePatterns()) {
1548 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001549 Builder.AddTypedTextChunk("while");
1550 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001551 if (SemaRef.getLangOptions().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001552 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001553 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001554 Builder.AddPlaceholderChunk("expression");
1555 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1556 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1557 Builder.AddPlaceholderChunk("statements");
1558 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1559 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1560 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001561
1562 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001563 Builder.AddTypedTextChunk("do");
1564 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1565 Builder.AddPlaceholderChunk("statements");
1566 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1567 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1568 Builder.AddTextChunk("while");
1569 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1570 Builder.AddPlaceholderChunk("expression");
1571 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1572 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001573
Douglas Gregord8e8a582010-05-25 21:41:55 +00001574 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001575 Builder.AddTypedTextChunk("for");
1576 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregord8e8a582010-05-25 21:41:55 +00001577 if (SemaRef.getLangOptions().CPlusPlus || SemaRef.getLangOptions().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001578 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001579 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001580 Builder.AddPlaceholderChunk("init-expression");
1581 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1582 Builder.AddPlaceholderChunk("condition");
1583 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1584 Builder.AddPlaceholderChunk("inc-expression");
1585 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1586 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1587 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1588 Builder.AddPlaceholderChunk("statements");
1589 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1590 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1591 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001592 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001593
1594 if (S->getContinueParent()) {
1595 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001596 Builder.AddTypedTextChunk("continue");
1597 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001598 }
1599
1600 if (S->getBreakParent()) {
1601 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001602 Builder.AddTypedTextChunk("break");
1603 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001604 }
1605
1606 // "return expression ;" or "return ;", depending on whether we
1607 // know the function is void or not.
1608 bool isVoid = false;
1609 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1610 isVoid = Function->getResultType()->isVoidType();
1611 else if (ObjCMethodDecl *Method
1612 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1613 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001614 else if (SemaRef.getCurBlock() &&
1615 !SemaRef.getCurBlock()->ReturnType.isNull())
1616 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001617 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001618 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001619 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1620 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001621 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001622 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001623
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001624 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001625 Builder.AddTypedTextChunk("goto");
1626 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1627 Builder.AddPlaceholderChunk("label");
1628 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001629
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001630 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001631 Builder.AddTypedTextChunk("using");
1632 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1633 Builder.AddTextChunk("namespace");
1634 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1635 Builder.AddPlaceholderChunk("identifier");
1636 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001637 }
1638
1639 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001640 case Sema::PCC_ForInit:
1641 case Sema::PCC_Condition:
Douglas Gregorbca403c2010-01-13 23:51:12 +00001642 AddStorageSpecifiers(CCC, SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001643 // Fall through: conditions and statements can have expressions.
1644
Douglas Gregor02688102010-09-14 23:59:36 +00001645 case Sema::PCC_ParenthesizedExpression:
John McCallf312b1e2010-08-26 23:41:50 +00001646 case Sema::PCC_Expression: {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001647 if (SemaRef.getLangOptions().CPlusPlus) {
1648 // 'this', if we're in a non-static member function.
1649 if (CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(SemaRef.CurContext))
1650 if (!Method->isStatic())
Douglas Gregora4477812010-01-14 16:01:26 +00001651 Results.AddResult(Result("this"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001652
1653 // true, false
Douglas Gregora4477812010-01-14 16:01:26 +00001654 Results.AddResult(Result("true"));
1655 Results.AddResult(Result("false"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001656
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001657 // dynamic_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001658 Builder.AddTypedTextChunk("dynamic_cast");
1659 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1660 Builder.AddPlaceholderChunk("type");
1661 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1662 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1663 Builder.AddPlaceholderChunk("expression");
1664 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1665 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001666
1667 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001668 Builder.AddTypedTextChunk("static_cast");
1669 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1670 Builder.AddPlaceholderChunk("type");
1671 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1672 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1673 Builder.AddPlaceholderChunk("expression");
1674 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1675 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001676
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001677 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001678 Builder.AddTypedTextChunk("reinterpret_cast");
1679 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1680 Builder.AddPlaceholderChunk("type");
1681 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1682 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1683 Builder.AddPlaceholderChunk("expression");
1684 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1685 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001686
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001687 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001688 Builder.AddTypedTextChunk("const_cast");
1689 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1690 Builder.AddPlaceholderChunk("type");
1691 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1692 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1693 Builder.AddPlaceholderChunk("expression");
1694 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1695 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001696
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001697 // typeid ( expression-or-type )
Douglas Gregor218937c2011-02-01 19:23:04 +00001698 Builder.AddTypedTextChunk("typeid");
1699 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1700 Builder.AddPlaceholderChunk("expression-or-type");
1701 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1702 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001703
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001704 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001705 Builder.AddTypedTextChunk("new");
1706 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1707 Builder.AddPlaceholderChunk("type");
1708 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1709 Builder.AddPlaceholderChunk("expressions");
1710 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1711 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001712
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001713 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001714 Builder.AddTypedTextChunk("new");
1715 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1716 Builder.AddPlaceholderChunk("type");
1717 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1718 Builder.AddPlaceholderChunk("size");
1719 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1720 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1721 Builder.AddPlaceholderChunk("expressions");
1722 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1723 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001724
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001725 // delete expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001726 Builder.AddTypedTextChunk("delete");
1727 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1728 Builder.AddPlaceholderChunk("expression");
1729 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001730
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001731 // delete [] expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001732 Builder.AddTypedTextChunk("delete");
1733 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1734 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1735 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1736 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1737 Builder.AddPlaceholderChunk("expression");
1738 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001739
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001740 // throw expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001741 Builder.AddTypedTextChunk("throw");
1742 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1743 Builder.AddPlaceholderChunk("expression");
1744 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor12e13132010-05-26 22:00:08 +00001745
1746 // FIXME: Rethrow?
Douglas Gregor01dfea02010-01-10 23:08:15 +00001747 }
1748
1749 if (SemaRef.getLangOptions().ObjC1) {
1750 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001751 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1752 // The interface can be NULL.
1753 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
1754 if (ID->getSuperClass())
1755 Results.AddResult(Result("super"));
1756 }
1757
Douglas Gregorbca403c2010-01-13 23:51:12 +00001758 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001759 }
1760
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001761 // sizeof expression
Douglas Gregor218937c2011-02-01 19:23:04 +00001762 Builder.AddTypedTextChunk("sizeof");
1763 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1764 Builder.AddPlaceholderChunk("expression-or-type");
1765 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1766 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001767 break;
1768 }
Douglas Gregord32b0222010-08-24 01:06:58 +00001769
John McCallf312b1e2010-08-26 23:41:50 +00001770 case Sema::PCC_Type:
Douglas Gregord32b0222010-08-24 01:06:58 +00001771 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001772 }
1773
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001774 if (WantTypesInContext(CCC, SemaRef.getLangOptions()))
1775 AddTypeSpecifierResults(SemaRef.getLangOptions(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001776
John McCallf312b1e2010-08-26 23:41:50 +00001777 if (SemaRef.getLangOptions().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00001778 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001779}
1780
Douglas Gregora63f6de2011-02-01 21:15:40 +00001781/// \brief Retrieve the string representation of the given type as a string
1782/// that has the appropriate lifetime for code completion.
1783///
1784/// This routine provides a fast path where we provide constant strings for
1785/// common type names.
1786const char *GetCompletionTypeString(QualType T,
1787 ASTContext &Context,
Douglas Gregordae68752011-02-01 22:57:45 +00001788 CodeCompletionAllocator &Allocator) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00001789 PrintingPolicy Policy(Context.PrintingPolicy);
1790 Policy.AnonymousTagLocations = false;
1791
1792 if (!T.getLocalQualifiers()) {
1793 // Built-in type names are constant strings.
1794 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
1795 return BT->getName(Context.getLangOptions());
1796
1797 // Anonymous tag types are constant strings.
1798 if (const TagType *TagT = dyn_cast<TagType>(T))
1799 if (TagDecl *Tag = TagT->getDecl())
1800 if (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()) {
1801 switch (Tag->getTagKind()) {
1802 case TTK_Struct: return "struct <anonymous>";
1803 case TTK_Class: return "class <anonymous>";
1804 case TTK_Union: return "union <anonymous>";
1805 case TTK_Enum: return "enum <anonymous>";
1806 }
1807 }
1808 }
1809
1810 // Slow path: format the type as a string.
1811 std::string Result;
1812 T.getAsStringInternal(Result, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00001813 return Allocator.CopyString(Result);
Douglas Gregora63f6de2011-02-01 21:15:40 +00001814}
1815
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001816/// \brief If the given declaration has an associated type, add it as a result
1817/// type chunk.
1818static void AddResultTypeChunk(ASTContext &Context,
1819 NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00001820 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001821 if (!ND)
1822 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00001823
1824 // Skip constructors and conversion functions, which have their return types
1825 // built into their names.
1826 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
1827 return;
1828
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001829 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00001830 QualType T;
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001831 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
1832 T = Function->getResultType();
1833 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
1834 T = Method->getResultType();
1835 else if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND))
1836 T = FunTmpl->getTemplatedDecl()->getResultType();
1837 else if (EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
1838 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
1839 else if (isa<UnresolvedUsingValueDecl>(ND)) {
1840 /* Do nothing: ignore unresolved using declarations*/
1841 } else if (ValueDecl *Value = dyn_cast<ValueDecl>(ND))
1842 T = Value->getType();
1843 else if (ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
1844 T = Property->getType();
1845
1846 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
1847 return;
1848
Douglas Gregora63f6de2011-02-01 21:15:40 +00001849 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context,
1850 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00001851}
1852
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001853static void MaybeAddSentinel(ASTContext &Context, NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00001854 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001855 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
1856 if (Sentinel->getSentinel() == 0) {
1857 if (Context.getLangOptions().ObjC1 &&
1858 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001859 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001860 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00001861 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001862 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001863 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00001864 }
1865}
1866
Douglas Gregor83482d12010-08-24 16:15:59 +00001867static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregoraba48082010-08-29 19:47:46 +00001868 ParmVarDecl *Param,
1869 bool SuppressName = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00001870 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
1871 if (Param->getType()->isDependentType() ||
1872 !Param->getType()->isBlockPointerType()) {
1873 // The argument for a dependent or non-block parameter is a placeholder
1874 // containing that parameter's type.
1875 std::string Result;
1876
Douglas Gregoraba48082010-08-29 19:47:46 +00001877 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00001878 Result = Param->getIdentifier()->getName();
1879
1880 Param->getType().getAsStringInternal(Result,
1881 Context.PrintingPolicy);
1882
1883 if (ObjCMethodParam) {
1884 Result = "(" + Result;
1885 Result += ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00001886 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00001887 Result += Param->getIdentifier()->getName();
1888 }
1889 return Result;
1890 }
1891
1892 // The argument for a block pointer parameter is a block literal with
1893 // the appropriate type.
1894 FunctionProtoTypeLoc *Block = 0;
1895 TypeLoc TL;
1896 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
1897 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
1898 while (true) {
1899 // Look through typedefs.
1900 if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&TL)) {
1901 if (TypeSourceInfo *InnerTSInfo
1902 = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) {
1903 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
1904 continue;
1905 }
1906 }
1907
1908 // Look through qualified types
1909 if (QualifiedTypeLoc *QualifiedTL = dyn_cast<QualifiedTypeLoc>(&TL)) {
1910 TL = QualifiedTL->getUnqualifiedLoc();
1911 continue;
1912 }
1913
1914 // Try to get the function prototype behind the block pointer type,
1915 // then we're done.
1916 if (BlockPointerTypeLoc *BlockPtr
1917 = dyn_cast<BlockPointerTypeLoc>(&TL)) {
Abramo Bagnara723df242010-12-14 22:11:44 +00001918 TL = BlockPtr->getPointeeLoc().IgnoreParens();
Douglas Gregor83482d12010-08-24 16:15:59 +00001919 Block = dyn_cast<FunctionProtoTypeLoc>(&TL);
1920 }
1921 break;
1922 }
1923 }
1924
1925 if (!Block) {
1926 // We were unable to find a FunctionProtoTypeLoc with parameter names
1927 // for the block; just use the parameter type as a placeholder.
1928 std::string Result;
1929 Param->getType().getUnqualifiedType().
1930 getAsStringInternal(Result, Context.PrintingPolicy);
1931
1932 if (ObjCMethodParam) {
1933 Result = "(" + Result;
1934 Result += ")";
1935 if (Param->getIdentifier())
1936 Result += Param->getIdentifier()->getName();
1937 }
1938
1939 return Result;
1940 }
1941
1942 // We have the function prototype behind the block pointer type, as it was
1943 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00001944 std::string Result;
1945 QualType ResultType = Block->getTypePtr()->getResultType();
1946 if (!ResultType->isVoidType())
1947 ResultType.getAsStringInternal(Result, Context.PrintingPolicy);
1948
1949 Result = '^' + Result;
1950 if (Block->getNumArgs() == 0) {
1951 if (Block->getTypePtr()->isVariadic())
1952 Result += "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00001953 else
1954 Result += "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00001955 } else {
1956 Result += "(";
1957 for (unsigned I = 0, N = Block->getNumArgs(); I != N; ++I) {
1958 if (I)
1959 Result += ", ";
1960 Result += FormatFunctionParameter(Context, Block->getArg(I));
1961
1962 if (I == N - 1 && Block->getTypePtr()->isVariadic())
1963 Result += ", ...";
1964 }
1965 Result += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00001966 }
Douglas Gregor38276252010-09-08 22:47:51 +00001967
Douglas Gregorc2760bc2010-10-02 23:49:58 +00001968 if (Param->getIdentifier())
1969 Result += Param->getIdentifier()->getName();
1970
Douglas Gregor83482d12010-08-24 16:15:59 +00001971 return Result;
1972}
1973
Douglas Gregor86d9a522009-09-21 16:56:56 +00001974/// \brief Add function parameter chunks to the given code completion string.
1975static void AddFunctionParameterChunks(ASTContext &Context,
1976 FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00001977 CodeCompletionBuilder &Result,
1978 unsigned Start = 0,
1979 bool InOptional = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00001980 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00001981 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00001982
Douglas Gregor218937c2011-02-01 19:23:04 +00001983 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001984 ParmVarDecl *Param = Function->getParamDecl(P);
1985
Douglas Gregor218937c2011-02-01 19:23:04 +00001986 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001987 // When we see an optional default argument, put that argument and
1988 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00001989 CodeCompletionBuilder Opt(Result.getAllocator());
1990 if (!FirstParameter)
1991 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
1992 AddFunctionParameterChunks(Context, Function, Opt, P, true);
1993 Result.AddOptionalChunk(Opt.TakeString());
1994 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001995 }
1996
Douglas Gregor218937c2011-02-01 19:23:04 +00001997 if (FirstParameter)
1998 FirstParameter = false;
1999 else
2000 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2001
2002 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002003
2004 // Format the placeholder string.
Douglas Gregor83482d12010-08-24 16:15:59 +00002005 std::string PlaceholderStr = FormatFunctionParameter(Context, Param);
2006
Douglas Gregore17794f2010-08-31 05:13:43 +00002007 if (Function->isVariadic() && P == N - 1)
2008 PlaceholderStr += ", ...";
2009
Douglas Gregor86d9a522009-09-21 16:56:56 +00002010 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002011 Result.AddPlaceholderChunk(
2012 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002013 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002014
2015 if (const FunctionProtoType *Proto
2016 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002017 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002018 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002019 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002020
Douglas Gregor218937c2011-02-01 19:23:04 +00002021 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002022 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002023}
2024
2025/// \brief Add template parameter chunks to the given code completion string.
2026static void AddTemplateParameterChunks(ASTContext &Context,
2027 TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002028 CodeCompletionBuilder &Result,
2029 unsigned MaxParameters = 0,
2030 unsigned Start = 0,
2031 bool InDefaultArg = false) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002032 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002033 bool FirstParameter = true;
2034
2035 TemplateParameterList *Params = Template->getTemplateParameters();
2036 TemplateParameterList::iterator PEnd = Params->end();
2037 if (MaxParameters)
2038 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002039 for (TemplateParameterList::iterator P = Params->begin() + Start;
2040 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002041 bool HasDefaultArg = false;
2042 std::string PlaceholderStr;
2043 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2044 if (TTP->wasDeclaredWithTypename())
2045 PlaceholderStr = "typename";
2046 else
2047 PlaceholderStr = "class";
2048
2049 if (TTP->getIdentifier()) {
2050 PlaceholderStr += ' ';
2051 PlaceholderStr += TTP->getIdentifier()->getName();
2052 }
2053
2054 HasDefaultArg = TTP->hasDefaultArgument();
2055 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002056 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002057 if (NTTP->getIdentifier())
2058 PlaceholderStr = NTTP->getIdentifier()->getName();
2059 NTTP->getType().getAsStringInternal(PlaceholderStr,
2060 Context.PrintingPolicy);
2061 HasDefaultArg = NTTP->hasDefaultArgument();
2062 } else {
2063 assert(isa<TemplateTemplateParmDecl>(*P));
2064 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2065
2066 // Since putting the template argument list into the placeholder would
2067 // be very, very long, we just use an abbreviation.
2068 PlaceholderStr = "template<...> class";
2069 if (TTP->getIdentifier()) {
2070 PlaceholderStr += ' ';
2071 PlaceholderStr += TTP->getIdentifier()->getName();
2072 }
2073
2074 HasDefaultArg = TTP->hasDefaultArgument();
2075 }
2076
Douglas Gregor218937c2011-02-01 19:23:04 +00002077 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002078 // When we see an optional default argument, put that argument and
2079 // the remaining default arguments into a new, optional string.
Douglas Gregor218937c2011-02-01 19:23:04 +00002080 CodeCompletionBuilder Opt(Result.getAllocator());
2081 if (!FirstParameter)
2082 Opt.AddChunk(Chunk(CodeCompletionString::CK_Comma));
2083 AddTemplateParameterChunks(Context, Template, Opt, MaxParameters,
2084 P - Params->begin(), true);
2085 Result.AddOptionalChunk(Opt.TakeString());
2086 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002087 }
2088
Douglas Gregor218937c2011-02-01 19:23:04 +00002089 InDefaultArg = false;
2090
Douglas Gregor86d9a522009-09-21 16:56:56 +00002091 if (FirstParameter)
2092 FirstParameter = false;
2093 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002094 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002095
2096 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002097 Result.AddPlaceholderChunk(
2098 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002099 }
2100}
2101
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002102/// \brief Add a qualifier to the given code-completion string, if the
2103/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002104static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002105AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002106 NestedNameSpecifier *Qualifier,
2107 bool QualifierIsInformative,
2108 ASTContext &Context) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002109 if (!Qualifier)
2110 return;
2111
2112 std::string PrintedNNS;
2113 {
2114 llvm::raw_string_ostream OS(PrintedNNS);
2115 Qualifier->print(OS, Context.PrintingPolicy);
2116 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002117 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002118 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002119 else
Douglas Gregordae68752011-02-01 22:57:45 +00002120 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002121}
2122
Douglas Gregor218937c2011-02-01 19:23:04 +00002123static void
2124AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
2125 FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002126 const FunctionProtoType *Proto
2127 = Function->getType()->getAs<FunctionProtoType>();
2128 if (!Proto || !Proto->getTypeQuals())
2129 return;
2130
Douglas Gregora63f6de2011-02-01 21:15:40 +00002131 // FIXME: Add ref-qualifier!
2132
2133 // Handle single qualifiers without copying
2134 if (Proto->getTypeQuals() == Qualifiers::Const) {
2135 Result.AddInformativeChunk(" const");
2136 return;
2137 }
2138
2139 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2140 Result.AddInformativeChunk(" volatile");
2141 return;
2142 }
2143
2144 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2145 Result.AddInformativeChunk(" restrict");
2146 return;
2147 }
2148
2149 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002150 std::string QualsStr;
2151 if (Proto->getTypeQuals() & Qualifiers::Const)
2152 QualsStr += " const";
2153 if (Proto->getTypeQuals() & Qualifiers::Volatile)
2154 QualsStr += " volatile";
2155 if (Proto->getTypeQuals() & Qualifiers::Restrict)
2156 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002157 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002158}
2159
Douglas Gregor6f942b22010-09-21 16:06:22 +00002160/// \brief Add the name of the given declaration
2161static void AddTypedNameChunk(ASTContext &Context, NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00002162 CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002163 typedef CodeCompletionString::Chunk Chunk;
2164
2165 DeclarationName Name = ND->getDeclName();
2166 if (!Name)
2167 return;
2168
2169 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002170 case DeclarationName::CXXOperatorName: {
2171 const char *OperatorName = 0;
2172 switch (Name.getCXXOverloadedOperator()) {
2173 case OO_None:
2174 case OO_Conditional:
2175 case NUM_OVERLOADED_OPERATORS:
2176 OperatorName = "operator";
2177 break;
2178
2179#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2180 case OO_##Name: OperatorName = "operator" Spelling; break;
2181#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2182#include "clang/Basic/OperatorKinds.def"
2183
2184 case OO_New: OperatorName = "operator new"; break;
2185 case OO_Delete: OperatorName = "operator delete"; break;
2186 case OO_Array_New: OperatorName = "operator new[]"; break;
2187 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2188 case OO_Call: OperatorName = "operator()"; break;
2189 case OO_Subscript: OperatorName = "operator[]"; break;
2190 }
2191 Result.AddTypedTextChunk(OperatorName);
2192 break;
2193 }
2194
Douglas Gregor6f942b22010-09-21 16:06:22 +00002195 case DeclarationName::Identifier:
2196 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002197 case DeclarationName::CXXDestructorName:
2198 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002199 Result.AddTypedTextChunk(
2200 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002201 break;
2202
2203 case DeclarationName::CXXUsingDirective:
2204 case DeclarationName::ObjCZeroArgSelector:
2205 case DeclarationName::ObjCOneArgSelector:
2206 case DeclarationName::ObjCMultiArgSelector:
2207 break;
2208
2209 case DeclarationName::CXXConstructorName: {
2210 CXXRecordDecl *Record = 0;
2211 QualType Ty = Name.getCXXNameType();
2212 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2213 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2214 else if (const InjectedClassNameType *InjectedTy
2215 = Ty->getAs<InjectedClassNameType>())
2216 Record = InjectedTy->getDecl();
2217 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002218 Result.AddTypedTextChunk(
2219 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002220 break;
2221 }
2222
Douglas Gregordae68752011-02-01 22:57:45 +00002223 Result.AddTypedTextChunk(
2224 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002225 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002226 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002227 AddTemplateParameterChunks(Context, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002228 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002229 }
2230 break;
2231 }
2232 }
2233}
2234
Douglas Gregor86d9a522009-09-21 16:56:56 +00002235/// \brief If possible, create a new code completion string for the given
2236/// result.
2237///
2238/// \returns Either a new, heap-allocated code completion string describing
2239/// how to use this result, or NULL to indicate that the string or name of the
2240/// result is all that is needed.
2241CodeCompletionString *
John McCall0a2c5e22010-08-25 06:19:51 +00002242CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002243 CodeCompletionAllocator &Allocator) {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002244 typedef CodeCompletionString::Chunk Chunk;
Douglas Gregor218937c2011-02-01 19:23:04 +00002245 CodeCompletionBuilder Result(Allocator, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002246
Douglas Gregor218937c2011-02-01 19:23:04 +00002247 if (Kind == RK_Pattern) {
2248 Pattern->Priority = Priority;
2249 Pattern->Availability = Availability;
2250 return Pattern;
2251 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002252
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002253 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002254 Result.AddTypedTextChunk(Keyword);
2255 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002256 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002257
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002258 if (Kind == RK_Macro) {
2259 MacroInfo *MI = S.PP.getMacroInfo(Macro);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002260 assert(MI && "Not a macro?");
2261
Douglas Gregordae68752011-02-01 22:57:45 +00002262 Result.AddTypedTextChunk(
2263 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002264
2265 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002266 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002267
2268 // Format a function-like macro with placeholders for the arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00002269 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002270 for (MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
2271 A != AEnd; ++A) {
2272 if (A != MI->arg_begin())
Douglas Gregor218937c2011-02-01 19:23:04 +00002273 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002274
2275 if (!MI->isVariadic() || A != AEnd - 1) {
2276 // Non-variadic argument.
Douglas Gregordae68752011-02-01 22:57:45 +00002277 Result.AddPlaceholderChunk(
2278 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002279 continue;
2280 }
2281
2282 // Variadic argument; cope with the different between GNU and C99
2283 // variadic macros, providing a single placeholder for the rest of the
2284 // arguments.
2285 if ((*A)->isStr("__VA_ARGS__"))
Douglas Gregor218937c2011-02-01 19:23:04 +00002286 Result.AddPlaceholderChunk("...");
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002287 else {
2288 std::string Arg = (*A)->getName();
2289 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002290 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002291 }
2292 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002293 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2294 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002295 }
2296
Douglas Gregord8e8a582010-05-25 21:41:55 +00002297 assert(Kind == RK_Declaration && "Missed a result kind?");
Douglas Gregor86d9a522009-09-21 16:56:56 +00002298 NamedDecl *ND = Declaration;
2299
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002300 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002301 Result.AddTypedTextChunk(
2302 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002303 Result.AddTextChunk("::");
2304 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002305 }
2306
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002307 AddResultTypeChunk(S.Context, ND, Result);
2308
Douglas Gregor86d9a522009-09-21 16:56:56 +00002309 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002310 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2311 S.Context);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002312 AddTypedNameChunk(S.Context, ND, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002313 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002314 AddFunctionParameterChunks(S.Context, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002315 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002316 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002317 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002318 }
2319
2320 if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002321 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2322 S.Context);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002323 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Douglas Gregor6f942b22010-09-21 16:06:22 +00002324 AddTypedNameChunk(S.Context, Function, Result);
2325
Douglas Gregor86d9a522009-09-21 16:56:56 +00002326 // Figure out which template parameters are deduced (or have default
2327 // arguments).
2328 llvm::SmallVector<bool, 16> Deduced;
2329 S.MarkDeducedTemplateParameters(FunTmpl, Deduced);
2330 unsigned LastDeducibleArgument;
2331 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2332 --LastDeducibleArgument) {
2333 if (!Deduced[LastDeducibleArgument - 1]) {
2334 // C++0x: Figure out if the template argument has a default. If so,
2335 // the user doesn't need to type this argument.
2336 // FIXME: We need to abstract template parameters better!
2337 bool HasDefaultArg = false;
2338 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002339 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002340 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2341 HasDefaultArg = TTP->hasDefaultArgument();
2342 else if (NonTypeTemplateParmDecl *NTTP
2343 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2344 HasDefaultArg = NTTP->hasDefaultArgument();
2345 else {
2346 assert(isa<TemplateTemplateParmDecl>(Param));
2347 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002348 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002349 }
2350
2351 if (!HasDefaultArg)
2352 break;
2353 }
2354 }
2355
2356 if (LastDeducibleArgument) {
2357 // Some of the function template arguments cannot be deduced from a
2358 // function call, so we introduce an explicit template argument list
2359 // containing all of the arguments up to the first deducible argument.
Douglas Gregor218937c2011-02-01 19:23:04 +00002360 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002361 AddTemplateParameterChunks(S.Context, FunTmpl, Result,
2362 LastDeducibleArgument);
Douglas Gregor218937c2011-02-01 19:23:04 +00002363 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002364 }
2365
2366 // Add the function parameters
Douglas Gregor218937c2011-02-01 19:23:04 +00002367 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002368 AddFunctionParameterChunks(S.Context, Function, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002369 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregora61a8792009-12-11 18:44:16 +00002370 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002371 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002372 }
2373
2374 if (TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002375 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2376 S.Context);
Douglas Gregordae68752011-02-01 22:57:45 +00002377 Result.AddTypedTextChunk(
2378 Result.getAllocator().CopyString(Template->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002379 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftAngle));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002380 AddTemplateParameterChunks(S.Context, Template, Result);
Douglas Gregor218937c2011-02-01 19:23:04 +00002381 Result.AddChunk(Chunk(CodeCompletionString::CK_RightAngle));
2382 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002383 }
2384
Douglas Gregor9630eb62009-11-17 16:44:22 +00002385 if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002386 Selector Sel = Method->getSelector();
2387 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002388 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002389 Sel.getIdentifierInfoForSlot(0)->getName()));
2390 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002391 }
2392
Douglas Gregord3c68542009-11-19 01:08:35 +00002393 std::string SelName = Sel.getIdentifierInfoForSlot(0)->getName().str();
2394 SelName += ':';
2395 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002396 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002397 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002398 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002399
2400 // If there is only one parameter, and we're past it, add an empty
2401 // typed-text chunk since there is nothing to type.
2402 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002403 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002404 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002405 unsigned Idx = 0;
2406 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
2407 PEnd = Method->param_end();
2408 P != PEnd; (void)++P, ++Idx) {
2409 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002410 std::string Keyword;
2411 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002412 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002413 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
2414 Keyword += II->getName().str();
2415 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002416 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002417 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002418 else
Douglas Gregordae68752011-02-01 22:57:45 +00002419 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002420 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002421
2422 // If we're before the starting parameter, skip the placeholder.
2423 if (Idx < StartParameter)
2424 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002425
2426 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002427
2428 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Douglas Gregoraba48082010-08-29 19:47:46 +00002429 Arg = FormatFunctionParameter(S.Context, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002430 else {
2431 (*P)->getType().getAsStringInternal(Arg, S.Context.PrintingPolicy);
2432 Arg = "(" + Arg + ")";
2433 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002434 if (DeclaringEntity || AllParametersAreInformative)
2435 Arg += II->getName().str();
Douglas Gregor83482d12010-08-24 16:15:59 +00002436 }
2437
Douglas Gregore17794f2010-08-31 05:13:43 +00002438 if (Method->isVariadic() && (P + 1) == PEnd)
2439 Arg += ", ...";
2440
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002441 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002442 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002443 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002444 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002445 else
Douglas Gregordae68752011-02-01 22:57:45 +00002446 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002447 }
2448
Douglas Gregor2a17af02009-12-23 00:21:46 +00002449 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002450 if (Method->param_size() == 0) {
2451 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002452 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002453 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002454 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002455 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002456 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002457 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002458
2459 MaybeAddSentinel(S.Context, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002460 }
2461
Douglas Gregor218937c2011-02-01 19:23:04 +00002462 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002463 }
2464
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002465 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002466 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
2467 S.Context);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002468
Douglas Gregordae68752011-02-01 22:57:45 +00002469 Result.AddTypedTextChunk(
2470 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002471 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002472}
2473
Douglas Gregor86d802e2009-09-23 00:34:09 +00002474CodeCompletionString *
2475CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2476 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002477 Sema &S,
Douglas Gregordae68752011-02-01 22:57:45 +00002478 CodeCompletionAllocator &Allocator) const {
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002479 typedef CodeCompletionString::Chunk Chunk;
2480
Douglas Gregor218937c2011-02-01 19:23:04 +00002481 // FIXME: Set priority, availability appropriately.
2482 CodeCompletionBuilder Result(Allocator, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002483 FunctionDecl *FDecl = getFunction();
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002484 AddResultTypeChunk(S.Context, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002485 const FunctionProtoType *Proto
2486 = dyn_cast<FunctionProtoType>(getFunctionType());
2487 if (!FDecl && !Proto) {
2488 // Function without a prototype. Just give the return type and a
2489 // highlighted ellipsis.
2490 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002491 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
2492 S.Context,
2493 Result.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002494 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
2495 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
2496 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
2497 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002498 }
2499
2500 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002501 Result.AddTextChunk(
2502 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002503 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002504 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002505 Result.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002506 Proto->getResultType().getAsString(S.Context.PrintingPolicy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002507
Douglas Gregor218937c2011-02-01 19:23:04 +00002508 Result.AddChunk(Chunk(CodeCompletionString::CK_LeftParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002509 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2510 for (unsigned I = 0; I != NumParams; ++I) {
2511 if (I)
Douglas Gregor218937c2011-02-01 19:23:04 +00002512 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002513
2514 std::string ArgString;
2515 QualType ArgType;
2516
2517 if (FDecl) {
2518 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2519 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2520 } else {
2521 ArgType = Proto->getArgType(I);
2522 }
2523
2524 ArgType.getAsStringInternal(ArgString, S.Context.PrintingPolicy);
2525
2526 if (I == CurrentArg)
Douglas Gregor218937c2011-02-01 19:23:04 +00002527 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter,
Douglas Gregordae68752011-02-01 22:57:45 +00002528 Result.getAllocator().CopyString(ArgString)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002529 else
Douglas Gregordae68752011-02-01 22:57:45 +00002530 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002531 }
2532
2533 if (Proto && Proto->isVariadic()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002534 Result.AddChunk(Chunk(CodeCompletionString::CK_Comma));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002535 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002536 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002537 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002538 Result.AddChunk(Chunk(CodeCompletionString::CK_CurrentParameter, "..."));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002539 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002540 Result.AddChunk(Chunk(CodeCompletionString::CK_RightParen));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002541
Douglas Gregor218937c2011-02-01 19:23:04 +00002542 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002543}
2544
Douglas Gregor1827e102010-08-16 16:18:59 +00002545unsigned clang::getMacroUsagePriority(llvm::StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002546 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002547 bool PreferredTypeIsPointer) {
2548 unsigned Priority = CCP_Macro;
2549
Douglas Gregorb05496d2010-09-20 21:11:48 +00002550 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2551 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2552 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002553 Priority = CCP_Constant;
2554 if (PreferredTypeIsPointer)
2555 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002556 }
2557 // Treat "YES", "NO", "true", and "false" as constants.
2558 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2559 MacroName.equals("true") || MacroName.equals("false"))
2560 Priority = CCP_Constant;
2561 // Treat "bool" as a type.
2562 else if (MacroName.equals("bool"))
2563 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2564
Douglas Gregor1827e102010-08-16 16:18:59 +00002565
2566 return Priority;
2567}
2568
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002569CXCursorKind clang::getCursorKindForDecl(Decl *D) {
2570 if (!D)
2571 return CXCursor_UnexposedDecl;
2572
2573 switch (D->getKind()) {
2574 case Decl::Enum: return CXCursor_EnumDecl;
2575 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2576 case Decl::Field: return CXCursor_FieldDecl;
2577 case Decl::Function:
2578 return CXCursor_FunctionDecl;
2579 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2580 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
2581 case Decl::ObjCClass:
2582 // FIXME
2583 return CXCursor_UnexposedDecl;
2584 case Decl::ObjCForwardProtocol:
2585 // FIXME
2586 return CXCursor_UnexposedDecl;
2587 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
2588 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
2589 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2590 case Decl::ObjCMethod:
2591 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2592 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2593 case Decl::CXXMethod: return CXCursor_CXXMethod;
2594 case Decl::CXXConstructor: return CXCursor_Constructor;
2595 case Decl::CXXDestructor: return CXCursor_Destructor;
2596 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2597 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
2598 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
2599 case Decl::ParmVar: return CXCursor_ParmDecl;
2600 case Decl::Typedef: return CXCursor_TypedefDecl;
2601 case Decl::Var: return CXCursor_VarDecl;
2602 case Decl::Namespace: return CXCursor_Namespace;
2603 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2604 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2605 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2606 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2607 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2608 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
2609 case Decl::ClassTemplatePartialSpecialization:
2610 return CXCursor_ClassTemplatePartialSpecialization;
2611 case Decl::UsingDirective: return CXCursor_UsingDirective;
2612
2613 case Decl::Using:
2614 case Decl::UnresolvedUsingValue:
2615 case Decl::UnresolvedUsingTypename:
2616 return CXCursor_UsingDeclaration;
2617
2618 default:
2619 if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
2620 switch (TD->getTagKind()) {
2621 case TTK_Struct: return CXCursor_StructDecl;
2622 case TTK_Class: return CXCursor_ClassDecl;
2623 case TTK_Union: return CXCursor_UnionDecl;
2624 case TTK_Enum: return CXCursor_EnumDecl;
2625 }
2626 }
2627 }
2628
2629 return CXCursor_UnexposedDecl;
2630}
2631
Douglas Gregor590c7d52010-07-08 20:55:51 +00002632static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
2633 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002634 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002635
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002636 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002637
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002638 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2639 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002640 M != MEnd; ++M) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002641 Results.AddResult(Result(M->first,
2642 getMacroUsagePriority(M->first->getName(),
Douglas Gregorb05496d2010-09-20 21:11:48 +00002643 PP.getLangOptions(),
Douglas Gregor1827e102010-08-16 16:18:59 +00002644 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00002645 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002646
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002647 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002648
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002649}
2650
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002651static void AddPrettyFunctionResults(const LangOptions &LangOpts,
2652 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00002653 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002654
2655 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002656
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002657 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
2658 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
2659 if (LangOpts.C99 || LangOpts.CPlusPlus0x)
2660 Results.AddResult(Result("__func__", CCP_Constant));
2661 Results.ExitScope();
2662}
2663
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00002664static void HandleCodeCompleteResults(Sema *S,
2665 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002666 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00002667 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002668 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002669 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002670 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002671}
2672
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002673static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
2674 Sema::ParserCompletionContext PCC) {
2675 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00002676 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002677 return CodeCompletionContext::CCC_TopLevel;
2678
John McCallf312b1e2010-08-26 23:41:50 +00002679 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002680 return CodeCompletionContext::CCC_ClassStructUnion;
2681
John McCallf312b1e2010-08-26 23:41:50 +00002682 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002683 return CodeCompletionContext::CCC_ObjCInterface;
2684
John McCallf312b1e2010-08-26 23:41:50 +00002685 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002686 return CodeCompletionContext::CCC_ObjCImplementation;
2687
John McCallf312b1e2010-08-26 23:41:50 +00002688 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002689 return CodeCompletionContext::CCC_ObjCIvarList;
2690
John McCallf312b1e2010-08-26 23:41:50 +00002691 case Sema::PCC_Template:
2692 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002693 if (S.CurContext->isFileContext())
2694 return CodeCompletionContext::CCC_TopLevel;
2695 else if (S.CurContext->isRecord())
2696 return CodeCompletionContext::CCC_ClassStructUnion;
2697 else
2698 return CodeCompletionContext::CCC_Other;
2699
John McCallf312b1e2010-08-26 23:41:50 +00002700 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00002701 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00002702
John McCallf312b1e2010-08-26 23:41:50 +00002703 case Sema::PCC_ForInit:
Douglas Gregora5450a02010-10-18 22:01:46 +00002704 if (S.getLangOptions().CPlusPlus || S.getLangOptions().C99 ||
2705 S.getLangOptions().ObjC1)
2706 return CodeCompletionContext::CCC_ParenthesizedExpression;
2707 else
2708 return CodeCompletionContext::CCC_Expression;
2709
2710 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00002711 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002712 return CodeCompletionContext::CCC_Expression;
2713
John McCallf312b1e2010-08-26 23:41:50 +00002714 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002715 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00002716
John McCallf312b1e2010-08-26 23:41:50 +00002717 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00002718 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00002719
2720 case Sema::PCC_ParenthesizedExpression:
2721 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002722 }
2723
2724 return CodeCompletionContext::CCC_Other;
2725}
2726
Douglas Gregorf6961522010-08-27 21:18:54 +00002727/// \brief If we're in a C++ virtual member function, add completion results
2728/// that invoke the functions we override, since it's common to invoke the
2729/// overridden function as well as adding new functionality.
2730///
2731/// \param S The semantic analysis object for which we are generating results.
2732///
2733/// \param InContext This context in which the nested-name-specifier preceding
2734/// the code-completion point
2735static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
2736 ResultBuilder &Results) {
2737 // Look through blocks.
2738 DeclContext *CurContext = S.CurContext;
2739 while (isa<BlockDecl>(CurContext))
2740 CurContext = CurContext->getParent();
2741
2742
2743 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
2744 if (!Method || !Method->isVirtual())
2745 return;
2746
2747 // We need to have names for all of the parameters, if we're going to
2748 // generate a forwarding call.
2749 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2750 PEnd = Method->param_end();
2751 P != PEnd;
2752 ++P) {
2753 if (!(*P)->getDeclName())
2754 return;
2755 }
2756
2757 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
2758 MEnd = Method->end_overridden_methods();
2759 M != MEnd; ++M) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002760 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorf6961522010-08-27 21:18:54 +00002761 CXXMethodDecl *Overridden = const_cast<CXXMethodDecl *>(*M);
2762 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
2763 continue;
2764
2765 // If we need a nested-name-specifier, add one now.
2766 if (!InContext) {
2767 NestedNameSpecifier *NNS
2768 = getRequiredQualification(S.Context, CurContext,
2769 Overridden->getDeclContext());
2770 if (NNS) {
2771 std::string Str;
2772 llvm::raw_string_ostream OS(Str);
2773 NNS->print(OS, S.Context.PrintingPolicy);
Douglas Gregordae68752011-02-01 22:57:45 +00002774 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002775 }
2776 } else if (!InContext->Equals(Overridden->getDeclContext()))
2777 continue;
2778
Douglas Gregordae68752011-02-01 22:57:45 +00002779 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002780 Overridden->getNameAsString()));
2781 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00002782 bool FirstParam = true;
2783 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
2784 PEnd = Method->param_end();
2785 P != PEnd; ++P) {
2786 if (FirstParam)
2787 FirstParam = false;
2788 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002789 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00002790
Douglas Gregordae68752011-02-01 22:57:45 +00002791 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00002792 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00002793 }
Douglas Gregor218937c2011-02-01 19:23:04 +00002794 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2795 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00002796 CCP_SuperCompletion,
2797 CXCursor_CXXMethod));
2798 Results.Ignore(Overridden);
2799 }
2800}
2801
Douglas Gregor01dfea02010-01-10 23:08:15 +00002802void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002803 ParserCompletionContext CompletionContext) {
John McCall0a2c5e22010-08-25 06:19:51 +00002804 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002805 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00002806 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00002807 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00002808
Douglas Gregor01dfea02010-01-10 23:08:15 +00002809 // Determine how to filter results, e.g., so that the names of
2810 // values (functions, enumerators, function templates, etc.) are
2811 // only allowed where we can have an expression.
2812 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002813 case PCC_Namespace:
2814 case PCC_Class:
2815 case PCC_ObjCInterface:
2816 case PCC_ObjCImplementation:
2817 case PCC_ObjCInstanceVariableList:
2818 case PCC_Template:
2819 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00002820 case PCC_Type:
Douglas Gregor01dfea02010-01-10 23:08:15 +00002821 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
2822 break;
2823
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002824 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00002825 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00002826 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002827 case PCC_ForInit:
2828 case PCC_Condition:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00002829 if (WantTypesInContext(CompletionContext, getLangOptions()))
2830 Results.setFilter(&ResultBuilder::IsOrdinaryName);
2831 else
2832 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00002833
2834 if (getLangOptions().CPlusPlus)
2835 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00002836 break;
Douglas Gregordc845342010-05-25 05:58:43 +00002837
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002838 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00002839 // Unfiltered
2840 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00002841 }
2842
Douglas Gregor3cdee122010-08-26 16:36:48 +00002843 // If we are in a C++ non-static member function, check the qualifiers on
2844 // the member function to filter/prioritize the results list.
2845 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
2846 if (CurMethod->isInstance())
2847 Results.setObjectTypeQualifiers(
2848 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
2849
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00002850 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00002851 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
2852 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00002853
Douglas Gregorbca403c2010-01-13 23:51:12 +00002854 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00002855 Results.ExitScope();
2856
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002857 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00002858 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00002859 case PCC_Expression:
2860 case PCC_Statement:
2861 case PCC_RecoveryInFunction:
2862 if (S->getFnParent())
2863 AddPrettyFunctionResults(PP.getLangOptions(), Results);
2864 break;
2865
2866 case PCC_Namespace:
2867 case PCC_Class:
2868 case PCC_ObjCInterface:
2869 case PCC_ObjCImplementation:
2870 case PCC_ObjCInstanceVariableList:
2871 case PCC_Template:
2872 case PCC_MemberTemplate:
2873 case PCC_ForInit:
2874 case PCC_Condition:
2875 case PCC_Type:
2876 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002877 }
2878
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002879 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00002880 AddMacroResults(PP, Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00002881
Douglas Gregorcee9ff12010-09-20 22:39:41 +00002882 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002883 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00002884}
2885
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002886static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
2887 ParsedType Receiver,
2888 IdentifierInfo **SelIdents,
2889 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00002890 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002891 bool IsSuper,
2892 ResultBuilder &Results);
2893
2894void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
2895 bool AllowNonIdentifiers,
2896 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00002897 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002898 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00002899 AllowNestedNameSpecifiers
2900 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
2901 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002902 Results.EnterNewScope();
2903
2904 // Type qualifiers can come after names.
2905 Results.AddResult(Result("const"));
2906 Results.AddResult(Result("volatile"));
2907 if (getLangOptions().C99)
2908 Results.AddResult(Result("restrict"));
2909
2910 if (getLangOptions().CPlusPlus) {
2911 if (AllowNonIdentifiers) {
2912 Results.AddResult(Result("operator"));
2913 }
2914
2915 // Add nested-name-specifiers.
2916 if (AllowNestedNameSpecifiers) {
2917 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00002918 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002919 CodeCompletionDeclConsumer Consumer(Results, CurContext);
2920 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
2921 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00002922 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002923 }
2924 }
2925 Results.ExitScope();
2926
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002927 // If we're in a context where we might have an expression (rather than a
2928 // declaration), and what we've seen so far is an Objective-C type that could
2929 // be a receiver of a class message, this may be a class message send with
2930 // the initial opening bracket '[' missing. Add appropriate completions.
2931 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
2932 DS.getTypeSpecType() == DeclSpec::TST_typename &&
2933 DS.getStorageClassSpecAsWritten() == DeclSpec::SCS_unspecified &&
2934 !DS.isThreadSpecified() && !DS.isExternInLinkageSpec() &&
2935 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
2936 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
2937 DS.getTypeQualifiers() == 0 &&
2938 S &&
2939 (S->getFlags() & Scope::DeclScope) != 0 &&
2940 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
2941 Scope::FunctionPrototypeScope |
2942 Scope::AtCatchScope)) == 0) {
2943 ParsedType T = DS.getRepAsType();
2944 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Douglas Gregor70c5ac72010-09-20 23:34:21 +00002945 AddClassMessageCompletions(*this, S, T, 0, 0, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00002946 }
2947
Douglas Gregor4497dd42010-08-24 04:59:56 +00002948 // Note that we intentionally suppress macro results here, since we do not
2949 // encourage using macros to produce the names of entities.
2950
Douglas Gregor52779fb2010-09-23 23:01:17 +00002951 HandleCodeCompleteResults(this, CodeCompleter,
2952 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00002953 Results.data(), Results.size());
2954}
2955
Douglas Gregorfb629412010-08-23 21:17:50 +00002956struct Sema::CodeCompleteExpressionData {
2957 CodeCompleteExpressionData(QualType PreferredType = QualType())
2958 : PreferredType(PreferredType), IntegralConstantExpression(false),
2959 ObjCCollection(false) { }
2960
2961 QualType PreferredType;
2962 bool IntegralConstantExpression;
2963 bool ObjCCollection;
2964 llvm::SmallVector<Decl *, 4> IgnoreDecls;
2965};
2966
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002967/// \brief Perform code-completion in an expression context when we know what
2968/// type we're looking for.
Douglas Gregorf9578432010-07-28 21:50:18 +00002969///
2970/// \param IntegralConstantExpression Only permit integral constant
2971/// expressions.
Douglas Gregorfb629412010-08-23 21:17:50 +00002972void Sema::CodeCompleteExpression(Scope *S,
2973 const CodeCompleteExpressionData &Data) {
John McCall0a2c5e22010-08-25 06:19:51 +00002974 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00002975 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
2976 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00002977 if (Data.ObjCCollection)
2978 Results.setFilter(&ResultBuilder::IsObjCCollection);
2979 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00002980 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002981 else if (WantTypesInContext(PCC_Expression, getLangOptions()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002982 Results.setFilter(&ResultBuilder::IsOrdinaryName);
2983 else
2984 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00002985
2986 if (!Data.PreferredType.isNull())
2987 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
2988
2989 // Ignore any declarations that we were told that we don't care about.
2990 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
2991 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002992
2993 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00002994 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
2995 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002996
2997 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00002998 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00002999 Results.ExitScope();
3000
Douglas Gregor590c7d52010-07-08 20:55:51 +00003001 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003002 if (!Data.PreferredType.isNull())
3003 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3004 || Data.PreferredType->isMemberPointerType()
3005 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003006
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003007 if (S->getFnParent() &&
3008 !Data.ObjCCollection &&
3009 !Data.IntegralConstantExpression)
3010 AddPrettyFunctionResults(PP.getLangOptions(), Results);
3011
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003012 if (CodeCompleter->includeMacros())
Douglas Gregor590c7d52010-07-08 20:55:51 +00003013 AddMacroResults(PP, Results, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003014 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003015 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3016 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003017 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003018}
3019
Douglas Gregorac5fd842010-09-18 01:28:11 +00003020void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3021 if (E.isInvalid())
3022 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
3023 else if (getLangOptions().ObjC1)
3024 CodeCompleteObjCInstanceMessage(S, E.take(), 0, 0, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003025}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003026
Douglas Gregor73449212010-12-09 23:01:55 +00003027/// \brief The set of properties that have already been added, referenced by
3028/// property name.
3029typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3030
Douglas Gregor95ac6552009-11-18 01:29:26 +00003031static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003032 bool AllowCategories,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003033 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003034 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003035 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003036 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003037
3038 // Add properties in this container.
3039 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3040 PEnd = Container->prop_end();
3041 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003042 ++P) {
3043 if (AddedProperties.insert(P->getIdentifier()))
3044 Results.MaybeAddResult(Result(*P, 0), CurContext);
3045 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003046
3047 // Add properties in referenced protocols.
3048 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3049 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3050 PEnd = Protocol->protocol_end();
3051 P != PEnd; ++P)
Douglas Gregor73449212010-12-09 23:01:55 +00003052 AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
3053 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003054 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003055 if (AllowCategories) {
3056 // Look through categories.
3057 for (ObjCCategoryDecl *Category = IFace->getCategoryList();
3058 Category; Category = Category->getNextClassCategory())
Douglas Gregor73449212010-12-09 23:01:55 +00003059 AddObjCProperties(Category, AllowCategories, CurContext,
3060 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003061 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003062
3063 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003064 for (ObjCInterfaceDecl::all_protocol_iterator
3065 I = IFace->all_referenced_protocol_begin(),
3066 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor73449212010-12-09 23:01:55 +00003067 AddObjCProperties(*I, AllowCategories, CurContext, AddedProperties,
3068 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003069
3070 // Look in the superclass.
3071 if (IFace->getSuperClass())
Douglas Gregor322328b2009-11-18 22:32:06 +00003072 AddObjCProperties(IFace->getSuperClass(), AllowCategories, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003073 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003074 } else if (const ObjCCategoryDecl *Category
3075 = dyn_cast<ObjCCategoryDecl>(Container)) {
3076 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003077 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3078 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003079 P != PEnd; ++P)
Douglas Gregor73449212010-12-09 23:01:55 +00003080 AddObjCProperties(*P, AllowCategories, CurContext, AddedProperties,
3081 Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003082 }
3083}
3084
Douglas Gregor81b747b2009-09-17 21:32:03 +00003085void Sema::CodeCompleteMemberReferenceExpr(Scope *S, ExprTy *BaseE,
3086 SourceLocation OpLoc,
3087 bool IsArrow) {
3088 if (!BaseE || !CodeCompleter)
3089 return;
3090
John McCall0a2c5e22010-08-25 06:19:51 +00003091 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003092
Douglas Gregor81b747b2009-09-17 21:32:03 +00003093 Expr *Base = static_cast<Expr *>(BaseE);
3094 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003095
3096 if (IsArrow) {
3097 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3098 BaseType = Ptr->getPointeeType();
3099 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003100 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003101 else
3102 return;
3103 }
3104
Douglas Gregor218937c2011-02-01 19:23:04 +00003105 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003106 CodeCompletionContext(CodeCompletionContext::CCC_MemberAccess,
3107 BaseType),
3108 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003109 Results.EnterNewScope();
3110 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003111 // Indicate that we are performing a member access, and the cv-qualifiers
3112 // for the base object type.
3113 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3114
Douglas Gregor95ac6552009-11-18 01:29:26 +00003115 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003116 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003117 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003118 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3119 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003120
Douglas Gregor95ac6552009-11-18 01:29:26 +00003121 if (getLangOptions().CPlusPlus) {
3122 if (!Results.empty()) {
3123 // The "template" keyword can follow "->" or "." in the grammar.
3124 // However, we only want to suggest the template keyword if something
3125 // is dependent.
3126 bool IsDependent = BaseType->isDependentType();
3127 if (!IsDependent) {
3128 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3129 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3130 IsDependent = Ctx->isDependentContext();
3131 break;
3132 }
3133 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003134
Douglas Gregor95ac6552009-11-18 01:29:26 +00003135 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003136 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003137 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003138 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003139 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3140 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003141 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003142
3143 // Add property results based on our interface.
3144 const ObjCObjectPointerType *ObjCPtr
3145 = BaseType->getAsObjCInterfacePointerType();
3146 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor73449212010-12-09 23:01:55 +00003147 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true, CurContext,
3148 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003149
3150 // Add properties from the protocols in a qualified interface.
3151 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3152 E = ObjCPtr->qual_end();
3153 I != E; ++I)
Douglas Gregor73449212010-12-09 23:01:55 +00003154 AddObjCProperties(*I, true, CurContext, AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003155 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003156 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003157 // Objective-C instance variable access.
3158 ObjCInterfaceDecl *Class = 0;
3159 if (const ObjCObjectPointerType *ObjCPtr
3160 = BaseType->getAs<ObjCObjectPointerType>())
3161 Class = ObjCPtr->getInterfaceDecl();
3162 else
John McCallc12c5bb2010-05-15 11:32:37 +00003163 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003164
3165 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003166 if (Class) {
3167 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3168 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003169 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3170 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003171 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003172 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003173
3174 // FIXME: How do we cope with isa?
3175
3176 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003177
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003178 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003179 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003180 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003181 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003182}
3183
Douglas Gregor374929f2009-09-18 15:37:17 +00003184void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3185 if (!CodeCompleter)
3186 return;
3187
John McCall0a2c5e22010-08-25 06:19:51 +00003188 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003189 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003190 enum CodeCompletionContext::Kind ContextKind
3191 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003192 switch ((DeclSpec::TST)TagSpec) {
3193 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003194 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003195 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003196 break;
3197
3198 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003199 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003200 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003201 break;
3202
3203 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003204 case DeclSpec::TST_class:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003205 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003206 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003207 break;
3208
3209 default:
3210 assert(false && "Unknown type specifier kind in CodeCompleteTag");
3211 return;
3212 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003213
Douglas Gregor218937c2011-02-01 19:23:04 +00003214 ResultBuilder Results(*this, CodeCompleter->getAllocator(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003215 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003216
3217 // First pass: look for tags.
3218 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003219 LookupVisibleDecls(S, LookupTagName, Consumer,
3220 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003221
Douglas Gregor8071e422010-08-15 06:18:01 +00003222 if (CodeCompleter->includeGlobals()) {
3223 // Second pass: look for nested name specifiers.
3224 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3225 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3226 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003227
Douglas Gregor52779fb2010-09-23 23:01:17 +00003228 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003229 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003230}
3231
Douglas Gregor1a480c42010-08-27 17:35:51 +00003232void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003233 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3234 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003235 Results.EnterNewScope();
3236 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3237 Results.AddResult("const");
3238 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3239 Results.AddResult("volatile");
3240 if (getLangOptions().C99 &&
3241 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3242 Results.AddResult("restrict");
3243 Results.ExitScope();
3244 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003245 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003246 Results.data(), Results.size());
3247}
3248
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003249void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003250 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003251 return;
3252
John McCall781472f2010-08-25 08:40:02 +00003253 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
Douglas Gregorf9578432010-07-28 21:50:18 +00003254 if (!Switch->getCond()->getType()->isEnumeralType()) {
Douglas Gregorfb629412010-08-23 21:17:50 +00003255 CodeCompleteExpressionData Data(Switch->getCond()->getType());
3256 Data.IntegralConstantExpression = true;
3257 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003258 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003259 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003260
3261 // Code-complete the cases of a switch statement over an enumeration type
3262 // by providing the list of
3263 EnumDecl *Enum = Switch->getCond()->getType()->getAs<EnumType>()->getDecl();
3264
3265 // Determine which enumerators we have already seen in the switch statement.
3266 // FIXME: Ideally, we would also be able to look *past* the code-completion
3267 // token, in case we are code-completing in the middle of the switch and not
3268 // at the end. However, we aren't able to do so at the moment.
3269 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003270 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003271 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3272 SC = SC->getNextSwitchCase()) {
3273 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3274 if (!Case)
3275 continue;
3276
3277 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3278 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3279 if (EnumConstantDecl *Enumerator
3280 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3281 // We look into the AST of the case statement to determine which
3282 // enumerator was named. Alternatively, we could compute the value of
3283 // the integral constant expression, then compare it against the
3284 // values of each enumerator. However, value-based approach would not
3285 // work as well with C++ templates where enumerators declared within a
3286 // template are type- and value-dependent.
3287 EnumeratorsSeen.insert(Enumerator);
3288
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003289 // If this is a qualified-id, keep track of the nested-name-specifier
3290 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003291 //
3292 // switch (TagD.getKind()) {
3293 // case TagDecl::TK_enum:
3294 // break;
3295 // case XXX
3296 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003297 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003298 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3299 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003300 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003301 }
3302 }
3303
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003304 if (getLangOptions().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
3305 // If there are no prior enumerators in C++, check whether we have to
3306 // qualify the names of the enumerators that we suggest, because they
3307 // may not be visible in this scope.
3308 Qualifier = getRequiredQualification(Context, CurContext,
3309 Enum->getDeclContext());
3310
3311 // FIXME: Scoped enums need to start with "EnumDecl" as the context!
3312 }
3313
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003314 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003315 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3316 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003317 Results.EnterNewScope();
3318 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3319 EEnd = Enum->enumerator_end();
3320 E != EEnd; ++E) {
3321 if (EnumeratorsSeen.count(*E))
3322 continue;
3323
John McCall0a2c5e22010-08-25 06:19:51 +00003324 Results.AddResult(CodeCompletionResult(*E, Qualifier),
Douglas Gregor608300b2010-01-14 16:14:35 +00003325 CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003326 }
3327 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003328
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003329 if (CodeCompleter->includeMacros())
Douglas Gregorbca403c2010-01-13 23:51:12 +00003330 AddMacroResults(PP, Results);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003331 HandleCodeCompleteResults(this, CodeCompleter,
3332 CodeCompletionContext::CCC_Expression,
3333 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003334}
3335
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003336namespace {
3337 struct IsBetterOverloadCandidate {
3338 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003339 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003340
3341 public:
John McCall5769d612010-02-08 23:07:23 +00003342 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3343 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003344
3345 bool
3346 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003347 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003348 }
3349 };
3350}
3351
Douglas Gregord28dcd72010-05-30 06:10:08 +00003352static bool anyNullArguments(Expr **Args, unsigned NumArgs) {
3353 if (NumArgs && !Args)
3354 return true;
3355
3356 for (unsigned I = 0; I != NumArgs; ++I)
3357 if (!Args[I])
3358 return true;
3359
3360 return false;
3361}
3362
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003363void Sema::CodeCompleteCall(Scope *S, ExprTy *FnIn,
3364 ExprTy **ArgsIn, unsigned NumArgs) {
3365 if (!CodeCompleter)
3366 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003367
3368 // When we're code-completing for a call, we fall back to ordinary
3369 // name code-completion whenever we can't produce specific
3370 // results. We may want to revisit this strategy in the future,
3371 // e.g., by merging the two kinds of results.
3372
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003373 Expr *Fn = (Expr *)FnIn;
3374 Expr **Args = (Expr **)ArgsIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003375
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003376 // Ignore type-dependent call expressions entirely.
Douglas Gregord28dcd72010-05-30 06:10:08 +00003377 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args, NumArgs) ||
Douglas Gregoref96eac2009-12-11 19:06:04 +00003378 Expr::hasAnyTypeDependentArguments(Args, NumArgs)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003379 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003380 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003381 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003382
John McCall3b4294e2009-12-16 12:17:52 +00003383 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003384 SourceLocation Loc = Fn->getExprLoc();
3385 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003386
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003387 // FIXME: What if we're calling something that isn't a function declaration?
3388 // FIXME: What if we're calling a pseudo-destructor?
3389 // FIXME: What if we're calling a member function?
3390
Douglas Gregorc0265402010-01-21 15:46:19 +00003391 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
3392 llvm::SmallVector<ResultCandidate, 8> Results;
3393
John McCall3b4294e2009-12-16 12:17:52 +00003394 Expr *NakedFn = Fn->IgnoreParenCasts();
3395 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
3396 AddOverloadedCallCandidates(ULE, Args, NumArgs, CandidateSet,
3397 /*PartialOverloading=*/ true);
3398 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3399 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003400 if (FDecl) {
Douglas Gregord28dcd72010-05-30 06:10:08 +00003401 if (!getLangOptions().CPlusPlus ||
3402 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003403 Results.push_back(ResultCandidate(FDecl));
3404 else
John McCall86820f52010-01-26 01:37:31 +00003405 // FIXME: access?
John McCall9aa472c2010-03-19 07:35:19 +00003406 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none),
3407 Args, NumArgs, CandidateSet,
Douglas Gregorc27d6c52010-04-16 17:41:49 +00003408 false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003409 }
John McCall3b4294e2009-12-16 12:17:52 +00003410 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003411
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003412 QualType ParamType;
3413
Douglas Gregorc0265402010-01-21 15:46:19 +00003414 if (!CandidateSet.empty()) {
3415 // Sort the overload candidate set by placing the best overloads first.
3416 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003417 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003418
Douglas Gregorc0265402010-01-21 15:46:19 +00003419 // Add the remaining viable overload candidates as code-completion reslults.
3420 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3421 CandEnd = CandidateSet.end();
3422 Cand != CandEnd; ++Cand) {
3423 if (Cand->Viable)
3424 Results.push_back(ResultCandidate(Cand->Function));
3425 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003426
3427 // From the viable candidates, try to determine the type of this parameter.
3428 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3429 if (const FunctionType *FType = Results[I].getFunctionType())
3430 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
3431 if (NumArgs < Proto->getNumArgs()) {
3432 if (ParamType.isNull())
3433 ParamType = Proto->getArgType(NumArgs);
3434 else if (!Context.hasSameUnqualifiedType(
3435 ParamType.getNonReferenceType(),
3436 Proto->getArgType(NumArgs).getNonReferenceType())) {
3437 ParamType = QualType();
3438 break;
3439 }
3440 }
3441 }
3442 } else {
3443 // Try to determine the parameter type from the type of the expression
3444 // being called.
3445 QualType FunctionType = Fn->getType();
3446 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3447 FunctionType = Ptr->getPointeeType();
3448 else if (const BlockPointerType *BlockPtr
3449 = FunctionType->getAs<BlockPointerType>())
3450 FunctionType = BlockPtr->getPointeeType();
3451 else if (const MemberPointerType *MemPtr
3452 = FunctionType->getAs<MemberPointerType>())
3453 FunctionType = MemPtr->getPointeeType();
3454
3455 if (const FunctionProtoType *Proto
3456 = FunctionType->getAs<FunctionProtoType>()) {
3457 if (NumArgs < Proto->getNumArgs())
3458 ParamType = Proto->getArgType(NumArgs);
3459 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003460 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003461
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003462 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003463 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003464 else
3465 CodeCompleteExpression(S, ParamType);
3466
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003467 if (!Results.empty())
Douglas Gregoref96eac2009-12-11 19:06:04 +00003468 CodeCompleter->ProcessOverloadCandidates(*this, NumArgs, Results.data(),
3469 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003470}
3471
John McCalld226f652010-08-21 09:40:31 +00003472void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3473 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003474 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003475 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003476 return;
3477 }
3478
3479 CodeCompleteExpression(S, VD->getType());
3480}
3481
3482void Sema::CodeCompleteReturn(Scope *S) {
3483 QualType ResultType;
3484 if (isa<BlockDecl>(CurContext)) {
3485 if (BlockScopeInfo *BSI = getCurBlock())
3486 ResultType = BSI->ReturnType;
3487 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3488 ResultType = Function->getResultType();
3489 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3490 ResultType = Method->getResultType();
3491
3492 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003493 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003494 else
3495 CodeCompleteExpression(S, ResultType);
3496}
3497
3498void Sema::CodeCompleteAssignmentRHS(Scope *S, ExprTy *LHS) {
3499 if (LHS)
3500 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
3501 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003502 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003503}
3504
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00003505void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003506 bool EnteringContext) {
3507 if (!SS.getScopeRep() || !CodeCompleter)
3508 return;
3509
Douglas Gregor86d9a522009-09-21 16:56:56 +00003510 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
3511 if (!Ctx)
3512 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003513
3514 // Try to instantiate any non-dependent declaration contexts before
3515 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00003516 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00003517 return;
3518
Douglas Gregor218937c2011-02-01 19:23:04 +00003519 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3520 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00003521 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003522
Douglas Gregor86d9a522009-09-21 16:56:56 +00003523 // The "template" keyword can follow "::" in the grammar, but only
3524 // put it into the grammar if the nested-name-specifier is dependent.
3525 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
3526 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00003527 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00003528
3529 // Add calls to overridden virtual functions, if there are any.
3530 //
3531 // FIXME: This isn't wonderful, because we don't know whether we're actually
3532 // in a context that permits expressions. This is a general issue with
3533 // qualified-id completions.
3534 if (!EnteringContext)
3535 MaybeAddOverrideCalls(*this, Ctx, Results);
3536 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003537
Douglas Gregorf6961522010-08-27 21:18:54 +00003538 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3539 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
3540
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003541 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorf6961522010-08-27 21:18:54 +00003542 CodeCompletionContext::CCC_Name,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003543 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003544}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003545
3546void Sema::CodeCompleteUsing(Scope *S) {
3547 if (!CodeCompleter)
3548 return;
3549
Douglas Gregor218937c2011-02-01 19:23:04 +00003550 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003551 CodeCompletionContext::CCC_PotentiallyQualifiedName,
3552 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003553 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003554
3555 // If we aren't in class scope, we could see the "namespace" keyword.
3556 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00003557 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003558
3559 // After "using", we can see anything that would start a
3560 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003561 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003562 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3563 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003564 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003565
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003566 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003567 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003568 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003569}
3570
3571void Sema::CodeCompleteUsingDirective(Scope *S) {
3572 if (!CodeCompleter)
3573 return;
3574
Douglas Gregor86d9a522009-09-21 16:56:56 +00003575 // After "using namespace", we expect to see a namespace name or namespace
3576 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003577 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3578 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003579 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003580 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003581 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003582 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3583 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003584 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003585 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003586 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003587 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003588}
3589
3590void Sema::CodeCompleteNamespaceDecl(Scope *S) {
3591 if (!CodeCompleter)
3592 return;
3593
Douglas Gregor86d9a522009-09-21 16:56:56 +00003594 DeclContext *Ctx = (DeclContext *)S->getEntity();
3595 if (!S->getParent())
3596 Ctx = Context.getTranslationUnitDecl();
3597
Douglas Gregor52779fb2010-09-23 23:01:17 +00003598 bool SuppressedGlobalResults
3599 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
3600
Douglas Gregor218937c2011-02-01 19:23:04 +00003601 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003602 SuppressedGlobalResults
3603 ? CodeCompletionContext::CCC_Namespace
3604 : CodeCompletionContext::CCC_Other,
3605 &ResultBuilder::IsNamespace);
3606
3607 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00003608 // We only want to see those namespaces that have already been defined
3609 // within this scope, because its likely that the user is creating an
3610 // extended namespace declaration. Keep track of the most recent
3611 // definition of each namespace.
3612 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
3613 for (DeclContext::specific_decl_iterator<NamespaceDecl>
3614 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
3615 NS != NSEnd; ++NS)
3616 OrigToLatest[NS->getOriginalNamespace()] = *NS;
3617
3618 // Add the most recent definition (or extended definition) of each
3619 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003620 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003621 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
3622 NS = OrigToLatest.begin(), NSEnd = OrigToLatest.end();
3623 NS != NSEnd; ++NS)
John McCall0a2c5e22010-08-25 06:19:51 +00003624 Results.AddResult(CodeCompletionResult(NS->second, 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00003625 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003626 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003627 }
3628
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003629 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003630 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003631 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003632}
3633
3634void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
3635 if (!CodeCompleter)
3636 return;
3637
Douglas Gregor86d9a522009-09-21 16:56:56 +00003638 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00003639 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3640 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003641 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003642 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003643 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3644 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003645 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003646 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003647 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003648}
3649
Douglas Gregored8d3222009-09-18 20:05:18 +00003650void Sema::CodeCompleteOperatorName(Scope *S) {
3651 if (!CodeCompleter)
3652 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003653
John McCall0a2c5e22010-08-25 06:19:51 +00003654 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003655 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3656 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003657 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003658 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00003659
Douglas Gregor86d9a522009-09-21 16:56:56 +00003660 // Add the names of overloadable operators.
3661#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
3662 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00003663 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00003664#include "clang/Basic/OperatorKinds.def"
3665
3666 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00003667 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003668 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003669 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3670 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00003671
3672 // Add any type specifiers
Douglas Gregorbca403c2010-01-13 23:51:12 +00003673 AddTypeSpecifierResults(getLangOptions(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00003674 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003675
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003676 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00003677 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003678 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00003679}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00003680
Douglas Gregor0133f522010-08-28 00:00:50 +00003681void Sema::CodeCompleteConstructorInitializer(Decl *ConstructorD,
Sean Huntcbb67482011-01-08 20:30:50 +00003682 CXXCtorInitializer** Initializers,
Douglas Gregor0133f522010-08-28 00:00:50 +00003683 unsigned NumInitializers) {
3684 CXXConstructorDecl *Constructor
3685 = static_cast<CXXConstructorDecl *>(ConstructorD);
3686 if (!Constructor)
3687 return;
3688
Douglas Gregor218937c2011-02-01 19:23:04 +00003689 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003690 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00003691 Results.EnterNewScope();
3692
3693 // Fill in any already-initialized fields or base classes.
3694 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
3695 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
3696 for (unsigned I = 0; I != NumInitializers; ++I) {
3697 if (Initializers[I]->isBaseInitializer())
3698 InitializedBases.insert(
3699 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
3700 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00003701 InitializedFields.insert(cast<FieldDecl>(
3702 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00003703 }
3704
3705 // Add completions for base classes.
Douglas Gregor218937c2011-02-01 19:23:04 +00003706 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor0c431c82010-08-29 19:27:27 +00003707 bool SawLastInitializer = (NumInitializers == 0);
Douglas Gregor0133f522010-08-28 00:00:50 +00003708 CXXRecordDecl *ClassDecl = Constructor->getParent();
3709 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
3710 BaseEnd = ClassDecl->bases_end();
3711 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003712 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
3713 SawLastInitializer
3714 = NumInitializers > 0 &&
3715 Initializers[NumInitializers - 1]->isBaseInitializer() &&
3716 Context.hasSameUnqualifiedType(Base->getType(),
3717 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00003718 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003719 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003720
Douglas Gregor218937c2011-02-01 19:23:04 +00003721 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00003722 Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003723 Base->getType().getAsString(Context.PrintingPolicy)));
3724 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3725 Builder.AddPlaceholderChunk("args");
3726 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3727 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003728 SawLastInitializer? CCP_NextInitializer
3729 : CCP_MemberDeclaration));
3730 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003731 }
3732
3733 // Add completions for virtual base classes.
3734 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
3735 BaseEnd = ClassDecl->vbases_end();
3736 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003737 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
3738 SawLastInitializer
3739 = NumInitializers > 0 &&
3740 Initializers[NumInitializers - 1]->isBaseInitializer() &&
3741 Context.hasSameUnqualifiedType(Base->getType(),
3742 QualType(Initializers[NumInitializers - 1]->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00003743 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003744 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003745
Douglas Gregor218937c2011-02-01 19:23:04 +00003746 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00003747 Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003748 Base->getType().getAsString(Context.PrintingPolicy)));
3749 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3750 Builder.AddPlaceholderChunk("args");
3751 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3752 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003753 SawLastInitializer? CCP_NextInitializer
3754 : CCP_MemberDeclaration));
3755 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003756 }
3757
3758 // Add completions for members.
3759 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
3760 FieldEnd = ClassDecl->field_end();
3761 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00003762 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
3763 SawLastInitializer
3764 = NumInitializers > 0 &&
Francois Pichet00eb3f92010-12-04 09:14:42 +00003765 Initializers[NumInitializers - 1]->isAnyMemberInitializer() &&
3766 Initializers[NumInitializers - 1]->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00003767 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00003768 }
Douglas Gregor0133f522010-08-28 00:00:50 +00003769
3770 if (!Field->getDeclName())
3771 continue;
3772
Douglas Gregordae68752011-02-01 22:57:45 +00003773 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003774 Field->getIdentifier()->getName()));
3775 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3776 Builder.AddPlaceholderChunk("args");
3777 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3778 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00003779 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00003780 : CCP_MemberDeclaration,
3781 CXCursor_MemberRef));
Douglas Gregor0c431c82010-08-29 19:27:27 +00003782 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00003783 }
3784 Results.ExitScope();
3785
Douglas Gregor52779fb2010-09-23 23:01:17 +00003786 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00003787 Results.data(), Results.size());
3788}
3789
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003790// Macro that expands to @Keyword or Keyword, depending on whether NeedAt is
3791// true or false.
3792#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) NeedAt? "@" #Keyword : #Keyword
Douglas Gregorbca403c2010-01-13 23:51:12 +00003793static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003794 ResultBuilder &Results,
3795 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003796 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003797 // Since we have an implementation, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00003798 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003799
Douglas Gregor218937c2011-02-01 19:23:04 +00003800 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003801 if (LangOpts.ObjC2) {
3802 // @dynamic
Douglas Gregor218937c2011-02-01 19:23:04 +00003803 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,dynamic));
3804 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3805 Builder.AddPlaceholderChunk("property");
3806 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003807
3808 // @synthesize
Douglas Gregor218937c2011-02-01 19:23:04 +00003809 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synthesize));
3810 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3811 Builder.AddPlaceholderChunk("property");
3812 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003813 }
3814}
3815
Douglas Gregorbca403c2010-01-13 23:51:12 +00003816static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003817 ResultBuilder &Results,
3818 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003819 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003820
3821 // Since we have an interface or protocol, we can end it.
Douglas Gregora4477812010-01-14 16:01:26 +00003822 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,end)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003823
3824 if (LangOpts.ObjC2) {
3825 // @property
Douglas Gregora4477812010-01-14 16:01:26 +00003826 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,property)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003827
3828 // @required
Douglas Gregora4477812010-01-14 16:01:26 +00003829 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,required)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003830
3831 // @optional
Douglas Gregora4477812010-01-14 16:01:26 +00003832 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,optional)));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003833 }
3834}
3835
Douglas Gregorbca403c2010-01-13 23:51:12 +00003836static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003837 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003838 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003839
3840 // @class name ;
Douglas Gregor218937c2011-02-01 19:23:04 +00003841 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,class));
3842 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3843 Builder.AddPlaceholderChunk("name");
3844 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003845
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003846 if (Results.includeCodePatterns()) {
3847 // @interface name
3848 // FIXME: Could introduce the whole pattern, including superclasses and
3849 // such.
Douglas Gregor218937c2011-02-01 19:23:04 +00003850 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,interface));
3851 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3852 Builder.AddPlaceholderChunk("class");
3853 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003854
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003855 // @protocol name
Douglas Gregor218937c2011-02-01 19:23:04 +00003856 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
3857 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3858 Builder.AddPlaceholderChunk("protocol");
3859 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003860
3861 // @implementation name
Douglas Gregor218937c2011-02-01 19:23:04 +00003862 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,implementation));
3863 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3864 Builder.AddPlaceholderChunk("class");
3865 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003866 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003867
3868 // @compatibility_alias name
Douglas Gregor218937c2011-02-01 19:23:04 +00003869 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,compatibility_alias));
3870 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3871 Builder.AddPlaceholderChunk("alias");
3872 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3873 Builder.AddPlaceholderChunk("class");
3874 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003875}
3876
John McCalld226f652010-08-21 09:40:31 +00003877void Sema::CodeCompleteObjCAtDirective(Scope *S, Decl *ObjCImpDecl,
Douglas Gregorc464ae82009-12-07 09:27:33 +00003878 bool InInterface) {
John McCall0a2c5e22010-08-25 06:19:51 +00003879 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003880 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3881 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00003882 Results.EnterNewScope();
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003883 if (ObjCImpDecl)
Douglas Gregorbca403c2010-01-13 23:51:12 +00003884 AddObjCImplementationResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003885 else if (InInterface)
Douglas Gregorbca403c2010-01-13 23:51:12 +00003886 AddObjCInterfaceResults(getLangOptions(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003887 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00003888 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00003889 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003890 HandleCodeCompleteResults(this, CodeCompleter,
3891 CodeCompletionContext::CCC_Other,
3892 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00003893}
3894
Douglas Gregorbca403c2010-01-13 23:51:12 +00003895static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003896 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003897 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003898
3899 // @encode ( type-name )
Douglas Gregor218937c2011-02-01 19:23:04 +00003900 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,encode));
3901 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3902 Builder.AddPlaceholderChunk("type-name");
3903 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3904 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003905
3906 // @protocol ( protocol-name )
Douglas Gregor218937c2011-02-01 19:23:04 +00003907 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,protocol));
3908 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3909 Builder.AddPlaceholderChunk("protocol-name");
3910 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3911 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003912
3913 // @selector ( selector )
Douglas Gregor218937c2011-02-01 19:23:04 +00003914 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,selector));
3915 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3916 Builder.AddPlaceholderChunk("selector");
3917 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3918 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003919}
3920
Douglas Gregorbca403c2010-01-13 23:51:12 +00003921static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003922 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003923 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003924
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003925 if (Results.includeCodePatterns()) {
3926 // @try { statements } @catch ( declaration ) { statements } @finally
3927 // { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00003928 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,try));
3929 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3930 Builder.AddPlaceholderChunk("statements");
3931 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3932 Builder.AddTextChunk("@catch");
3933 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3934 Builder.AddPlaceholderChunk("parameter");
3935 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3936 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3937 Builder.AddPlaceholderChunk("statements");
3938 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3939 Builder.AddTextChunk("@finally");
3940 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3941 Builder.AddPlaceholderChunk("statements");
3942 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3943 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003944 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003945
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003946 // @throw
Douglas Gregor218937c2011-02-01 19:23:04 +00003947 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,throw));
3948 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3949 Builder.AddPlaceholderChunk("expression");
3950 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003951
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003952 if (Results.includeCodePatterns()) {
3953 // @synchronized ( expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00003954 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,synchronized));
3955 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
3956 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3957 Builder.AddPlaceholderChunk("expression");
3958 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3959 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
3960 Builder.AddPlaceholderChunk("statements");
3961 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
3962 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00003963 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003964}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003965
Douglas Gregorbca403c2010-01-13 23:51:12 +00003966static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003967 ResultBuilder &Results,
3968 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00003969 typedef CodeCompletionResult Result;
Douglas Gregora4477812010-01-14 16:01:26 +00003970 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,private)));
3971 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,protected)));
3972 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,public)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003973 if (LangOpts.ObjC2)
Douglas Gregora4477812010-01-14 16:01:26 +00003974 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,package)));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003975}
3976
3977void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003978 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3979 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003980 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00003981 AddObjCVisibilityResults(getLangOptions(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003982 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003983 HandleCodeCompleteResults(this, CodeCompleter,
3984 CodeCompletionContext::CCC_Other,
3985 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00003986}
3987
3988void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003989 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3990 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00003991 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00003992 AddObjCStatementResults(Results, false);
3993 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003994 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003995 HandleCodeCompleteResults(this, CodeCompleter,
3996 CodeCompletionContext::CCC_Other,
3997 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00003998}
3999
4000void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004001 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4002 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004003 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004004 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004005 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004006 HandleCodeCompleteResults(this, CodeCompleter,
4007 CodeCompletionContext::CCC_Other,
4008 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004009}
4010
Douglas Gregor988358f2009-11-19 00:14:45 +00004011/// \brief Determine whether the addition of the given flag to an Objective-C
4012/// property's attributes will cause a conflict.
4013static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
4014 // Check if we've already added this flag.
4015 if (Attributes & NewFlag)
4016 return true;
4017
4018 Attributes |= NewFlag;
4019
4020 // Check for collisions with "readonly".
4021 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4022 (Attributes & (ObjCDeclSpec::DQ_PR_readwrite |
4023 ObjCDeclSpec::DQ_PR_assign |
4024 ObjCDeclSpec::DQ_PR_copy |
4025 ObjCDeclSpec::DQ_PR_retain)))
4026 return true;
4027
4028 // Check for more than one of { assign, copy, retain }.
4029 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
4030 ObjCDeclSpec::DQ_PR_copy |
4031 ObjCDeclSpec::DQ_PR_retain);
4032 if (AssignCopyRetMask &&
4033 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
4034 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
4035 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain)
4036 return true;
4037
4038 return false;
4039}
4040
Douglas Gregora93b1082009-11-18 23:08:07 +00004041void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004042 if (!CodeCompleter)
4043 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004044
Steve Naroffece8e712009-10-08 21:55:05 +00004045 unsigned Attributes = ODS.getPropertyAttributes();
4046
John McCall0a2c5e22010-08-25 06:19:51 +00004047 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004048 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4049 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004050 Results.EnterNewScope();
Douglas Gregor988358f2009-11-19 00:14:45 +00004051 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004052 Results.AddResult(CodeCompletionResult("readonly"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004053 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004054 Results.AddResult(CodeCompletionResult("assign"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004055 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004056 Results.AddResult(CodeCompletionResult("readwrite"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004057 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004058 Results.AddResult(CodeCompletionResult("retain"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004059 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004060 Results.AddResult(CodeCompletionResult("copy"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004061 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004062 Results.AddResult(CodeCompletionResult("nonatomic"));
Douglas Gregor988358f2009-11-19 00:14:45 +00004063 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004064 CodeCompletionBuilder Setter(Results.getAllocator());
4065 Setter.AddTypedTextChunk("setter");
4066 Setter.AddTextChunk(" = ");
4067 Setter.AddPlaceholderChunk("method");
4068 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004069 }
Douglas Gregor988358f2009-11-19 00:14:45 +00004070 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004071 CodeCompletionBuilder Getter(Results.getAllocator());
4072 Getter.AddTypedTextChunk("getter");
4073 Getter.AddTextChunk(" = ");
4074 Getter.AddPlaceholderChunk("method");
4075 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004076 }
Steve Naroffece8e712009-10-08 21:55:05 +00004077 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004078 HandleCodeCompleteResults(this, CodeCompleter,
4079 CodeCompletionContext::CCC_Other,
4080 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004081}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004082
Douglas Gregor4ad96852009-11-19 07:41:15 +00004083/// \brief Descripts the kind of Objective-C method that we want to find
4084/// via code completion.
4085enum ObjCMethodKind {
4086 MK_Any, //< Any kind of method, provided it means other specified criteria.
4087 MK_ZeroArgSelector, //< Zero-argument (unary) selector.
4088 MK_OneArgSelector //< One-argument selector.
4089};
4090
Douglas Gregor458433d2010-08-26 15:07:07 +00004091static bool isAcceptableObjCSelector(Selector Sel,
4092 ObjCMethodKind WantKind,
4093 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004094 unsigned NumSelIdents,
4095 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004096 if (NumSelIdents > Sel.getNumArgs())
4097 return false;
4098
4099 switch (WantKind) {
4100 case MK_Any: break;
4101 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4102 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4103 }
4104
Douglas Gregorcf544262010-11-17 21:36:08 +00004105 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4106 return false;
4107
Douglas Gregor458433d2010-08-26 15:07:07 +00004108 for (unsigned I = 0; I != NumSelIdents; ++I)
4109 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4110 return false;
4111
4112 return true;
4113}
4114
Douglas Gregor4ad96852009-11-19 07:41:15 +00004115static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4116 ObjCMethodKind WantKind,
4117 IdentifierInfo **SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004118 unsigned NumSelIdents,
4119 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004120 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004121 NumSelIdents, AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004122}
Douglas Gregord36adf52010-09-16 16:06:31 +00004123
4124namespace {
4125 /// \brief A set of selectors, which is used to avoid introducing multiple
4126 /// completions with the same selector into the result set.
4127 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4128}
4129
Douglas Gregor36ecb042009-11-17 23:22:23 +00004130/// \brief Add all of the Objective-C methods in the given Objective-C
4131/// container to the set of results.
4132///
4133/// The container will be a class, protocol, category, or implementation of
4134/// any of the above. This mether will recurse to include methods from
4135/// the superclasses of classes along with their categories, protocols, and
4136/// implementations.
4137///
4138/// \param Container the container in which we'll look to find methods.
4139///
4140/// \param WantInstance whether to add instance methods (only); if false, this
4141/// routine will add factory methods (only).
4142///
4143/// \param CurContext the context in which we're performing the lookup that
4144/// finds methods.
4145///
Douglas Gregorcf544262010-11-17 21:36:08 +00004146/// \param AllowSameLength Whether we allow a method to be added to the list
4147/// when it has the same number of parameters as we have selector identifiers.
4148///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004149/// \param Results the structure into which we'll add results.
4150static void AddObjCMethods(ObjCContainerDecl *Container,
4151 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004152 ObjCMethodKind WantKind,
Douglas Gregord3c68542009-11-19 01:08:35 +00004153 IdentifierInfo **SelIdents,
4154 unsigned NumSelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004155 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004156 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004157 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004158 ResultBuilder &Results,
4159 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004160 typedef CodeCompletionResult Result;
Douglas Gregor36ecb042009-11-17 23:22:23 +00004161 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4162 MEnd = Container->meth_end();
4163 M != MEnd; ++M) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004164 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
4165 // Check whether the selector identifiers we've been given are a
4166 // subset of the identifiers for this particular method.
Douglas Gregorcf544262010-11-17 21:36:08 +00004167 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, NumSelIdents,
4168 AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004169 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004170
Douglas Gregord36adf52010-09-16 16:06:31 +00004171 if (!Selectors.insert((*M)->getSelector()))
4172 continue;
4173
Douglas Gregord3c68542009-11-19 01:08:35 +00004174 Result R = Result(*M, 0);
4175 R.StartParameter = NumSelIdents;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004176 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004177 if (!InOriginalClass)
4178 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004179 Results.MaybeAddResult(R, CurContext);
4180 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004181 }
4182
Douglas Gregore396c7b2010-09-16 15:34:59 +00004183 // Visit the protocols of protocols.
4184 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
4185 const ObjCList<ObjCProtocolDecl> &Protocols
4186 = Protocol->getReferencedProtocols();
4187 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4188 E = Protocols.end();
4189 I != E; ++I)
4190 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004191 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregore396c7b2010-09-16 15:34:59 +00004192 }
4193
Douglas Gregor36ecb042009-11-17 23:22:23 +00004194 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
4195 if (!IFace)
4196 return;
4197
4198 // Add methods in protocols.
4199 const ObjCList<ObjCProtocolDecl> &Protocols= IFace->getReferencedProtocols();
4200 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4201 E = Protocols.end();
4202 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004203 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004204 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004205
4206 // Add methods in categories.
4207 for (ObjCCategoryDecl *CatDecl = IFace->getCategoryList(); CatDecl;
4208 CatDecl = CatDecl->getNextClassCategory()) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004209 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004210 NumSelIdents, CurContext, Selectors, AllowSameLength,
4211 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004212
4213 // Add a categories protocol methods.
4214 const ObjCList<ObjCProtocolDecl> &Protocols
4215 = CatDecl->getReferencedProtocols();
4216 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4217 E = Protocols.end();
4218 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004219 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004220 NumSelIdents, CurContext, Selectors, AllowSameLength,
4221 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004222
4223 // Add methods in category implementations.
4224 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004225 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004226 NumSelIdents, CurContext, Selectors, AllowSameLength,
4227 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004228 }
4229
4230 // Add methods in superclass.
4231 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004232 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Douglas Gregorcf544262010-11-17 21:36:08 +00004233 SelIdents, NumSelIdents, CurContext, Selectors,
4234 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004235
4236 // Add methods in our implementation, if any.
4237 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004238 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004239 NumSelIdents, CurContext, Selectors, AllowSameLength,
4240 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004241}
4242
4243
Douglas Gregorbdb2d502010-12-21 17:34:17 +00004244void Sema::CodeCompleteObjCPropertyGetter(Scope *S, Decl *ClassDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00004245 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004246
4247 // Try to find the interface where getters might live.
John McCalld226f652010-08-21 09:40:31 +00004248 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(ClassDecl);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004249 if (!Class) {
4250 if (ObjCCategoryDecl *Category
John McCalld226f652010-08-21 09:40:31 +00004251 = dyn_cast_or_null<ObjCCategoryDecl>(ClassDecl))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004252 Class = Category->getClassInterface();
4253
4254 if (!Class)
4255 return;
4256 }
4257
4258 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004259 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4260 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004261 Results.EnterNewScope();
4262
Douglas Gregord36adf52010-09-16 16:06:31 +00004263 VisitedSelectorSet Selectors;
4264 AddObjCMethods(Class, true, MK_ZeroArgSelector, 0, 0, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004265 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004266 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004267 HandleCodeCompleteResults(this, CodeCompleter,
4268 CodeCompletionContext::CCC_Other,
4269 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004270}
4271
Douglas Gregorbdb2d502010-12-21 17:34:17 +00004272void Sema::CodeCompleteObjCPropertySetter(Scope *S, Decl *ObjCImplDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00004273 typedef CodeCompletionResult Result;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004274
4275 // Try to find the interface where setters might live.
4276 ObjCInterfaceDecl *Class
John McCalld226f652010-08-21 09:40:31 +00004277 = dyn_cast_or_null<ObjCInterfaceDecl>(ObjCImplDecl);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004278 if (!Class) {
4279 if (ObjCCategoryDecl *Category
John McCalld226f652010-08-21 09:40:31 +00004280 = dyn_cast_or_null<ObjCCategoryDecl>(ObjCImplDecl))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004281 Class = Category->getClassInterface();
4282
4283 if (!Class)
4284 return;
4285 }
4286
4287 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004288 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4289 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004290 Results.EnterNewScope();
4291
Douglas Gregord36adf52010-09-16 16:06:31 +00004292 VisitedSelectorSet Selectors;
4293 AddObjCMethods(Class, true, MK_OneArgSelector, 0, 0, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004294 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004295
4296 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004297 HandleCodeCompleteResults(this, CodeCompleter,
4298 CodeCompletionContext::CCC_Other,
4299 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004300}
4301
Douglas Gregord32b0222010-08-24 01:06:58 +00004302void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS) {
John McCall0a2c5e22010-08-25 06:19:51 +00004303 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004304 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4305 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00004306 Results.EnterNewScope();
4307
4308 // Add context-sensitive, Objective-C parameter-passing keywords.
4309 bool AddedInOut = false;
4310 if ((DS.getObjCDeclQualifier() &
4311 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
4312 Results.AddResult("in");
4313 Results.AddResult("inout");
4314 AddedInOut = true;
4315 }
4316 if ((DS.getObjCDeclQualifier() &
4317 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
4318 Results.AddResult("out");
4319 if (!AddedInOut)
4320 Results.AddResult("inout");
4321 }
4322 if ((DS.getObjCDeclQualifier() &
4323 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
4324 ObjCDeclSpec::DQ_Oneway)) == 0) {
4325 Results.AddResult("bycopy");
4326 Results.AddResult("byref");
4327 Results.AddResult("oneway");
4328 }
4329
4330 // Add various builtin type names and specifiers.
4331 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
4332 Results.ExitScope();
4333
4334 // Add the various type names
4335 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
4336 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4337 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4338 CodeCompleter->includeGlobals());
4339
4340 if (CodeCompleter->includeMacros())
4341 AddMacroResults(PP, Results);
4342
4343 HandleCodeCompleteResults(this, CodeCompleter,
4344 CodeCompletionContext::CCC_Type,
4345 Results.data(), Results.size());
4346}
4347
Douglas Gregor22f56992010-04-06 19:22:33 +00004348/// \brief When we have an expression with type "id", we may assume
4349/// that it has some more-specific class type based on knowledge of
4350/// common uses of Objective-C. This routine returns that class type,
4351/// or NULL if no better result could be determined.
4352static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00004353 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00004354 if (!Msg)
4355 return 0;
4356
4357 Selector Sel = Msg->getSelector();
4358 if (Sel.isNull())
4359 return 0;
4360
4361 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
4362 if (!Id)
4363 return 0;
4364
4365 ObjCMethodDecl *Method = Msg->getMethodDecl();
4366 if (!Method)
4367 return 0;
4368
4369 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00004370 ObjCInterfaceDecl *IFace = 0;
4371 switch (Msg->getReceiverKind()) {
4372 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00004373 if (const ObjCObjectType *ObjType
4374 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
4375 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00004376 break;
4377
4378 case ObjCMessageExpr::Instance: {
4379 QualType T = Msg->getInstanceReceiver()->getType();
4380 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
4381 IFace = Ptr->getInterfaceDecl();
4382 break;
4383 }
4384
4385 case ObjCMessageExpr::SuperInstance:
4386 case ObjCMessageExpr::SuperClass:
4387 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00004388 }
4389
4390 if (!IFace)
4391 return 0;
4392
4393 ObjCInterfaceDecl *Super = IFace->getSuperClass();
4394 if (Method->isInstanceMethod())
4395 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4396 .Case("retain", IFace)
4397 .Case("autorelease", IFace)
4398 .Case("copy", IFace)
4399 .Case("copyWithZone", IFace)
4400 .Case("mutableCopy", IFace)
4401 .Case("mutableCopyWithZone", IFace)
4402 .Case("awakeFromCoder", IFace)
4403 .Case("replacementObjectFromCoder", IFace)
4404 .Case("class", IFace)
4405 .Case("classForCoder", IFace)
4406 .Case("superclass", Super)
4407 .Default(0);
4408
4409 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
4410 .Case("new", IFace)
4411 .Case("alloc", IFace)
4412 .Case("allocWithZone", IFace)
4413 .Case("class", IFace)
4414 .Case("superclass", Super)
4415 .Default(0);
4416}
4417
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004418// Add a special completion for a message send to "super", which fills in the
4419// most likely case of forwarding all of our arguments to the superclass
4420// function.
4421///
4422/// \param S The semantic analysis object.
4423///
4424/// \param S NeedSuperKeyword Whether we need to prefix this completion with
4425/// the "super" keyword. Otherwise, we just need to provide the arguments.
4426///
4427/// \param SelIdents The identifiers in the selector that have already been
4428/// provided as arguments for a send to "super".
4429///
4430/// \param NumSelIdents The number of identifiers in \p SelIdents.
4431///
4432/// \param Results The set of results to augment.
4433///
4434/// \returns the Objective-C method declaration that would be invoked by
4435/// this "super" completion. If NULL, no completion was added.
4436static ObjCMethodDecl *AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
4437 IdentifierInfo **SelIdents,
4438 unsigned NumSelIdents,
4439 ResultBuilder &Results) {
4440 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
4441 if (!CurMethod)
4442 return 0;
4443
4444 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
4445 if (!Class)
4446 return 0;
4447
4448 // Try to find a superclass method with the same selector.
4449 ObjCMethodDecl *SuperMethod = 0;
4450 while ((Class = Class->getSuperClass()) && !SuperMethod)
4451 SuperMethod = Class->getMethod(CurMethod->getSelector(),
4452 CurMethod->isInstanceMethod());
4453
4454 if (!SuperMethod)
4455 return 0;
4456
4457 // Check whether the superclass method has the same signature.
4458 if (CurMethod->param_size() != SuperMethod->param_size() ||
4459 CurMethod->isVariadic() != SuperMethod->isVariadic())
4460 return 0;
4461
4462 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
4463 CurPEnd = CurMethod->param_end(),
4464 SuperP = SuperMethod->param_begin();
4465 CurP != CurPEnd; ++CurP, ++SuperP) {
4466 // Make sure the parameter types are compatible.
4467 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
4468 (*SuperP)->getType()))
4469 return 0;
4470
4471 // Make sure we have a parameter name to forward!
4472 if (!(*CurP)->getIdentifier())
4473 return 0;
4474 }
4475
4476 // We have a superclass method. Now, form the send-to-super completion.
Douglas Gregor218937c2011-02-01 19:23:04 +00004477 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004478
4479 // Give this completion a return type.
Douglas Gregor218937c2011-02-01 19:23:04 +00004480 AddResultTypeChunk(S.Context, SuperMethod, Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004481
4482 // If we need the "super" keyword, add it (plus some spacing).
4483 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004484 Builder.AddTypedTextChunk("super");
4485 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004486 }
4487
4488 Selector Sel = CurMethod->getSelector();
4489 if (Sel.isUnarySelector()) {
4490 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00004491 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004492 Sel.getIdentifierInfoForSlot(0)->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004493 else
Douglas Gregordae68752011-02-01 22:57:45 +00004494 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004495 Sel.getIdentifierInfoForSlot(0)->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004496 } else {
4497 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
4498 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
4499 if (I > NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004500 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004501
4502 if (I < NumSelIdents)
Douglas Gregor218937c2011-02-01 19:23:04 +00004503 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004504 Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004505 Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004506 else if (NeedSuperKeyword || I > NumSelIdents) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004507 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004508 Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004509 Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004510 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004511 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004512 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00004513 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004514 Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004515 Sel.getIdentifierInfoForSlot(I)->getName().str() + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00004516 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004517 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004518 }
4519 }
4520 }
4521
Douglas Gregor218937c2011-02-01 19:23:04 +00004522 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_SuperCompletion,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004523 SuperMethod->isInstanceMethod()
4524 ? CXCursor_ObjCInstanceMethodDecl
4525 : CXCursor_ObjCClassMethodDecl));
4526 return SuperMethod;
4527}
4528
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004529void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00004530 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004531 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4532 CodeCompletionContext::CCC_ObjCMessageReceiver,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004533 &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004534
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004535 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4536 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00004537 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4538 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004539
4540 // If we are in an Objective-C method inside a class that has a superclass,
4541 // add "super" as an option.
4542 if (ObjCMethodDecl *Method = getCurMethodDecl())
4543 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004544 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004545 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004546
4547 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, 0, 0, Results);
4548 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004549
4550 Results.ExitScope();
4551
4552 if (CodeCompleter->includeMacros())
4553 AddMacroResults(PP, Results);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00004554 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004555 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00004556
4557}
4558
Douglas Gregor2725ca82010-04-21 19:57:20 +00004559void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
4560 IdentifierInfo **SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004561 unsigned NumSelIdents,
4562 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00004563 ObjCInterfaceDecl *CDecl = 0;
4564 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
4565 // Figure out which interface we're in.
4566 CDecl = CurMethod->getClassInterface();
4567 if (!CDecl)
4568 return;
4569
4570 // Find the superclass of this class.
4571 CDecl = CDecl->getSuperClass();
4572 if (!CDecl)
4573 return;
4574
4575 if (CurMethod->isInstanceMethod()) {
4576 // We are inside an instance method, which means that the message
4577 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004578 // current object.
4579 return CodeCompleteObjCInstanceMessage(S, 0,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004580 SelIdents, NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004581 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004582 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004583 }
4584
4585 // Fall through to send to the superclass in CDecl.
4586 } else {
4587 // "super" may be the name of a type or variable. Figure out which
4588 // it is.
4589 IdentifierInfo *Super = &Context.Idents.get("super");
4590 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
4591 LookupOrdinaryName);
4592 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
4593 // "super" names an interface. Use it.
4594 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00004595 if (const ObjCObjectType *Iface
4596 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
4597 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00004598 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
4599 // "super" names an unresolved type; we can't be more specific.
4600 } else {
4601 // Assume that "super" names some kind of value and parse that way.
4602 CXXScopeSpec SS;
4603 UnqualifiedId id;
4604 id.setIdentifier(Super, SuperLoc);
John McCall60d7b3a2010-08-24 06:29:42 +00004605 ExprResult SuperExpr = ActOnIdExpression(S, SS, id, false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004606 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004607 SelIdents, NumSelIdents,
4608 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004609 }
4610
4611 // Fall through
4612 }
4613
John McCallb3d87482010-08-24 05:47:05 +00004614 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00004615 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00004616 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00004617 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004618 NumSelIdents, AtArgumentExpression,
4619 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004620}
4621
Douglas Gregorb9d77572010-09-21 00:03:25 +00004622/// \brief Given a set of code-completion results for the argument of a message
4623/// send, determine the preferred type (if any) for that argument expression.
4624static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
4625 unsigned NumSelIdents) {
4626 typedef CodeCompletionResult Result;
4627 ASTContext &Context = Results.getSema().Context;
4628
4629 QualType PreferredType;
4630 unsigned BestPriority = CCP_Unlikely * 2;
4631 Result *ResultsData = Results.data();
4632 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
4633 Result &R = ResultsData[I];
4634 if (R.Kind == Result::RK_Declaration &&
4635 isa<ObjCMethodDecl>(R.Declaration)) {
4636 if (R.Priority <= BestPriority) {
4637 ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
4638 if (NumSelIdents <= Method->param_size()) {
4639 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
4640 ->getType();
4641 if (R.Priority < BestPriority || PreferredType.isNull()) {
4642 BestPriority = R.Priority;
4643 PreferredType = MyPreferredType;
4644 } else if (!Context.hasSameUnqualifiedType(PreferredType,
4645 MyPreferredType)) {
4646 PreferredType = QualType();
4647 }
4648 }
4649 }
4650 }
4651 }
4652
4653 return PreferredType;
4654}
4655
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004656static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
4657 ParsedType Receiver,
4658 IdentifierInfo **SelIdents,
4659 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004660 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004661 bool IsSuper,
4662 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00004663 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00004664 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004665
Douglas Gregor24a069f2009-11-17 17:59:40 +00004666 // If the given name refers to an interface type, retrieve the
4667 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00004668 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004669 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004670 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00004671 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
4672 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00004673 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004674
Douglas Gregor36ecb042009-11-17 23:22:23 +00004675 // Add all of the factory methods in this Objective-C class, its protocols,
4676 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00004677 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004678
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004679 // If this is a send-to-super, try to add the special "super" send
4680 // completion.
4681 if (IsSuper) {
4682 if (ObjCMethodDecl *SuperMethod
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004683 = AddSuperSendCompletion(SemaRef, false, SelIdents, NumSelIdents,
4684 Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004685 Results.Ignore(SuperMethod);
4686 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004687
Douglas Gregor265f7492010-08-27 15:29:55 +00004688 // If we're inside an Objective-C method definition, prefer its selector to
4689 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004690 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00004691 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004692
Douglas Gregord36adf52010-09-16 16:06:31 +00004693 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00004694 if (CDecl)
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004695 AddObjCMethods(CDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004696 SemaRef.CurContext, Selectors, AtArgumentExpression,
4697 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00004698 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00004699 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004700
Douglas Gregor719770d2010-04-06 17:30:22 +00004701 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00004702 // pool from the AST file.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004703 if (SemaRef.ExternalSource) {
4704 for (uint32_t I = 0,
4705 N = SemaRef.ExternalSource->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00004706 I != N; ++I) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004707 Selector Sel = SemaRef.ExternalSource->GetExternalSelector(I);
4708 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00004709 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004710
4711 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00004712 }
4713 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004714
4715 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
4716 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00004717 M != MEnd; ++M) {
4718 for (ObjCMethodList *MethList = &M->second.second;
4719 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00004720 MethList = MethList->Next) {
4721 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
4722 NumSelIdents))
4723 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004724
Douglas Gregor13438f92010-04-06 16:40:00 +00004725 Result R(MethList->Method, 0);
4726 R.StartParameter = NumSelIdents;
4727 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004728 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00004729 }
4730 }
4731 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004732
4733 Results.ExitScope();
4734}
Douglas Gregor13438f92010-04-06 16:40:00 +00004735
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004736void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
4737 IdentifierInfo **SelIdents,
4738 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004739 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00004740 bool IsSuper) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004741 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4742 CodeCompletionContext::CCC_Other);
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004743 AddClassMessageCompletions(*this, S, Receiver, SelIdents, NumSelIdents,
4744 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00004745
4746 // If we're actually at the argument expression (rather than prior to the
4747 // selector), we're actually performing code completion for an expression.
4748 // Determine whether we have a single, best method. If so, we can
4749 // code-complete the expression using the corresponding parameter type as
4750 // our preferred type, improving completion results.
4751 if (AtArgumentExpression) {
4752 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
4753 NumSelIdents);
4754 if (PreferredType.isNull())
4755 CodeCompleteOrdinaryName(S, PCC_Expression);
4756 else
4757 CodeCompleteExpression(S, PreferredType);
4758 return;
4759 }
4760
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004761 HandleCodeCompleteResults(this, CodeCompleter,
4762 CodeCompletionContext::CCC_Other,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004763 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00004764}
4765
Douglas Gregord3c68542009-11-19 01:08:35 +00004766void Sema::CodeCompleteObjCInstanceMessage(Scope *S, ExprTy *Receiver,
4767 IdentifierInfo **SelIdents,
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004768 unsigned NumSelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00004769 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004770 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00004771 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00004772
4773 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00004774
Douglas Gregor36ecb042009-11-17 23:22:23 +00004775 // If necessary, apply function/array conversion to the receiver.
4776 // C99 6.7.5.3p[7,8].
Douglas Gregor78edf512010-09-15 16:23:04 +00004777 if (RecExpr)
4778 DefaultFunctionArrayLvalueConversion(RecExpr);
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004779 QualType ReceiverType = RecExpr? RecExpr->getType()
4780 : Super? Context.getObjCObjectPointerType(
4781 Context.getObjCInterfaceType(Super))
4782 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00004783
Douglas Gregorda892642010-11-08 21:12:30 +00004784 // If we're messaging an expression with type "id" or "Class", check
4785 // whether we know something special about the receiver that allows
4786 // us to assume a more-specific receiver type.
4787 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
4788 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
4789 if (ReceiverType->isObjCClassType())
4790 return CodeCompleteObjCClassMessage(S,
4791 ParsedType::make(Context.getObjCInterfaceType(IFace)),
4792 SelIdents, NumSelIdents,
4793 AtArgumentExpression, Super);
4794
4795 ReceiverType = Context.getObjCObjectPointerType(
4796 Context.getObjCInterfaceType(IFace));
4797 }
4798
Douglas Gregor36ecb042009-11-17 23:22:23 +00004799 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00004800 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4801 CodeCompletionContext::CCC_Other);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004802 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00004803
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004804 // If this is a send-to-super, try to add the special "super" send
4805 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00004806 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00004807 if (ObjCMethodDecl *SuperMethod
4808 = AddSuperSendCompletion(*this, false, SelIdents, NumSelIdents,
4809 Results))
4810 Results.Ignore(SuperMethod);
4811 }
4812
Douglas Gregor265f7492010-08-27 15:29:55 +00004813 // If we're inside an Objective-C method definition, prefer its selector to
4814 // others.
4815 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
4816 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004817
Douglas Gregord36adf52010-09-16 16:06:31 +00004818 // Keep track of the selectors we've already added.
4819 VisitedSelectorSet Selectors;
4820
Douglas Gregorf74a4192009-11-18 00:06:18 +00004821 // Handle messages to Class. This really isn't a message to an instance
4822 // method, so we treat it the same way we would treat a message send to a
4823 // class method.
4824 if (ReceiverType->isObjCClassType() ||
4825 ReceiverType->isObjCQualifiedClassType()) {
4826 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
4827 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004828 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, NumSelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004829 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004830 }
4831 }
4832 // Handle messages to a qualified ID ("id<foo>").
4833 else if (const ObjCObjectPointerType *QualID
4834 = ReceiverType->getAsObjCQualifiedIdType()) {
4835 // Search protocols for instance methods.
4836 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
4837 E = QualID->qual_end();
4838 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004839 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004840 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004841 }
4842 // Handle messages to a pointer to interface type.
4843 else if (const ObjCObjectPointerType *IFacePtr
4844 = ReceiverType->getAsObjCInterfacePointerType()) {
4845 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004846 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004847 NumSelIdents, CurContext, Selectors, AtArgumentExpression,
4848 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004849
4850 // Search protocols for instance methods.
4851 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
4852 E = IFacePtr->qual_end();
4853 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004854 AddObjCMethods(*I, true, MK_Any, SelIdents, NumSelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004855 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00004856 }
Douglas Gregor13438f92010-04-06 16:40:00 +00004857 // Handle messages to "id".
4858 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00004859 // We're messaging "id", so provide all instance methods we know
4860 // about as code-completion results.
4861
4862 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00004863 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00004864 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00004865 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
4866 I != N; ++I) {
4867 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00004868 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00004869 continue;
4870
Sebastian Redldb9d2142010-08-02 23:18:59 +00004871 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00004872 }
4873 }
4874
Sebastian Redldb9d2142010-08-02 23:18:59 +00004875 for (GlobalMethodPool::iterator M = MethodPool.begin(),
4876 MEnd = MethodPool.end();
4877 M != MEnd; ++M) {
4878 for (ObjCMethodList *MethList = &M->second.first;
4879 MethList && MethList->Method;
Douglas Gregor13438f92010-04-06 16:40:00 +00004880 MethList = MethList->Next) {
4881 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
4882 NumSelIdents))
4883 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00004884
4885 if (!Selectors.insert(MethList->Method->getSelector()))
4886 continue;
4887
Douglas Gregor13438f92010-04-06 16:40:00 +00004888 Result R(MethList->Method, 0);
4889 R.StartParameter = NumSelIdents;
4890 R.AllParametersAreInformative = false;
4891 Results.MaybeAddResult(R, CurContext);
4892 }
4893 }
4894 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00004895 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00004896
4897
4898 // If we're actually at the argument expression (rather than prior to the
4899 // selector), we're actually performing code completion for an expression.
4900 // Determine whether we have a single, best method. If so, we can
4901 // code-complete the expression using the corresponding parameter type as
4902 // our preferred type, improving completion results.
4903 if (AtArgumentExpression) {
4904 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
4905 NumSelIdents);
4906 if (PreferredType.isNull())
4907 CodeCompleteOrdinaryName(S, PCC_Expression);
4908 else
4909 CodeCompleteExpression(S, PreferredType);
4910 return;
4911 }
4912
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004913 HandleCodeCompleteResults(this, CodeCompleter,
4914 CodeCompletionContext::CCC_Other,
4915 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00004916}
Douglas Gregor55385fe2009-11-18 04:19:12 +00004917
Douglas Gregorfb629412010-08-23 21:17:50 +00004918void Sema::CodeCompleteObjCForCollection(Scope *S,
4919 DeclGroupPtrTy IterationVar) {
4920 CodeCompleteExpressionData Data;
4921 Data.ObjCCollection = true;
4922
4923 if (IterationVar.getAsOpaquePtr()) {
4924 DeclGroupRef DG = IterationVar.getAsVal<DeclGroupRef>();
4925 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
4926 if (*I)
4927 Data.IgnoreDecls.push_back(*I);
4928 }
4929 }
4930
4931 CodeCompleteExpression(S, Data);
4932}
4933
Douglas Gregor458433d2010-08-26 15:07:07 +00004934void Sema::CodeCompleteObjCSelector(Scope *S, IdentifierInfo **SelIdents,
4935 unsigned NumSelIdents) {
4936 // If we have an external source, load the entire class method
4937 // pool from the AST file.
4938 if (ExternalSource) {
4939 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
4940 I != N; ++I) {
4941 Selector Sel = ExternalSource->GetExternalSelector(I);
4942 if (Sel.isNull() || MethodPool.count(Sel))
4943 continue;
4944
4945 ReadMethodPool(Sel);
4946 }
4947 }
4948
Douglas Gregor218937c2011-02-01 19:23:04 +00004949 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4950 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00004951 Results.EnterNewScope();
4952 for (GlobalMethodPool::iterator M = MethodPool.begin(),
4953 MEnd = MethodPool.end();
4954 M != MEnd; ++M) {
4955
4956 Selector Sel = M->first;
4957 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents, NumSelIdents))
4958 continue;
4959
Douglas Gregor218937c2011-02-01 19:23:04 +00004960 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor458433d2010-08-26 15:07:07 +00004961 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00004962 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004963 Sel.getIdentifierInfoForSlot(0)->getName()));
4964 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00004965 continue;
4966 }
4967
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00004968 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00004969 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00004970 if (I == NumSelIdents) {
4971 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00004972 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004973 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00004974 Accumulator.clear();
4975 }
4976 }
4977
4978 Accumulator += Sel.getIdentifierInfoForSlot(I)->getName().str();
4979 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00004980 }
Douglas Gregordae68752011-02-01 22:57:45 +00004981 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00004982 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00004983 }
4984 Results.ExitScope();
4985
4986 HandleCodeCompleteResults(this, CodeCompleter,
4987 CodeCompletionContext::CCC_SelectorName,
4988 Results.data(), Results.size());
4989}
4990
Douglas Gregor55385fe2009-11-18 04:19:12 +00004991/// \brief Add all of the protocol declarations that we find in the given
4992/// (translation unit) context.
4993static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00004994 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00004995 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00004996 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00004997
4998 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
4999 DEnd = Ctx->decls_end();
5000 D != DEnd; ++D) {
5001 // Record any protocols we find.
5002 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor083128f2009-11-18 04:49:41 +00005003 if (!OnlyForwardDeclarations || Proto->isForwardDecl())
Douglas Gregor608300b2010-01-14 16:14:35 +00005004 Results.AddResult(Result(Proto, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005005
5006 // Record any forward-declared protocols we find.
5007 if (ObjCForwardProtocolDecl *Forward
5008 = dyn_cast<ObjCForwardProtocolDecl>(*D)) {
5009 for (ObjCForwardProtocolDecl::protocol_iterator
5010 P = Forward->protocol_begin(),
5011 PEnd = Forward->protocol_end();
5012 P != PEnd; ++P)
Douglas Gregor083128f2009-11-18 04:49:41 +00005013 if (!OnlyForwardDeclarations || (*P)->isForwardDecl())
Douglas Gregor608300b2010-01-14 16:14:35 +00005014 Results.AddResult(Result(*P, 0), CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005015 }
5016 }
5017}
5018
5019void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5020 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005021 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5022 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005023
Douglas Gregor70c23352010-12-09 21:44:02 +00005024 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5025 Results.EnterNewScope();
5026
5027 // Tell the result set to ignore all of the protocols we have
5028 // already seen.
5029 // FIXME: This doesn't work when caching code-completion results.
5030 for (unsigned I = 0; I != NumProtocols; ++I)
5031 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5032 Protocols[I].second))
5033 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005034
Douglas Gregor70c23352010-12-09 21:44:02 +00005035 // Add all protocols.
5036 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5037 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005038
Douglas Gregor70c23352010-12-09 21:44:02 +00005039 Results.ExitScope();
5040 }
5041
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005042 HandleCodeCompleteResults(this, CodeCompleter,
5043 CodeCompletionContext::CCC_ObjCProtocolName,
5044 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005045}
5046
5047void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005048 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5049 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005050
Douglas Gregor70c23352010-12-09 21:44:02 +00005051 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5052 Results.EnterNewScope();
5053
5054 // Add all protocols.
5055 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5056 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005057
Douglas Gregor70c23352010-12-09 21:44:02 +00005058 Results.ExitScope();
5059 }
5060
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005061 HandleCodeCompleteResults(this, CodeCompleter,
5062 CodeCompletionContext::CCC_ObjCProtocolName,
5063 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005064}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005065
5066/// \brief Add all of the Objective-C interface declarations that we find in
5067/// the given (translation unit) context.
5068static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5069 bool OnlyForwardDeclarations,
5070 bool OnlyUnimplemented,
5071 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005072 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005073
5074 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5075 DEnd = Ctx->decls_end();
5076 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005077 // Record any interfaces we find.
5078 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
5079 if ((!OnlyForwardDeclarations || Class->isForwardDecl()) &&
5080 (!OnlyUnimplemented || !Class->getImplementation()))
5081 Results.AddResult(Result(Class, 0), CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005082
5083 // Record any forward-declared interfaces we find.
5084 if (ObjCClassDecl *Forward = dyn_cast<ObjCClassDecl>(*D)) {
5085 for (ObjCClassDecl::iterator C = Forward->begin(), CEnd = Forward->end();
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005086 C != CEnd; ++C)
5087 if ((!OnlyForwardDeclarations || C->getInterface()->isForwardDecl()) &&
5088 (!OnlyUnimplemented || !C->getInterface()->getImplementation()))
5089 Results.AddResult(Result(C->getInterface(), 0), CurContext,
Douglas Gregor608300b2010-01-14 16:14:35 +00005090 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005091 }
5092 }
5093}
5094
5095void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005096 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5097 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005098 Results.EnterNewScope();
5099
5100 // Add all classes.
5101 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, true,
5102 false, Results);
5103
5104 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005105 // FIXME: Add a special context for this, use cached global completion
5106 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005107 HandleCodeCompleteResults(this, CodeCompleter,
5108 CodeCompletionContext::CCC_Other,
5109 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005110}
5111
Douglas Gregorc83c6872010-04-15 22:33:43 +00005112void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5113 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005114 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5115 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005116 Results.EnterNewScope();
5117
5118 // Make sure that we ignore the class we're currently defining.
5119 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005120 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005121 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005122 Results.Ignore(CurClass);
5123
5124 // Add all classes.
5125 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5126 false, Results);
5127
5128 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005129 // FIXME: Add a special context for this, use cached global completion
5130 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005131 HandleCodeCompleteResults(this, CodeCompleter,
5132 CodeCompletionContext::CCC_Other,
5133 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005134}
5135
5136void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005137 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5138 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005139 Results.EnterNewScope();
5140
5141 // Add all unimplemented classes.
5142 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5143 true, Results);
5144
5145 Results.ExitScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00005146 // FIXME: Add a special context for this, use cached global completion
5147 // results.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005148 HandleCodeCompleteResults(this, CodeCompleter,
5149 CodeCompletionContext::CCC_Other,
5150 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005151}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005152
5153void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005154 IdentifierInfo *ClassName,
5155 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005156 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005157
Douglas Gregor218937c2011-02-01 19:23:04 +00005158 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5159 CodeCompletionContext::CCC_Other);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005160
5161 // Ignore any categories we find that have already been implemented by this
5162 // interface.
5163 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5164 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005165 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005166 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass))
5167 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5168 Category = Category->getNextClassCategory())
5169 CategoryNames.insert(Category->getIdentifier());
5170
5171 // Add all of the categories we know about.
5172 Results.EnterNewScope();
5173 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5174 for (DeclContext::decl_iterator D = TU->decls_begin(),
5175 DEnd = TU->decls_end();
5176 D != DEnd; ++D)
5177 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5178 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005179 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005180 Results.ExitScope();
5181
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005182 HandleCodeCompleteResults(this, CodeCompleter,
5183 CodeCompletionContext::CCC_Other,
5184 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005185}
5186
5187void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005188 IdentifierInfo *ClassName,
5189 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005190 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005191
5192 // Find the corresponding interface. If we couldn't find the interface, the
5193 // program itself is ill-formed. However, we'll try to be helpful still by
5194 // providing the list of all of the categories we know about.
5195 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005196 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005197 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5198 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005199 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005200
Douglas Gregor218937c2011-02-01 19:23:04 +00005201 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5202 CodeCompletionContext::CCC_Other);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005203
5204 // Add all of the categories that have have corresponding interface
5205 // declarations in this class and any of its superclasses, except for
5206 // already-implemented categories in the class itself.
5207 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5208 Results.EnterNewScope();
5209 bool IgnoreImplemented = true;
5210 while (Class) {
5211 for (ObjCCategoryDecl *Category = Class->getCategoryList(); Category;
5212 Category = Category->getNextClassCategory())
5213 if ((!IgnoreImplemented || !Category->getImplementation()) &&
5214 CategoryNames.insert(Category->getIdentifier()))
Douglas Gregor608300b2010-01-14 16:14:35 +00005215 Results.AddResult(Result(Category, 0), CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005216
5217 Class = Class->getSuperClass();
5218 IgnoreImplemented = false;
5219 }
5220 Results.ExitScope();
5221
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005222 HandleCodeCompleteResults(this, CodeCompleter,
5223 CodeCompletionContext::CCC_Other,
5224 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005225}
Douglas Gregor322328b2009-11-18 22:32:06 +00005226
John McCalld226f652010-08-21 09:40:31 +00005227void Sema::CodeCompleteObjCPropertyDefinition(Scope *S, Decl *ObjCImpDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00005228 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005229 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5230 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005231
5232 // Figure out where this @synthesize lives.
5233 ObjCContainerDecl *Container
John McCalld226f652010-08-21 09:40:31 +00005234 = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
Douglas Gregor322328b2009-11-18 22:32:06 +00005235 if (!Container ||
5236 (!isa<ObjCImplementationDecl>(Container) &&
5237 !isa<ObjCCategoryImplDecl>(Container)))
5238 return;
5239
5240 // Ignore any properties that have already been implemented.
5241 for (DeclContext::decl_iterator D = Container->decls_begin(),
5242 DEnd = Container->decls_end();
5243 D != DEnd; ++D)
5244 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5245 Results.Ignore(PropertyImpl->getPropertyDecl());
5246
5247 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00005248 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00005249 Results.EnterNewScope();
5250 if (ObjCImplementationDecl *ClassImpl
5251 = dyn_cast<ObjCImplementationDecl>(Container))
5252 AddObjCProperties(ClassImpl->getClassInterface(), false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00005253 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005254 else
5255 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor73449212010-12-09 23:01:55 +00005256 false, CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00005257 Results.ExitScope();
5258
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005259 HandleCodeCompleteResults(this, CodeCompleter,
5260 CodeCompletionContext::CCC_Other,
5261 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005262}
5263
5264void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
5265 IdentifierInfo *PropertyName,
John McCalld226f652010-08-21 09:40:31 +00005266 Decl *ObjCImpDecl) {
John McCall0a2c5e22010-08-25 06:19:51 +00005267 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005268 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5269 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005270
5271 // Figure out where this @synthesize lives.
5272 ObjCContainerDecl *Container
John McCalld226f652010-08-21 09:40:31 +00005273 = dyn_cast_or_null<ObjCContainerDecl>(ObjCImpDecl);
Douglas Gregor322328b2009-11-18 22:32:06 +00005274 if (!Container ||
5275 (!isa<ObjCImplementationDecl>(Container) &&
5276 !isa<ObjCCategoryImplDecl>(Container)))
5277 return;
5278
5279 // Figure out which interface we're looking into.
5280 ObjCInterfaceDecl *Class = 0;
5281 if (ObjCImplementationDecl *ClassImpl
5282 = dyn_cast<ObjCImplementationDecl>(Container))
5283 Class = ClassImpl->getClassInterface();
5284 else
5285 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
5286 ->getClassInterface();
5287
5288 // Add all of the instance variables in this class and its superclasses.
5289 Results.EnterNewScope();
5290 for(; Class; Class = Class->getSuperClass()) {
5291 // FIXME: We could screen the type of each ivar for compatibility with
5292 // the property, but is that being too paternal?
5293 for (ObjCInterfaceDecl::ivar_iterator IVar = Class->ivar_begin(),
5294 IVarEnd = Class->ivar_end();
5295 IVar != IVarEnd; ++IVar)
Douglas Gregor608300b2010-01-14 16:14:35 +00005296 Results.AddResult(Result(*IVar, 0), CurContext, 0, false);
Douglas Gregor322328b2009-11-18 22:32:06 +00005297 }
5298 Results.ExitScope();
5299
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005300 HandleCodeCompleteResults(this, CodeCompleter,
5301 CodeCompletionContext::CCC_Other,
5302 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00005303}
Douglas Gregore8f5a172010-04-07 00:21:17 +00005304
Douglas Gregor408be5a2010-08-25 01:08:01 +00005305// Mapping from selectors to the methods that implement that selector, along
5306// with the "in original class" flag.
5307typedef llvm::DenseMap<Selector, std::pair<ObjCMethodDecl *, bool> >
5308 KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005309
5310/// \brief Find all of the methods that reside in the given container
5311/// (and its superclasses, protocols, etc.) that meet the given
5312/// criteria. Insert those methods into the map of known methods,
5313/// indexed by selector so they can be easily found.
5314static void FindImplementableMethods(ASTContext &Context,
5315 ObjCContainerDecl *Container,
5316 bool WantInstanceMethods,
5317 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00005318 KnownMethodsMap &KnownMethods,
5319 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005320 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
5321 // Recurse into protocols.
5322 const ObjCList<ObjCProtocolDecl> &Protocols
5323 = IFace->getReferencedProtocols();
5324 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005325 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005326 I != E; ++I)
5327 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005328 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005329
Douglas Gregorea766182010-10-18 18:21:28 +00005330 // Add methods from any class extensions and categories.
5331 for (const ObjCCategoryDecl *Cat = IFace->getCategoryList(); Cat;
5332 Cat = Cat->getNextClassCategory())
Fariborz Jahanian80aa1cd2010-06-22 23:20:40 +00005333 FindImplementableMethods(Context, const_cast<ObjCCategoryDecl*>(Cat),
5334 WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005335 KnownMethods, false);
5336
5337 // Visit the superclass.
5338 if (IFace->getSuperClass())
5339 FindImplementableMethods(Context, IFace->getSuperClass(),
5340 WantInstanceMethods, ReturnType,
5341 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005342 }
5343
5344 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
5345 // Recurse into protocols.
5346 const ObjCList<ObjCProtocolDecl> &Protocols
5347 = Category->getReferencedProtocols();
5348 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00005349 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005350 I != E; ++I)
5351 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005352 KnownMethods, InOriginalClass);
5353
5354 // If this category is the original class, jump to the interface.
5355 if (InOriginalClass && Category->getClassInterface())
5356 FindImplementableMethods(Context, Category->getClassInterface(),
5357 WantInstanceMethods, ReturnType, KnownMethods,
5358 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005359 }
5360
5361 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
5362 // Recurse into protocols.
5363 const ObjCList<ObjCProtocolDecl> &Protocols
5364 = Protocol->getReferencedProtocols();
5365 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5366 E = Protocols.end();
5367 I != E; ++I)
5368 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00005369 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005370 }
5371
5372 // Add methods in this container. This operation occurs last because
5373 // we want the methods from this container to override any methods
5374 // we've previously seen with the same selector.
5375 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
5376 MEnd = Container->meth_end();
5377 M != MEnd; ++M) {
5378 if ((*M)->isInstanceMethod() == WantInstanceMethods) {
5379 if (!ReturnType.isNull() &&
5380 !Context.hasSameUnqualifiedType(ReturnType, (*M)->getResultType()))
5381 continue;
5382
Douglas Gregor408be5a2010-08-25 01:08:01 +00005383 KnownMethods[(*M)->getSelector()] = std::make_pair(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005384 }
5385 }
5386}
5387
5388void Sema::CodeCompleteObjCMethodDecl(Scope *S,
5389 bool IsInstanceMethod,
John McCallb3d87482010-08-24 05:47:05 +00005390 ParsedType ReturnTy,
John McCalld226f652010-08-21 09:40:31 +00005391 Decl *IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005392 // Determine the return type of the method we're declaring, if
5393 // provided.
5394 QualType ReturnType = GetTypeFromParser(ReturnTy);
5395
Douglas Gregorea766182010-10-18 18:21:28 +00005396 // Determine where we should start searching for methods.
5397 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00005398 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00005399 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005400 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
5401 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005402 IsInImplementation = true;
5403 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00005404 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005405 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00005406 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00005407 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00005408 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005409 }
5410
5411 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00005412 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00005413 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005414 }
5415
Douglas Gregorea766182010-10-18 18:21:28 +00005416 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005417 HandleCodeCompleteResults(this, CodeCompleter,
5418 CodeCompletionContext::CCC_Other,
5419 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005420 return;
5421 }
5422
5423 // Find all of the methods that we could declare/implement here.
5424 KnownMethodsMap KnownMethods;
5425 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00005426 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005427
Douglas Gregore8f5a172010-04-07 00:21:17 +00005428 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00005429 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005430 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5431 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005432 Results.EnterNewScope();
5433 PrintingPolicy Policy(Context.PrintingPolicy);
5434 Policy.AnonymousTagLocations = false;
5435 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
5436 MEnd = KnownMethods.end();
5437 M != MEnd; ++M) {
Douglas Gregor408be5a2010-08-25 01:08:01 +00005438 ObjCMethodDecl *Method = M->second.first;
Douglas Gregor218937c2011-02-01 19:23:04 +00005439 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregore8f5a172010-04-07 00:21:17 +00005440
5441 // If the result type was not already provided, add it to the
5442 // pattern as (type).
5443 if (ReturnType.isNull()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005444 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregora63f6de2011-02-01 21:15:40 +00005445 Builder.AddTextChunk(GetCompletionTypeString(Method->getResultType(),
5446 Context,
5447 Builder.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00005448 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005449 }
5450
5451 Selector Sel = Method->getSelector();
5452
5453 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00005454 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005455 Sel.getIdentifierInfoForSlot(0)->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005456
5457 // Add parameters to the pattern.
5458 unsigned I = 0;
5459 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
5460 PEnd = Method->param_end();
5461 P != PEnd; (void)++P, ++I) {
5462 // Add the part of the selector name.
5463 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00005464 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00005465 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005466 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5467 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005468 Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005469 (Sel.getIdentifierInfoForSlot(I)->getName()
5470 + ":").str()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005471 } else
5472 break;
5473
5474 // Add the parameter type.
Douglas Gregor218937c2011-02-01 19:23:04 +00005475 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregora63f6de2011-02-01 21:15:40 +00005476 Builder.AddTextChunk(GetCompletionTypeString((*P)->getOriginalType(),
5477 Context,
5478 Builder.getAllocator()));
Douglas Gregor218937c2011-02-01 19:23:04 +00005479 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005480
5481 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00005482 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005483 }
5484
5485 if (Method->isVariadic()) {
5486 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00005487 Builder.AddChunk(CodeCompletionString::CK_Comma);
5488 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00005489 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00005490
Douglas Gregor447107d2010-05-28 00:57:46 +00005491 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00005492 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00005493 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5494 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5495 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005496 if (!Method->getResultType()->isVoidType()) {
5497 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00005498 Builder.AddTextChunk("return");
5499 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5500 Builder.AddPlaceholderChunk("expression");
5501 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005502 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00005503 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00005504
Douglas Gregor218937c2011-02-01 19:23:04 +00005505 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
5506 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00005507 }
5508
Douglas Gregor408be5a2010-08-25 01:08:01 +00005509 unsigned Priority = CCP_CodePattern;
5510 if (!M->second.second)
5511 Priority += CCD_InBaseClass;
5512
Douglas Gregor218937c2011-02-01 19:23:04 +00005513 Results.AddResult(Result(Builder.TakeString(), Priority,
Douglas Gregor16ed9ad2010-08-17 16:06:07 +00005514 Method->isInstanceMethod()
5515 ? CXCursor_ObjCInstanceMethodDecl
5516 : CXCursor_ObjCClassMethodDecl));
Douglas Gregore8f5a172010-04-07 00:21:17 +00005517 }
5518
5519 Results.ExitScope();
5520
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005521 HandleCodeCompleteResults(this, CodeCompleter,
5522 CodeCompletionContext::CCC_Other,
5523 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00005524}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005525
5526void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
5527 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00005528 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00005529 ParsedType ReturnTy,
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005530 IdentifierInfo **SelIdents,
5531 unsigned NumSelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005532 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005533 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005534 if (ExternalSource) {
5535 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5536 I != N; ++I) {
5537 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005538 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005539 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00005540
5541 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005542 }
5543 }
5544
5545 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00005546 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005547 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
5548 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005549
5550 if (ReturnTy)
5551 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00005552
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005553 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005554 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5555 MEnd = MethodPool.end();
5556 M != MEnd; ++M) {
5557 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
5558 &M->second.second;
5559 MethList && MethList->Method;
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005560 MethList = MethList->Next) {
5561 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents,
5562 NumSelIdents))
5563 continue;
5564
Douglas Gregor40ed9a12010-07-08 23:37:41 +00005565 if (AtParameterName) {
5566 // Suggest parameter names we've seen before.
5567 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
5568 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
5569 if (Param->getIdentifier()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005570 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregordae68752011-02-01 22:57:45 +00005571 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005572 Param->getIdentifier()->getName()));
5573 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00005574 }
5575 }
5576
5577 continue;
5578 }
5579
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005580 Result R(MethList->Method, 0);
5581 R.StartParameter = NumSelIdents;
5582 R.AllParametersAreInformative = false;
5583 R.DeclaringEntity = true;
5584 Results.MaybeAddResult(R, CurContext);
5585 }
5586 }
5587
5588 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005589 HandleCodeCompleteResults(this, CodeCompleter,
5590 CodeCompletionContext::CCC_Other,
5591 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00005592}
Douglas Gregor87c08a52010-08-13 22:48:40 +00005593
Douglas Gregorf29c5232010-08-24 22:20:20 +00005594void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005595 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00005596 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00005597 Results.EnterNewScope();
5598
5599 // #if <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00005600 CodeCompletionBuilder Builder(Results.getAllocator());
5601 Builder.AddTypedTextChunk("if");
5602 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5603 Builder.AddPlaceholderChunk("condition");
5604 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005605
5606 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005607 Builder.AddTypedTextChunk("ifdef");
5608 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5609 Builder.AddPlaceholderChunk("macro");
5610 Results.AddResult(Builder.TakeString());
5611
Douglas Gregorf44e8542010-08-24 19:08:16 +00005612 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005613 Builder.AddTypedTextChunk("ifndef");
5614 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5615 Builder.AddPlaceholderChunk("macro");
5616 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005617
5618 if (InConditional) {
5619 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00005620 Builder.AddTypedTextChunk("elif");
5621 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5622 Builder.AddPlaceholderChunk("condition");
5623 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005624
5625 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00005626 Builder.AddTypedTextChunk("else");
5627 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005628
5629 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00005630 Builder.AddTypedTextChunk("endif");
5631 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005632 }
5633
5634 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00005635 Builder.AddTypedTextChunk("include");
5636 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5637 Builder.AddTextChunk("\"");
5638 Builder.AddPlaceholderChunk("header");
5639 Builder.AddTextChunk("\"");
5640 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005641
5642 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00005643 Builder.AddTypedTextChunk("include");
5644 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5645 Builder.AddTextChunk("<");
5646 Builder.AddPlaceholderChunk("header");
5647 Builder.AddTextChunk(">");
5648 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005649
5650 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005651 Builder.AddTypedTextChunk("define");
5652 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5653 Builder.AddPlaceholderChunk("macro");
5654 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005655
5656 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00005657 Builder.AddTypedTextChunk("define");
5658 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5659 Builder.AddPlaceholderChunk("macro");
5660 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5661 Builder.AddPlaceholderChunk("args");
5662 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5663 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005664
5665 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00005666 Builder.AddTypedTextChunk("undef");
5667 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5668 Builder.AddPlaceholderChunk("macro");
5669 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005670
5671 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00005672 Builder.AddTypedTextChunk("line");
5673 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5674 Builder.AddPlaceholderChunk("number");
5675 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005676
5677 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00005678 Builder.AddTypedTextChunk("line");
5679 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5680 Builder.AddPlaceholderChunk("number");
5681 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5682 Builder.AddTextChunk("\"");
5683 Builder.AddPlaceholderChunk("filename");
5684 Builder.AddTextChunk("\"");
5685 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005686
5687 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00005688 Builder.AddTypedTextChunk("error");
5689 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5690 Builder.AddPlaceholderChunk("message");
5691 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005692
5693 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00005694 Builder.AddTypedTextChunk("pragma");
5695 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5696 Builder.AddPlaceholderChunk("arguments");
5697 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005698
5699 if (getLangOptions().ObjC1) {
5700 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00005701 Builder.AddTypedTextChunk("import");
5702 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5703 Builder.AddTextChunk("\"");
5704 Builder.AddPlaceholderChunk("header");
5705 Builder.AddTextChunk("\"");
5706 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005707
5708 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00005709 Builder.AddTypedTextChunk("import");
5710 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5711 Builder.AddTextChunk("<");
5712 Builder.AddPlaceholderChunk("header");
5713 Builder.AddTextChunk(">");
5714 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005715 }
5716
5717 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00005718 Builder.AddTypedTextChunk("include_next");
5719 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5720 Builder.AddTextChunk("\"");
5721 Builder.AddPlaceholderChunk("header");
5722 Builder.AddTextChunk("\"");
5723 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005724
5725 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00005726 Builder.AddTypedTextChunk("include_next");
5727 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5728 Builder.AddTextChunk("<");
5729 Builder.AddPlaceholderChunk("header");
5730 Builder.AddTextChunk(">");
5731 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005732
5733 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00005734 Builder.AddTypedTextChunk("warning");
5735 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5736 Builder.AddPlaceholderChunk("message");
5737 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00005738
5739 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
5740 // completions for them. And __include_macros is a Clang-internal extension
5741 // that we don't want to encourage anyone to use.
5742
5743 // FIXME: we don't support #assert or #unassert, so don't suggest them.
5744 Results.ExitScope();
5745
Douglas Gregorf44e8542010-08-24 19:08:16 +00005746 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00005747 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00005748 Results.data(), Results.size());
5749}
5750
5751void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00005752 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00005753 S->getFnParent()? Sema::PCC_RecoveryInFunction
5754 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00005755}
5756
Douglas Gregorf29c5232010-08-24 22:20:20 +00005757void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005758 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00005759 IsDefinition? CodeCompletionContext::CCC_MacroName
5760 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005761 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
5762 // Add just the names of macros, not their arguments.
Douglas Gregor218937c2011-02-01 19:23:04 +00005763 CodeCompletionBuilder Builder(Results.getAllocator());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005764 Results.EnterNewScope();
5765 for (Preprocessor::macro_iterator M = PP.macro_begin(),
5766 MEnd = PP.macro_end();
5767 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00005768 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005769 M->first->getName()));
5770 Results.AddResult(Builder.TakeString());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005771 }
5772 Results.ExitScope();
5773 } else if (IsDefinition) {
5774 // FIXME: Can we detect when the user just wrote an include guard above?
5775 }
5776
Douglas Gregor52779fb2010-09-23 23:01:17 +00005777 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00005778 Results.data(), Results.size());
5779}
5780
Douglas Gregorf29c5232010-08-24 22:20:20 +00005781void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00005782 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00005783 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00005784
5785 if (!CodeCompleter || CodeCompleter->includeMacros())
5786 AddMacroResults(PP, Results);
5787
5788 // defined (<macro>)
5789 Results.EnterNewScope();
Douglas Gregor218937c2011-02-01 19:23:04 +00005790 CodeCompletionBuilder Builder(Results.getAllocator());
5791 Builder.AddTypedTextChunk("defined");
5792 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5793 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5794 Builder.AddPlaceholderChunk("macro");
5795 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5796 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00005797 Results.ExitScope();
5798
5799 HandleCodeCompleteResults(this, CodeCompleter,
5800 CodeCompletionContext::CCC_PreprocessorExpression,
5801 Results.data(), Results.size());
5802}
5803
5804void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
5805 IdentifierInfo *Macro,
5806 MacroInfo *MacroInfo,
5807 unsigned Argument) {
5808 // FIXME: In the future, we could provide "overload" results, much like we
5809 // do for function calls.
5810
5811 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00005812 S->getFnParent()? Sema::PCC_RecoveryInFunction
5813 : Sema::PCC_Namespace);
Douglas Gregorf29c5232010-08-24 22:20:20 +00005814}
5815
Douglas Gregor55817af2010-08-25 17:04:25 +00005816void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00005817 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00005818 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00005819 0, 0);
5820}
5821
Douglas Gregordae68752011-02-01 22:57:45 +00005822void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
John McCall0a2c5e22010-08-25 06:19:51 +00005823 llvm::SmallVectorImpl<CodeCompletionResult> &Results) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005824 ResultBuilder Builder(*this, Allocator, CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00005825 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
5826 CodeCompletionDeclConsumer Consumer(Builder,
5827 Context.getTranslationUnitDecl());
5828 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
5829 Consumer);
5830 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00005831
5832 if (!CodeCompleter || CodeCompleter->includeMacros())
5833 AddMacroResults(PP, Builder);
5834
5835 Results.clear();
5836 Results.insert(Results.end(),
5837 Builder.data(), Builder.data() + Builder.size());
5838}