blob: 5e084eb5d4142fe9d25d0c84315e65f552a64c84 [file] [log] [blame]
Douglas Gregor81b747b2009-09-17 21:32:03 +00001//===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file defines the code-completion semantic actions.
11//
12//===----------------------------------------------------------------------===//
John McCall2d887082010-08-25 22:03:47 +000013#include "clang/Sema/SemaInternal.h"
John McCall7cd088e2010-08-24 07:21:54 +000014#include "clang/AST/DeclObjC.h"
Douglas Gregorb9d0ef72009-09-21 19:57:38 +000015#include "clang/AST/ExprCXX.h"
Douglas Gregor24a069f2009-11-17 17:59:40 +000016#include "clang/AST/ExprObjC.h"
Jordan Rose223f0ff2013-02-09 10:09:43 +000017#include "clang/Basic/CharInfo.h"
Douglas Gregorc5b2e582012-01-29 18:15:03 +000018#include "clang/Lex/HeaderSearch.h"
Douglas Gregor3f7c7f42009-10-30 16:50:04 +000019#include "clang/Lex/MacroInfo.h"
20#include "clang/Lex/Preprocessor.h"
Chandler Carruth55fc8732012-12-04 09:13:33 +000021#include "clang/Sema/CodeCompleteConsumer.h"
22#include "clang/Sema/ExternalSemaSource.h"
23#include "clang/Sema/Lookup.h"
24#include "clang/Sema/Overload.h"
25#include "clang/Sema/Scope.h"
26#include "clang/Sema/ScopeInfo.h"
Douglas Gregord36adf52010-09-16 16:06:31 +000027#include "llvm/ADT/DenseSet.h"
Benjamin Kramer013b3662012-01-30 16:17:39 +000028#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000029#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer8fe83e12012-02-04 13:45:25 +000030#include "llvm/ADT/SmallString.h"
Douglas Gregor6a684032009-09-28 03:51:44 +000031#include "llvm/ADT/StringExtras.h"
Douglas Gregor22f56992010-04-06 19:22:33 +000032#include "llvm/ADT/StringSwitch.h"
Douglas Gregor458433d2010-08-26 15:07:07 +000033#include "llvm/ADT/Twine.h"
Douglas Gregor86d9a522009-09-21 16:56:56 +000034#include <list>
35#include <map>
36#include <vector>
Douglas Gregor81b747b2009-09-17 21:32:03 +000037
38using namespace clang;
John McCall781472f2010-08-25 08:40:02 +000039using namespace sema;
Douglas Gregor81b747b2009-09-17 21:32:03 +000040
Douglas Gregor86d9a522009-09-21 16:56:56 +000041namespace {
42 /// \brief A container of code-completion results.
43 class ResultBuilder {
44 public:
45 /// \brief The type of a name-lookup filter, which can be provided to the
46 /// name-lookup routines to specify which declarations should be included in
47 /// the result set (when it returns true) and which declarations should be
48 /// filtered out (returns false).
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000049 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +000050
John McCall0a2c5e22010-08-25 06:19:51 +000051 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +000052
53 private:
54 /// \brief The actual results we have found.
55 std::vector<Result> Results;
56
57 /// \brief A record of all of the declarations we have found and placed
58 /// into the result set, used to ensure that no declaration ever gets into
59 /// the result set twice.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000060 llvm::SmallPtrSet<const Decl*, 16> AllDeclsFound;
Douglas Gregor86d9a522009-09-21 16:56:56 +000061
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000062 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000063
64 /// \brief An entry in the shadow map, which is optimized to store
65 /// a single (declaration, index) mapping (the common case) but
66 /// can also store a list of (declaration, index) mappings.
67 class ShadowMapEntry {
Chris Lattner5f9e2722011-07-23 10:55:15 +000068 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000069
70 /// \brief Contains either the solitary NamedDecl * or a vector
71 /// of (declaration, index) pairs.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000072 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector*> DeclOrVector;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000073
74 /// \brief When the entry contains a single declaration, this is
75 /// the index associated with that entry.
76 unsigned SingleDeclIndex;
77
78 public:
79 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) { }
80
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000081 void Add(const NamedDecl *ND, unsigned Index) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000082 if (DeclOrVector.isNull()) {
83 // 0 - > 1 elements: just set the single element information.
84 DeclOrVector = ND;
85 SingleDeclIndex = Index;
86 return;
87 }
88
Dmitri Gribenko89cf4252013-01-23 17:21:11 +000089 if (const NamedDecl *PrevND =
90 DeclOrVector.dyn_cast<const NamedDecl *>()) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +000091 // 1 -> 2 elements: create the vector of results and push in the
92 // existing declaration.
93 DeclIndexPairVector *Vec = new DeclIndexPairVector;
94 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
95 DeclOrVector = Vec;
96 }
97
98 // Add the new element to the end of the vector.
99 DeclOrVector.get<DeclIndexPairVector*>()->push_back(
100 DeclIndexPair(ND, Index));
101 }
102
103 void Destroy() {
104 if (DeclIndexPairVector *Vec
105 = DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
106 delete Vec;
107 DeclOrVector = ((NamedDecl *)0);
108 }
109 }
110
111 // Iteration.
112 class iterator;
113 iterator begin() const;
114 iterator end() const;
115 };
116
Douglas Gregor86d9a522009-09-21 16:56:56 +0000117 /// \brief A mapping from declaration names to the declarations that have
118 /// this name within a particular scope and their index within the list of
119 /// results.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000120 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000121
122 /// \brief The semantic analysis object for which results are being
123 /// produced.
124 Sema &SemaRef;
Douglas Gregor218937c2011-02-01 19:23:04 +0000125
126 /// \brief The allocator used to allocate new code-completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000127 CodeCompletionAllocator &Allocator;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000128
129 CodeCompletionTUInfo &CCTUInfo;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000130
131 /// \brief If non-NULL, a filter function used to remove any code-completion
132 /// results that are not desirable.
133 LookupFilter Filter;
Douglas Gregor45bcd432010-01-14 03:21:49 +0000134
135 /// \brief Whether we should allow declarations as
136 /// nested-name-specifiers that would otherwise be filtered out.
137 bool AllowNestedNameSpecifiers;
138
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000139 /// \brief If set, the type that we would prefer our resulting value
140 /// declarations to have.
141 ///
142 /// Closely matching the preferred type gives a boost to a result's
143 /// priority.
144 CanQualType PreferredType;
145
Douglas Gregor86d9a522009-09-21 16:56:56 +0000146 /// \brief A list of shadow maps, which is used to model name hiding at
147 /// different levels of, e.g., the inheritance hierarchy.
148 std::list<ShadowMap> ShadowMaps;
149
Douglas Gregor3cdee122010-08-26 16:36:48 +0000150 /// \brief If we're potentially referring to a C++ member function, the set
151 /// of qualifiers applied to the object type.
152 Qualifiers ObjectTypeQualifiers;
153
154 /// \brief Whether the \p ObjectTypeQualifiers field is active.
155 bool HasObjectTypeQualifiers;
156
Douglas Gregor265f7492010-08-27 15:29:55 +0000157 /// \brief The selector that we prefer.
158 Selector PreferredSelector;
159
Douglas Gregorca45da02010-11-02 20:36:02 +0000160 /// \brief The completion context in which we are gathering results.
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000161 CodeCompletionContext CompletionContext;
162
James Dennetta40f7922012-06-14 03:11:41 +0000163 /// \brief If we are in an instance method definition, the \@implementation
Douglas Gregorca45da02010-11-02 20:36:02 +0000164 /// object.
165 ObjCImplementationDecl *ObjCImplementation;
Douglas Gregord1f09b42013-01-31 04:52:16 +0000166
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000167 void AdjustResultPriorityForDecl(Result &R);
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000168
Douglas Gregor6f942b22010-09-21 16:06:22 +0000169 void MaybeAddConstructorResults(Result R);
170
Douglas Gregor86d9a522009-09-21 16:56:56 +0000171 public:
Douglas Gregordae68752011-02-01 22:57:45 +0000172 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000173 CodeCompletionTUInfo &CCTUInfo,
Douglas Gregor52779fb2010-09-23 23:01:17 +0000174 const CodeCompletionContext &CompletionContext,
175 LookupFilter Filter = 0)
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000176 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
177 Filter(Filter),
Douglas Gregor218937c2011-02-01 19:23:04 +0000178 AllowNestedNameSpecifiers(false), HasObjectTypeQualifiers(false),
Douglas Gregorca45da02010-11-02 20:36:02 +0000179 CompletionContext(CompletionContext),
180 ObjCImplementation(0)
181 {
182 // If this is an Objective-C instance method definition, dig out the
183 // corresponding implementation.
184 switch (CompletionContext.getKind()) {
185 case CodeCompletionContext::CCC_Expression:
186 case CodeCompletionContext::CCC_ObjCMessageReceiver:
187 case CodeCompletionContext::CCC_ParenthesizedExpression:
188 case CodeCompletionContext::CCC_Statement:
189 case CodeCompletionContext::CCC_Recovery:
190 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
191 if (Method->isInstanceMethod())
192 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
193 ObjCImplementation = Interface->getImplementation();
194 break;
195
196 default:
197 break;
198 }
199 }
Douglas Gregord1f09b42013-01-31 04:52:16 +0000200
201 /// \brief Determine the priority for a reference to the given declaration.
202 unsigned getBasePriority(const NamedDecl *D);
203
Douglas Gregord8e8a582010-05-25 21:41:55 +0000204 /// \brief Whether we should include code patterns in the completion
205 /// results.
206 bool includeCodePatterns() const {
207 return SemaRef.CodeCompleter &&
Douglas Gregorf6961522010-08-27 21:18:54 +0000208 SemaRef.CodeCompleter->includeCodePatterns();
Douglas Gregord8e8a582010-05-25 21:41:55 +0000209 }
210
Douglas Gregor86d9a522009-09-21 16:56:56 +0000211 /// \brief Set the filter used for code-completion results.
212 void setFilter(LookupFilter Filter) {
213 this->Filter = Filter;
214 }
215
Douglas Gregor86d9a522009-09-21 16:56:56 +0000216 Result *data() { return Results.empty()? 0 : &Results.front(); }
217 unsigned size() const { return Results.size(); }
218 bool empty() const { return Results.empty(); }
219
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000220 /// \brief Specify the preferred type.
221 void setPreferredType(QualType T) {
222 PreferredType = SemaRef.Context.getCanonicalType(T);
223 }
224
Douglas Gregor3cdee122010-08-26 16:36:48 +0000225 /// \brief Set the cv-qualifiers on the object type, for us in filtering
226 /// calls to member functions.
227 ///
228 /// When there are qualifiers in this set, they will be used to filter
229 /// out member functions that aren't available (because there will be a
230 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
231 /// match.
232 void setObjectTypeQualifiers(Qualifiers Quals) {
233 ObjectTypeQualifiers = Quals;
234 HasObjectTypeQualifiers = true;
235 }
236
Douglas Gregor265f7492010-08-27 15:29:55 +0000237 /// \brief Set the preferred selector.
238 ///
239 /// When an Objective-C method declaration result is added, and that
240 /// method's selector matches this preferred selector, we give that method
241 /// a slight priority boost.
242 void setPreferredSelector(Selector Sel) {
243 PreferredSelector = Sel;
244 }
Douglas Gregorca45da02010-11-02 20:36:02 +0000245
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000246 /// \brief Retrieve the code-completion context for which results are
247 /// being collected.
248 const CodeCompletionContext &getCompletionContext() const {
249 return CompletionContext;
250 }
251
Douglas Gregor45bcd432010-01-14 03:21:49 +0000252 /// \brief Specify whether nested-name-specifiers are allowed.
253 void allowNestedNameSpecifiers(bool Allow = true) {
254 AllowNestedNameSpecifiers = Allow;
255 }
256
Douglas Gregorb9d77572010-09-21 00:03:25 +0000257 /// \brief Return the semantic analysis object for which we are collecting
258 /// code completion results.
259 Sema &getSema() const { return SemaRef; }
260
Douglas Gregor218937c2011-02-01 19:23:04 +0000261 /// \brief Retrieve the allocator used to allocate code completion strings.
Douglas Gregordae68752011-02-01 22:57:45 +0000262 CodeCompletionAllocator &getAllocator() const { return Allocator; }
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +0000263
264 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
Douglas Gregor218937c2011-02-01 19:23:04 +0000265
Douglas Gregore495b7f2010-01-14 00:20:49 +0000266 /// \brief Determine whether the given declaration is at all interesting
267 /// as a code-completion result.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000268 ///
269 /// \param ND the declaration that we are inspecting.
270 ///
271 /// \param AsNestedNameSpecifier will be set true if this declaration is
272 /// only interesting when it is a nested-name-specifier.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000273 bool isInterestingDecl(const NamedDecl *ND,
274 bool &AsNestedNameSpecifier) const;
Douglas Gregor6660d842010-01-14 00:41:07 +0000275
276 /// \brief Check whether the result is hidden by the Hiding declaration.
277 ///
278 /// \returns true if the result is hidden and cannot be found, false if
279 /// the hidden result could still be found. When false, \p R may be
280 /// modified to describe how the result can be found (e.g., via extra
281 /// qualification).
282 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000283 const NamedDecl *Hiding);
Douglas Gregor6660d842010-01-14 00:41:07 +0000284
Douglas Gregor86d9a522009-09-21 16:56:56 +0000285 /// \brief Add a new result to this result set (if it isn't already in one
286 /// of the shadow maps), or replace an existing result (for, e.g., a
287 /// redeclaration).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000288 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000289 /// \param R the result to add (if it is unique).
Douglas Gregor456c4a12009-09-21 20:12:40 +0000290 ///
Douglas Gregor81f3bff2012-02-15 15:34:24 +0000291 /// \param CurContext the context in which this result will be named.
Douglas Gregor456c4a12009-09-21 20:12:40 +0000292 void MaybeAddResult(Result R, DeclContext *CurContext = 0);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000293
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000294 /// \brief Add a new result to this result set, where we already know
295 /// the hiding declation (if any).
296 ///
297 /// \param R the result to add (if it is unique).
298 ///
299 /// \param CurContext the context in which this result will be named.
300 ///
301 /// \param Hiding the declaration that hides the result.
Douglas Gregor0cc84042010-01-14 15:47:35 +0000302 ///
303 /// \param InBaseClass whether the result was found in a base
304 /// class of the searched context.
305 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
306 bool InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000307
Douglas Gregora4477812010-01-14 16:01:26 +0000308 /// \brief Add a new non-declaration result to this result set.
309 void AddResult(Result R);
310
Douglas Gregor86d9a522009-09-21 16:56:56 +0000311 /// \brief Enter into a new scope.
312 void EnterNewScope();
313
314 /// \brief Exit from the current scope.
315 void ExitScope();
316
Douglas Gregor55385fe2009-11-18 04:19:12 +0000317 /// \brief Ignore this declaration, if it is seen again.
Dmitri Gribenko68a932d2013-02-14 13:53:30 +0000318 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
Douglas Gregor55385fe2009-11-18 04:19:12 +0000319
Douglas Gregor86d9a522009-09-21 16:56:56 +0000320 /// \name Name lookup predicates
321 ///
322 /// These predicates can be passed to the name lookup functions to filter the
323 /// results of name lookup. All of the predicates have the same type, so that
324 ///
325 //@{
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000326 bool IsOrdinaryName(const NamedDecl *ND) const;
327 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
328 bool IsIntegralConstantValue(const NamedDecl *ND) const;
329 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
330 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
331 bool IsEnum(const NamedDecl *ND) const;
332 bool IsClassOrStruct(const NamedDecl *ND) const;
333 bool IsUnion(const NamedDecl *ND) const;
334 bool IsNamespace(const NamedDecl *ND) const;
335 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
336 bool IsType(const NamedDecl *ND) const;
337 bool IsMember(const NamedDecl *ND) const;
338 bool IsObjCIvar(const NamedDecl *ND) const;
339 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
340 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
341 bool IsObjCCollection(const NamedDecl *ND) const;
342 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000343 //@}
344 };
345}
346
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000347class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000348 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000349 unsigned SingleDeclIndex;
350
351public:
352 typedef DeclIndexPair value_type;
353 typedef value_type reference;
354 typedef std::ptrdiff_t difference_type;
355 typedef std::input_iterator_tag iterator_category;
356
357 class pointer {
358 DeclIndexPair Value;
359
360 public:
361 pointer(const DeclIndexPair &Value) : Value(Value) { }
362
363 const DeclIndexPair *operator->() const {
364 return &Value;
365 }
366 };
367
368 iterator() : DeclOrIterator((NamedDecl *)0), SingleDeclIndex(0) { }
369
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000370 iterator(const NamedDecl *SingleDecl, unsigned Index)
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000371 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) { }
372
373 iterator(const DeclIndexPair *Iterator)
374 : DeclOrIterator(Iterator), SingleDeclIndex(0) { }
375
376 iterator &operator++() {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000377 if (DeclOrIterator.is<const NamedDecl *>()) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000378 DeclOrIterator = (NamedDecl *)0;
379 SingleDeclIndex = 0;
380 return *this;
381 }
382
383 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair*>();
384 ++I;
385 DeclOrIterator = I;
386 return *this;
387 }
388
Chris Lattner66392d42010-09-04 18:12:20 +0000389 /*iterator operator++(int) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000390 iterator tmp(*this);
391 ++(*this);
392 return tmp;
Chris Lattner66392d42010-09-04 18:12:20 +0000393 }*/
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000394
395 reference operator*() const {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000396 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000397 return reference(ND, SingleDeclIndex);
398
Douglas Gregord490f952009-12-06 21:27:58 +0000399 return *DeclOrIterator.get<const DeclIndexPair*>();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000400 }
401
402 pointer operator->() const {
403 return pointer(**this);
404 }
405
406 friend bool operator==(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000407 return X.DeclOrIterator.getOpaqueValue()
408 == Y.DeclOrIterator.getOpaqueValue() &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000409 X.SingleDeclIndex == Y.SingleDeclIndex;
410 }
411
412 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregord490f952009-12-06 21:27:58 +0000413 return !(X == Y);
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000414 }
415};
416
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000417ResultBuilder::ShadowMapEntry::iterator
418ResultBuilder::ShadowMapEntry::begin() const {
419 if (DeclOrVector.isNull())
420 return iterator();
421
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000422 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000423 return iterator(ND, SingleDeclIndex);
424
425 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
426}
427
428ResultBuilder::ShadowMapEntry::iterator
429ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000430 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000431 return iterator();
432
433 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
434}
435
Douglas Gregor456c4a12009-09-21 20:12:40 +0000436/// \brief Compute the qualification required to get from the current context
437/// (\p CurContext) to the target context (\p TargetContext).
438///
439/// \param Context the AST context in which the qualification will be used.
440///
441/// \param CurContext the context where an entity is being named, which is
442/// typically based on the current scope.
443///
444/// \param TargetContext the context in which the named entity actually
445/// resides.
446///
447/// \returns a nested name specifier that refers into the target context, or
448/// NULL if no qualification is needed.
449static NestedNameSpecifier *
450getRequiredQualification(ASTContext &Context,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000451 const DeclContext *CurContext,
452 const DeclContext *TargetContext) {
453 SmallVector<const DeclContext *, 4> TargetParents;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000454
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000455 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor456c4a12009-09-21 20:12:40 +0000456 CommonAncestor && !CommonAncestor->Encloses(CurContext);
457 CommonAncestor = CommonAncestor->getLookupParent()) {
458 if (CommonAncestor->isTransparentContext() ||
459 CommonAncestor->isFunctionOrMethod())
460 continue;
461
462 TargetParents.push_back(CommonAncestor);
463 }
464
465 NestedNameSpecifier *Result = 0;
466 while (!TargetParents.empty()) {
Robert Wilhelm344472e2013-08-23 16:11:15 +0000467 const DeclContext *Parent = TargetParents.pop_back_val();
468
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000469 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregorfb629412010-08-23 21:17:50 +0000470 if (!Namespace->getIdentifier())
471 continue;
472
Douglas Gregor456c4a12009-09-21 20:12:40 +0000473 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Douglas Gregorfb629412010-08-23 21:17:50 +0000474 }
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000475 else if (const TagDecl *TD = dyn_cast<TagDecl>(Parent))
Douglas Gregor456c4a12009-09-21 20:12:40 +0000476 Result = NestedNameSpecifier::Create(Context, Result,
477 false,
478 Context.getTypeDeclType(TD).getTypePtr());
Douglas Gregor0c8296d2009-11-07 00:00:49 +0000479 }
Douglas Gregor456c4a12009-09-21 20:12:40 +0000480 return Result;
481}
482
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000483bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000484 bool &AsNestedNameSpecifier) const {
485 AsNestedNameSpecifier = false;
486
Douglas Gregore495b7f2010-01-14 00:20:49 +0000487 ND = ND->getUnderlyingDecl();
488 unsigned IDNS = ND->getIdentifierNamespace();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000489
490 // Skip unnamed entities.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000491 if (!ND->getDeclName())
492 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000493
494 // Friend declarations and declarations introduced due to friends are never
495 // added as results.
John McCall92b7f702010-03-11 07:50:04 +0000496 if (IDNS & (Decl::IDNS_OrdinaryFriend | Decl::IDNS_TagFriend))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000497 return false;
498
Douglas Gregor76282942009-12-11 17:31:05 +0000499 // Class template (partial) specializations are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000500 if (isa<ClassTemplateSpecializationDecl>(ND) ||
501 isa<ClassTemplatePartialSpecializationDecl>(ND))
502 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000503
Douglas Gregor76282942009-12-11 17:31:05 +0000504 // Using declarations themselves are never added as results.
Douglas Gregore495b7f2010-01-14 00:20:49 +0000505 if (isa<UsingDecl>(ND))
506 return false;
507
508 // Some declarations have reserved names that we don't want to ever show.
509 if (const IdentifierInfo *Id = ND->getIdentifier()) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000510 // __va_list_tag is a freak of nature. Find it and skip it.
511 if (Id->isStr("__va_list_tag") || Id->isStr("__builtin_va_list"))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000512 return false;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000513
Douglas Gregorf52cede2009-10-09 22:16:47 +0000514 // Filter out names reserved for the implementation (C99 7.1.3,
Douglas Gregor797efb52010-07-14 17:44:04 +0000515 // C++ [lib.global.names]) if they come from a system header.
Daniel Dunbare013d682009-10-18 20:26:12 +0000516 //
517 // FIXME: Add predicate for this.
Douglas Gregorf52cede2009-10-09 22:16:47 +0000518 if (Id->getLength() >= 2) {
Daniel Dunbare013d682009-10-18 20:26:12 +0000519 const char *Name = Id->getNameStart();
Douglas Gregorf52cede2009-10-09 22:16:47 +0000520 if (Name[0] == '_' &&
Douglas Gregor797efb52010-07-14 17:44:04 +0000521 (Name[1] == '_' || (Name[1] >= 'A' && Name[1] <= 'Z')) &&
522 (ND->getLocation().isInvalid() ||
523 SemaRef.SourceMgr.isInSystemHeader(
524 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000525 return false;
Douglas Gregorf52cede2009-10-09 22:16:47 +0000526 }
Douglas Gregor86d9a522009-09-21 16:56:56 +0000527 }
Douglas Gregor9b0ba872010-11-09 03:59:40 +0000528
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000529 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
530 ((isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND)) &&
531 Filter != &ResultBuilder::IsNamespace &&
Douglas Gregor52779fb2010-09-23 23:01:17 +0000532 Filter != &ResultBuilder::IsNamespaceOrAlias &&
533 Filter != 0))
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000534 AsNestedNameSpecifier = true;
535
Douglas Gregor86d9a522009-09-21 16:56:56 +0000536 // Filter out any unwanted results.
Douglas Gregor45bcd432010-01-14 03:21:49 +0000537 if (Filter && !(this->*Filter)(ND)) {
538 // Check whether it is interesting as a nested-name-specifier.
David Blaikie4e4d0842012-03-11 07:00:24 +0000539 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor45bcd432010-01-14 03:21:49 +0000540 IsNestedNameSpecifier(ND) &&
541 (Filter != &ResultBuilder::IsMember ||
542 (isa<CXXRecordDecl>(ND) &&
543 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
544 AsNestedNameSpecifier = true;
545 return true;
546 }
547
Douglas Gregore495b7f2010-01-14 00:20:49 +0000548 return false;
Douglas Gregora5fb7c32010-08-16 23:05:20 +0000549 }
Douglas Gregore495b7f2010-01-14 00:20:49 +0000550 // ... then it must be interesting!
551 return true;
552}
553
Douglas Gregor6660d842010-01-14 00:41:07 +0000554bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000555 const NamedDecl *Hiding) {
Douglas Gregor6660d842010-01-14 00:41:07 +0000556 // In C, there is no way to refer to a hidden name.
557 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
558 // name if we introduce the tag type.
David Blaikie4e4d0842012-03-11 07:00:24 +0000559 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor6660d842010-01-14 00:41:07 +0000560 return true;
561
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000562 const DeclContext *HiddenCtx =
563 R.Declaration->getDeclContext()->getRedeclContext();
Douglas Gregor6660d842010-01-14 00:41:07 +0000564
565 // There is no way to qualify a name declared in a function or method.
566 if (HiddenCtx->isFunctionOrMethod())
567 return true;
568
Sebastian Redl7a126a42010-08-31 00:36:30 +0000569 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregor6660d842010-01-14 00:41:07 +0000570 return true;
571
572 // We can refer to the result with the appropriate qualification. Do it.
573 R.Hidden = true;
574 R.QualifierIsInformative = false;
575
576 if (!R.Qualifier)
577 R.Qualifier = getRequiredQualification(SemaRef.Context,
578 CurContext,
579 R.Declaration->getDeclContext());
580 return false;
581}
582
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000583/// \brief A simplified classification of types used to determine whether two
584/// types are "similar enough" when adjusting priorities.
Douglas Gregor1827e102010-08-16 16:18:59 +0000585SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000586 switch (T->getTypeClass()) {
587 case Type::Builtin:
588 switch (cast<BuiltinType>(T)->getKind()) {
589 case BuiltinType::Void:
590 return STC_Void;
591
592 case BuiltinType::NullPtr:
593 return STC_Pointer;
594
595 case BuiltinType::Overload:
596 case BuiltinType::Dependent:
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000597 return STC_Other;
598
599 case BuiltinType::ObjCId:
600 case BuiltinType::ObjCClass:
601 case BuiltinType::ObjCSel:
602 return STC_ObjectiveC;
603
604 default:
605 return STC_Arithmetic;
606 }
David Blaikie7530c032012-01-17 06:56:22 +0000607
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000608 case Type::Complex:
609 return STC_Arithmetic;
610
611 case Type::Pointer:
612 return STC_Pointer;
613
614 case Type::BlockPointer:
615 return STC_Block;
616
617 case Type::LValueReference:
618 case Type::RValueReference:
619 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
620
621 case Type::ConstantArray:
622 case Type::IncompleteArray:
623 case Type::VariableArray:
624 case Type::DependentSizedArray:
625 return STC_Array;
626
627 case Type::DependentSizedExtVector:
628 case Type::Vector:
629 case Type::ExtVector:
630 return STC_Arithmetic;
631
632 case Type::FunctionProto:
633 case Type::FunctionNoProto:
634 return STC_Function;
635
636 case Type::Record:
637 return STC_Record;
638
639 case Type::Enum:
640 return STC_Arithmetic;
641
642 case Type::ObjCObject:
643 case Type::ObjCInterface:
644 case Type::ObjCObjectPointer:
645 return STC_ObjectiveC;
646
647 default:
648 return STC_Other;
649 }
650}
651
652/// \brief Get the type that a given expression will have if this declaration
653/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000654QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000655 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
656
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000657 if (const TypeDecl *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000658 return C.getTypeDeclType(Type);
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000659 if (const ObjCInterfaceDecl *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000660 return C.getObjCInterfaceType(Iface);
661
662 QualType T;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000663 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000664 T = Function->getCallResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000665 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000666 T = Method->getSendResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000667 else if (const FunctionTemplateDecl *FunTmpl =
668 dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregor5291c3c2010-07-13 08:18:22 +0000669 T = FunTmpl->getTemplatedDecl()->getCallResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000670 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000671 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000672 else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000673 T = Property->getType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000674 else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000675 T = Value->getType();
676 else
677 return QualType();
Douglas Gregor3e64d562011-04-14 20:33:34 +0000678
679 // Dig through references, function pointers, and block pointers to
680 // get down to the likely type of an expression when the entity is
681 // used.
682 do {
683 if (const ReferenceType *Ref = T->getAs<ReferenceType>()) {
684 T = Ref->getPointeeType();
685 continue;
686 }
687
688 if (const PointerType *Pointer = T->getAs<PointerType>()) {
689 if (Pointer->getPointeeType()->isFunctionType()) {
690 T = Pointer->getPointeeType();
691 continue;
692 }
693
694 break;
695 }
696
697 if (const BlockPointerType *Block = T->getAs<BlockPointerType>()) {
698 T = Block->getPointeeType();
699 continue;
700 }
701
702 if (const FunctionType *Function = T->getAs<FunctionType>()) {
703 T = Function->getResultType();
704 continue;
705 }
706
707 break;
708 } while (true);
709
710 return T;
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000711}
712
Douglas Gregord1f09b42013-01-31 04:52:16 +0000713unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
714 if (!ND)
715 return CCP_Unlikely;
716
717 // Context-based decisions.
718 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
719 if (DC->isFunctionOrMethod() || isa<BlockDecl>(DC)) {
720 // _cmd is relatively rare
721 if (const ImplicitParamDecl *ImplicitParam =
722 dyn_cast<ImplicitParamDecl>(ND))
723 if (ImplicitParam->getIdentifier() &&
724 ImplicitParam->getIdentifier()->isStr("_cmd"))
725 return CCP_ObjC_cmd;
726
727 return CCP_LocalDeclaration;
728 }
729 if (DC->isRecord() || isa<ObjCContainerDecl>(DC))
730 return CCP_MemberDeclaration;
731
732 // Content-based decisions.
733 if (isa<EnumConstantDecl>(ND))
734 return CCP_Constant;
735
Douglas Gregor626799b2013-01-31 05:03:46 +0000736 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
737 // message receiver, or parenthesized expression context. There, it's as
738 // likely that the user will want to write a type as other declarations.
739 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
740 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
741 CompletionContext.getKind()
742 == CodeCompletionContext::CCC_ObjCMessageReceiver ||
743 CompletionContext.getKind()
744 == CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregord1f09b42013-01-31 04:52:16 +0000745 return CCP_Type;
746
747 return CCP_Declaration;
748}
749
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000750void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
751 // If this is an Objective-C method declaration whose selector matches our
752 // preferred selector, give it a priority boost.
753 if (!PreferredSelector.isNull())
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000754 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000755 if (PreferredSelector == Method->getSelector())
756 R.Priority += CCD_SelectorMatch;
Douglas Gregor08f43cd2010-09-20 23:11:55 +0000757
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000758 // If we have a preferred type, adjust the priority for results with exactly-
759 // matching or nearly-matching types.
760 if (!PreferredType.isNull()) {
761 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
762 if (!T.isNull()) {
763 CanQualType TC = SemaRef.Context.getCanonicalType(T);
764 // Check for exactly-matching types (modulo qualifiers).
765 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
766 R.Priority /= CCF_ExactTypeMatch;
767 // Check for nearly-matching types, based on classification of each.
768 else if ((getSimplifiedTypeClass(PreferredType)
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000769 == getSimplifiedTypeClass(TC)) &&
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000770 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
771 R.Priority /= CCF_SimilarTypeMatch;
772 }
773 }
Douglas Gregor1f5537a2010-07-08 23:20:03 +0000774}
775
Douglas Gregor6f942b22010-09-21 16:06:22 +0000776void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikie4e4d0842012-03-11 07:00:24 +0000777 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor6f942b22010-09-21 16:06:22 +0000778 !CompletionContext.wantConstructorResults())
779 return;
780
781 ASTContext &Context = SemaRef.Context;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000782 const NamedDecl *D = R.Declaration;
783 const CXXRecordDecl *Record = 0;
784 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor6f942b22010-09-21 16:06:22 +0000785 Record = ClassTemplate->getTemplatedDecl();
786 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
787 // Skip specializations and partial specializations.
788 if (isa<ClassTemplateSpecializationDecl>(Record))
789 return;
790 } else {
791 // There are no constructors here.
792 return;
793 }
794
795 Record = Record->getDefinition();
796 if (!Record)
797 return;
798
799
800 QualType RecordTy = Context.getTypeDeclType(Record);
801 DeclarationName ConstructorName
802 = Context.DeclarationNames.getCXXConstructorName(
803 Context.getCanonicalType(RecordTy));
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000804 DeclContext::lookup_const_result Ctors = Record->lookup(ConstructorName);
805 for (DeclContext::lookup_const_iterator I = Ctors.begin(),
806 E = Ctors.end();
807 I != E; ++I) {
David Blaikie3bc93e32012-12-19 00:45:41 +0000808 R.Declaration = *I;
Douglas Gregor6f942b22010-09-21 16:06:22 +0000809 R.CursorKind = getCursorKindForDecl(R.Declaration);
810 Results.push_back(R);
811 }
812}
813
Douglas Gregore495b7f2010-01-14 00:20:49 +0000814void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
815 assert(!ShadowMaps.empty() && "Must enter into a results scope");
816
817 if (R.Kind != Result::RK_Declaration) {
818 // For non-declaration results, just add the result.
819 Results.push_back(R);
820 return;
821 }
822
823 // Look through using declarations.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000824 if (const UsingShadowDecl *Using =
825 dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregord1f09b42013-01-31 04:52:16 +0000826 MaybeAddResult(Result(Using->getTargetDecl(),
827 getBasePriority(Using->getTargetDecl()),
828 R.Qualifier),
829 CurContext);
Douglas Gregore495b7f2010-01-14 00:20:49 +0000830 return;
831 }
832
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000833 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregore495b7f2010-01-14 00:20:49 +0000834 unsigned IDNS = CanonDecl->getIdentifierNamespace();
835
Douglas Gregor45bcd432010-01-14 03:21:49 +0000836 bool AsNestedNameSpecifier = false;
837 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregore495b7f2010-01-14 00:20:49 +0000838 return;
839
Douglas Gregor6f942b22010-09-21 16:06:22 +0000840 // C++ constructors are never found by name lookup.
841 if (isa<CXXConstructorDecl>(R.Declaration))
842 return;
843
Douglas Gregor86d9a522009-09-21 16:56:56 +0000844 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000845 ShadowMapEntry::iterator I, IEnd;
846 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
847 if (NamePos != SMap.end()) {
848 I = NamePos->second.begin();
849 IEnd = NamePos->second.end();
850 }
851
852 for (; I != IEnd; ++I) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000853 const NamedDecl *ND = I->first;
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000854 unsigned Index = I->second;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000855 if (ND->getCanonicalDecl() == CanonDecl) {
856 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor86d9a522009-09-21 16:56:56 +0000857 Results[Index].Declaration = R.Declaration;
858
Douglas Gregor86d9a522009-09-21 16:56:56 +0000859 // We're done.
860 return;
861 }
862 }
863
864 // This is a new declaration in this scope. However, check whether this
865 // declaration name is hidden by a similarly-named declaration in an outer
866 // scope.
867 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
868 --SMEnd;
869 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000870 ShadowMapEntry::iterator I, IEnd;
871 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
872 if (NamePos != SM->end()) {
873 I = NamePos->second.begin();
874 IEnd = NamePos->second.end();
875 }
876 for (; I != IEnd; ++I) {
Douglas Gregor86d9a522009-09-21 16:56:56 +0000877 // A tag declaration does not hide a non-tag declaration.
John McCall0d6b1642010-04-23 18:46:30 +0000878 if (I->first->hasTagIdentifierNamespace() &&
Douglas Gregor86d9a522009-09-21 16:56:56 +0000879 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
880 Decl::IDNS_ObjCProtocol)))
881 continue;
882
883 // Protocols are in distinct namespaces from everything else.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000884 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000885 || (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000886 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor86d9a522009-09-21 16:56:56 +0000887 continue;
888
889 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregor6660d842010-01-14 00:41:07 +0000890 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor86d9a522009-09-21 16:56:56 +0000891 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +0000892
893 break;
894 }
895 }
896
897 // Make sure that any given declaration only shows up in the result set once.
898 if (!AllDeclsFound.insert(CanonDecl))
899 return;
Douglas Gregor265f7492010-08-27 15:29:55 +0000900
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000901 // If the filter is for nested-name-specifiers, then this result starts a
902 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000903 if (AsNestedNameSpecifier) {
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000904 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000905 R.Priority = CCP_NestedNameSpecifier;
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000906 } else
907 AdjustResultPriorityForDecl(R);
Douglas Gregor265f7492010-08-27 15:29:55 +0000908
Douglas Gregor0563c262009-09-22 23:15:58 +0000909 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000910 if (R.QualifierIsInformative && !R.Qualifier &&
911 !R.StartsNestedNameSpecifier) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000912 const DeclContext *Ctx = R.Declaration->getDeclContext();
913 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Douglas Gregor0563c262009-09-22 23:15:58 +0000914 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000915 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Douglas Gregor0563c262009-09-22 23:15:58 +0000916 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
917 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
918 else
919 R.QualifierIsInformative = false;
920 }
Douglas Gregoreb5758b2009-09-23 22:26:46 +0000921
Douglas Gregor86d9a522009-09-21 16:56:56 +0000922 // Insert this result into the set of results and into the current shadow
923 // map.
Douglas Gregorfbcb5d62009-12-06 20:23:50 +0000924 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor86d9a522009-09-21 16:56:56 +0000925 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +0000926
927 if (!AsNestedNameSpecifier)
928 MaybeAddConstructorResults(R);
Douglas Gregor86d9a522009-09-21 16:56:56 +0000929}
930
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000931void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor0cc84042010-01-14 15:47:35 +0000932 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregora4477812010-01-14 16:01:26 +0000933 if (R.Kind != Result::RK_Declaration) {
934 // For non-declaration results, just add the result.
935 Results.push_back(R);
936 return;
937 }
938
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000939 // Look through using declarations.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000940 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Douglas Gregord1f09b42013-01-31 04:52:16 +0000941 AddResult(Result(Using->getTargetDecl(),
942 getBasePriority(Using->getTargetDecl()),
943 R.Qualifier),
944 CurContext, Hiding);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000945 return;
946 }
947
Douglas Gregor45bcd432010-01-14 03:21:49 +0000948 bool AsNestedNameSpecifier = false;
949 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000950 return;
951
Douglas Gregor6f942b22010-09-21 16:06:22 +0000952 // C++ constructors are never found by name lookup.
953 if (isa<CXXConstructorDecl>(R.Declaration))
954 return;
955
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000956 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
957 return;
Nick Lewycky173a37a2012-04-03 21:44:08 +0000958
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000959 // Make sure that any given declaration only shows up in the result set once.
960 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()))
961 return;
962
963 // If the filter is for nested-name-specifiers, then this result starts a
964 // nested-name-specifier.
Douglas Gregor12e13132010-05-26 22:00:08 +0000965 if (AsNestedNameSpecifier) {
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000966 R.StartsNestedNameSpecifier = true;
Douglas Gregor12e13132010-05-26 22:00:08 +0000967 R.Priority = CCP_NestedNameSpecifier;
968 }
Douglas Gregor0cc84042010-01-14 15:47:35 +0000969 else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && InBaseClass &&
970 isa<CXXRecordDecl>(R.Declaration->getDeclContext()
Sebastian Redl7a126a42010-08-31 00:36:30 +0000971 ->getRedeclContext()))
Douglas Gregor0cc84042010-01-14 15:47:35 +0000972 R.QualifierIsInformative = true;
973
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000974 // If this result is supposed to have an informative qualifier, add one.
975 if (R.QualifierIsInformative && !R.Qualifier &&
976 !R.StartsNestedNameSpecifier) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000977 const DeclContext *Ctx = R.Declaration->getDeclContext();
978 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000979 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, Namespace);
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000980 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000981 R.Qualifier = NestedNameSpecifier::Create(SemaRef.Context, 0, false,
Douglas Gregor45bcd432010-01-14 03:21:49 +0000982 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor1ca6ae82010-01-14 01:09:38 +0000983 else
984 R.QualifierIsInformative = false;
985 }
986
Douglas Gregor12e13132010-05-26 22:00:08 +0000987 // Adjust the priority if this result comes from a base class.
988 if (InBaseClass)
989 R.Priority += CCD_InBaseClass;
990
Douglas Gregorcee9ff12010-09-20 22:39:41 +0000991 AdjustResultPriorityForDecl(R);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +0000992
Douglas Gregor3cdee122010-08-26 16:36:48 +0000993 if (HasObjectTypeQualifiers)
Dmitri Gribenko89cf4252013-01-23 17:21:11 +0000994 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor3cdee122010-08-26 16:36:48 +0000995 if (Method->isInstance()) {
996 Qualifiers MethodQuals
997 = Qualifiers::fromCVRMask(Method->getTypeQualifiers());
998 if (ObjectTypeQualifiers == MethodQuals)
999 R.Priority += CCD_ObjectQualifierMatch;
1000 else if (ObjectTypeQualifiers - MethodQuals) {
1001 // The method cannot be invoked, because doing so would drop
1002 // qualifiers.
1003 return;
1004 }
1005 }
1006
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001007 // Insert this result into the set of results.
1008 Results.push_back(R);
Douglas Gregor6f942b22010-09-21 16:06:22 +00001009
1010 if (!AsNestedNameSpecifier)
1011 MaybeAddConstructorResults(R);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001012}
1013
Douglas Gregora4477812010-01-14 16:01:26 +00001014void ResultBuilder::AddResult(Result R) {
1015 assert(R.Kind != Result::RK_Declaration &&
1016 "Declaration results need more context");
1017 Results.push_back(R);
1018}
1019
Douglas Gregor86d9a522009-09-21 16:56:56 +00001020/// \brief Enter into a new scope.
1021void ResultBuilder::EnterNewScope() {
1022 ShadowMaps.push_back(ShadowMap());
1023}
1024
1025/// \brief Exit from the current scope.
1026void ResultBuilder::ExitScope() {
Douglas Gregorfbcb5d62009-12-06 20:23:50 +00001027 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
1028 EEnd = ShadowMaps.back().end();
1029 E != EEnd;
1030 ++E)
1031 E->second.Destroy();
1032
Douglas Gregor86d9a522009-09-21 16:56:56 +00001033 ShadowMaps.pop_back();
1034}
1035
Douglas Gregor791215b2009-09-21 20:51:25 +00001036/// \brief Determines whether this given declaration will be found by
1037/// ordinary name lookup.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001038bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001039 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1040
Douglas Gregor791215b2009-09-21 20:51:25 +00001041 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001042 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001043 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001044 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001045 if (isa<ObjCIvarDecl>(ND))
1046 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001047 }
1048
Douglas Gregor791215b2009-09-21 20:51:25 +00001049 return ND->getIdentifierNamespace() & IDNS;
1050}
1051
Douglas Gregor01dfea02010-01-10 23:08:15 +00001052/// \brief Determines whether this given declaration will be found by
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001053/// ordinary name lookup but is not a type name.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001054bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001055 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1056 if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND))
1057 return false;
1058
1059 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001060 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9b30b262010-06-15 20:26:51 +00001061 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
David Blaikie4e4d0842012-03-11 07:00:24 +00001062 else if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregorca45da02010-11-02 20:36:02 +00001063 if (isa<ObjCIvarDecl>(ND))
1064 return true;
Douglas Gregorca45da02010-11-02 20:36:02 +00001065 }
1066
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001067 return ND->getIdentifierNamespace() & IDNS;
1068}
1069
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001070bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregorf9578432010-07-28 21:50:18 +00001071 if (!IsOrdinaryNonTypeName(ND))
1072 return 0;
1073
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001074 if (const ValueDecl *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregorf9578432010-07-28 21:50:18 +00001075 if (VD->getType()->isIntegralOrEnumerationType())
1076 return true;
1077
1078 return false;
1079}
1080
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001081/// \brief Determines whether this given declaration will be found by
Douglas Gregor01dfea02010-01-10 23:08:15 +00001082/// ordinary name lookup.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001083bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001084 ND = cast<NamedDecl>(ND->getUnderlyingDecl());
1085
Douglas Gregor01dfea02010-01-10 23:08:15 +00001086 unsigned IDNS = Decl::IDNS_Ordinary;
David Blaikie4e4d0842012-03-11 07:00:24 +00001087 if (SemaRef.getLangOpts().CPlusPlus)
John McCall0d6b1642010-04-23 18:46:30 +00001088 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001089
1090 return (ND->getIdentifierNamespace() & IDNS) &&
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001091 !isa<ValueDecl>(ND) && !isa<FunctionTemplateDecl>(ND) &&
1092 !isa<ObjCPropertyDecl>(ND);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001093}
1094
Douglas Gregor86d9a522009-09-21 16:56:56 +00001095/// \brief Determines whether the given declaration is suitable as the
1096/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001097bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001098 // Allow us to find class templates, too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001099 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor86d9a522009-09-21 16:56:56 +00001100 ND = ClassTemplate->getTemplatedDecl();
1101
1102 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1103}
1104
1105/// \brief Determines whether the given declaration is an enumeration.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001106bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001107 return isa<EnumDecl>(ND);
1108}
1109
1110/// \brief Determines whether the given declaration is a class or struct.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001111bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001112 // Allow us to find class templates, too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001113 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor86d9a522009-09-21 16:56:56 +00001114 ND = ClassTemplate->getTemplatedDecl();
Joao Matos6666ed42012-08-31 18:45:21 +00001115
1116 // For purposes of this check, interfaces match too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001117 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001118 return RD->getTagKind() == TTK_Class ||
Joao Matos6666ed42012-08-31 18:45:21 +00001119 RD->getTagKind() == TTK_Struct ||
1120 RD->getTagKind() == TTK_Interface;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001121
1122 return false;
1123}
1124
1125/// \brief Determines whether the given declaration is a union.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001126bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001127 // Allow us to find class templates, too.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001128 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor86d9a522009-09-21 16:56:56 +00001129 ND = ClassTemplate->getTemplatedDecl();
1130
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001131 if (const RecordDecl *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara465d41b2010-05-11 21:36:43 +00001132 return RD->getTagKind() == TTK_Union;
Douglas Gregor86d9a522009-09-21 16:56:56 +00001133
1134 return false;
1135}
1136
1137/// \brief Determines whether the given declaration is a namespace.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001138bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001139 return isa<NamespaceDecl>(ND);
1140}
1141
1142/// \brief Determines whether the given declaration is a namespace or
1143/// namespace alias.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001144bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Douglas Gregor86d9a522009-09-21 16:56:56 +00001145 return isa<NamespaceDecl>(ND) || isa<NamespaceAliasDecl>(ND);
1146}
1147
Douglas Gregor76282942009-12-11 17:31:05 +00001148/// \brief Determines whether the given declaration is a type.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001149bool ResultBuilder::IsType(const NamedDecl *ND) const {
1150 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
Douglas Gregord32b0222010-08-24 01:06:58 +00001151 ND = Using->getTargetDecl();
1152
1153 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor86d9a522009-09-21 16:56:56 +00001154}
1155
Douglas Gregor76282942009-12-11 17:31:05 +00001156/// \brief Determines which members of a class should be visible via
1157/// "." or "->". Only value declarations, nested name specifiers, and
1158/// using declarations thereof should show up.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001159bool ResultBuilder::IsMember(const NamedDecl *ND) const {
1160 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(ND))
Douglas Gregor76282942009-12-11 17:31:05 +00001161 ND = Using->getTargetDecl();
1162
Douglas Gregorce821962009-12-11 18:14:22 +00001163 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
1164 isa<ObjCPropertyDecl>(ND);
Douglas Gregoreb5758b2009-09-23 22:26:46 +00001165}
1166
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001167static bool isObjCReceiverType(ASTContext &C, QualType T) {
1168 T = C.getCanonicalType(T);
1169 switch (T->getTypeClass()) {
1170 case Type::ObjCObject:
1171 case Type::ObjCInterface:
1172 case Type::ObjCObjectPointer:
1173 return true;
1174
1175 case Type::Builtin:
1176 switch (cast<BuiltinType>(T)->getKind()) {
1177 case BuiltinType::ObjCId:
1178 case BuiltinType::ObjCClass:
1179 case BuiltinType::ObjCSel:
1180 return true;
1181
1182 default:
1183 break;
1184 }
1185 return false;
1186
1187 default:
1188 break;
1189 }
1190
David Blaikie4e4d0842012-03-11 07:00:24 +00001191 if (!C.getLangOpts().CPlusPlus)
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001192 return false;
1193
1194 // FIXME: We could perform more analysis here to determine whether a
1195 // particular class type has any conversions to Objective-C types. For now,
1196 // just accept all class types.
1197 return T->isDependentType() || T->isRecordType();
1198}
1199
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001200bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001201 QualType T = getDeclUsageType(SemaRef.Context, ND);
1202 if (T.isNull())
1203 return false;
1204
1205 T = SemaRef.Context.getBaseElementType(T);
1206 return isObjCReceiverType(SemaRef.Context, T);
1207}
1208
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001209bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const {
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001210 if (IsObjCMessageReceiver(ND))
1211 return true;
1212
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001213 const VarDecl *Var = dyn_cast<VarDecl>(ND);
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001214 if (!Var)
1215 return false;
1216
1217 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1218}
1219
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001220bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikie4e4d0842012-03-11 07:00:24 +00001221 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1222 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregorfb629412010-08-23 21:17:50 +00001223 return false;
1224
1225 QualType T = getDeclUsageType(SemaRef.Context, ND);
1226 if (T.isNull())
1227 return false;
1228
1229 T = SemaRef.Context.getBaseElementType(T);
1230 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
1231 T->isObjCIdType() ||
David Blaikie4e4d0842012-03-11 07:00:24 +00001232 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregorfb629412010-08-23 21:17:50 +00001233}
Douglas Gregor8e254cf2010-05-27 23:06:34 +00001234
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001235bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor52779fb2010-09-23 23:01:17 +00001236 return false;
1237}
1238
James Dennettde23c7e2012-06-17 05:33:25 +00001239/// \brief Determines whether the given declaration is an Objective-C
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001240/// instance variable.
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00001241bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00001242 return isa<ObjCIvarDecl>(ND);
1243}
1244
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001245namespace {
1246 /// \brief Visible declaration consumer that adds a code-completion result
1247 /// for each visible declaration.
1248 class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1249 ResultBuilder &Results;
1250 DeclContext *CurContext;
1251
1252 public:
1253 CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
1254 : Results(Results), CurContext(CurContext) { }
1255
Erik Verbruggend1205962011-10-06 07:27:49 +00001256 virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1257 bool InBaseClass) {
1258 bool Accessible = true;
Douglas Gregor17015ef2011-11-03 16:51:37 +00001259 if (Ctx)
1260 Accessible = Results.getSema().IsSimplyAccessible(ND, Ctx);
1261
Douglas Gregord1f09b42013-01-31 04:52:16 +00001262 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), 0, false,
1263 Accessible);
Erik Verbruggend1205962011-10-06 07:27:49 +00001264 Results.AddResult(Result, CurContext, Hiding, InBaseClass);
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00001265 }
1266 };
1267}
1268
Douglas Gregor86d9a522009-09-21 16:56:56 +00001269/// \brief Add type specifiers for the current language as keyword results.
Douglas Gregorbca403c2010-01-13 23:51:12 +00001270static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor86d9a522009-09-21 16:56:56 +00001271 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001272 typedef CodeCompletionResult Result;
Douglas Gregor12e13132010-05-26 22:00:08 +00001273 Results.AddResult(Result("short", CCP_Type));
1274 Results.AddResult(Result("long", CCP_Type));
1275 Results.AddResult(Result("signed", CCP_Type));
1276 Results.AddResult(Result("unsigned", CCP_Type));
1277 Results.AddResult(Result("void", CCP_Type));
1278 Results.AddResult(Result("char", CCP_Type));
1279 Results.AddResult(Result("int", CCP_Type));
1280 Results.AddResult(Result("float", CCP_Type));
1281 Results.AddResult(Result("double", CCP_Type));
1282 Results.AddResult(Result("enum", CCP_Type));
1283 Results.AddResult(Result("struct", CCP_Type));
1284 Results.AddResult(Result("union", CCP_Type));
1285 Results.AddResult(Result("const", CCP_Type));
1286 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001287
Douglas Gregor86d9a522009-09-21 16:56:56 +00001288 if (LangOpts.C99) {
1289 // C99-specific
Douglas Gregor12e13132010-05-26 22:00:08 +00001290 Results.AddResult(Result("_Complex", CCP_Type));
1291 Results.AddResult(Result("_Imaginary", CCP_Type));
1292 Results.AddResult(Result("_Bool", CCP_Type));
1293 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001294 }
1295
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001296 CodeCompletionBuilder Builder(Results.getAllocator(),
1297 Results.getCodeCompletionTUInfo());
Douglas Gregor86d9a522009-09-21 16:56:56 +00001298 if (LangOpts.CPlusPlus) {
1299 // C++-specific
Douglas Gregorb05496d2010-09-20 21:11:48 +00001300 Results.AddResult(Result("bool", CCP_Type +
1301 (LangOpts.ObjC1? CCD_bool_in_ObjC : 0)));
Douglas Gregor12e13132010-05-26 22:00:08 +00001302 Results.AddResult(Result("class", CCP_Type));
1303 Results.AddResult(Result("wchar_t", CCP_Type));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001304
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001305 // typename qualified-id
Douglas Gregor218937c2011-02-01 19:23:04 +00001306 Builder.AddTypedTextChunk("typename");
1307 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1308 Builder.AddPlaceholderChunk("qualifier");
1309 Builder.AddTextChunk("::");
1310 Builder.AddPlaceholderChunk("name");
1311 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001312
Richard Smith80ad52f2013-01-02 11:42:31 +00001313 if (LangOpts.CPlusPlus11) {
Douglas Gregor12e13132010-05-26 22:00:08 +00001314 Results.AddResult(Result("auto", CCP_Type));
1315 Results.AddResult(Result("char16_t", CCP_Type));
1316 Results.AddResult(Result("char32_t", CCP_Type));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001317
Douglas Gregor218937c2011-02-01 19:23:04 +00001318 Builder.AddTypedTextChunk("decltype");
1319 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1320 Builder.AddPlaceholderChunk("expression");
1321 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1322 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001323 }
1324 }
1325
1326 // GNU extensions
1327 if (LangOpts.GNUMode) {
1328 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregora4477812010-01-14 16:01:26 +00001329 // Results.AddResult(Result("_Decimal32"));
1330 // Results.AddResult(Result("_Decimal64"));
1331 // Results.AddResult(Result("_Decimal128"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001332
Douglas Gregor218937c2011-02-01 19:23:04 +00001333 Builder.AddTypedTextChunk("typeof");
1334 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1335 Builder.AddPlaceholderChunk("expression");
1336 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001337
Douglas Gregor218937c2011-02-01 19:23:04 +00001338 Builder.AddTypedTextChunk("typeof");
1339 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1340 Builder.AddPlaceholderChunk("type");
1341 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1342 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor86d9a522009-09-21 16:56:56 +00001343 }
1344}
1345
John McCallf312b1e2010-08-26 23:41:50 +00001346static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001347 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001348 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001349 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001350 // Note: we don't suggest either "auto" or "register", because both
1351 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1352 // in C++0x as a type specifier.
Douglas Gregora4477812010-01-14 16:01:26 +00001353 Results.AddResult(Result("extern"));
1354 Results.AddResult(Result("static"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001355}
1356
John McCallf312b1e2010-08-26 23:41:50 +00001357static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001358 const LangOptions &LangOpts,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001359 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00001360 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001361 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001362 case Sema::PCC_Class:
1363 case Sema::PCC_MemberTemplate:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001364 if (LangOpts.CPlusPlus) {
Douglas Gregora4477812010-01-14 16:01:26 +00001365 Results.AddResult(Result("explicit"));
1366 Results.AddResult(Result("friend"));
1367 Results.AddResult(Result("mutable"));
1368 Results.AddResult(Result("virtual"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001369 }
1370 // Fall through
1371
John McCallf312b1e2010-08-26 23:41:50 +00001372 case Sema::PCC_ObjCInterface:
1373 case Sema::PCC_ObjCImplementation:
1374 case Sema::PCC_Namespace:
1375 case Sema::PCC_Template:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001376 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregora4477812010-01-14 16:01:26 +00001377 Results.AddResult(Result("inline"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001378 break;
1379
John McCallf312b1e2010-08-26 23:41:50 +00001380 case Sema::PCC_ObjCInstanceVariableList:
1381 case Sema::PCC_Expression:
1382 case Sema::PCC_Statement:
1383 case Sema::PCC_ForInit:
1384 case Sema::PCC_Condition:
1385 case Sema::PCC_RecoveryInFunction:
1386 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001387 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001388 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00001389 break;
1390 }
1391}
1392
Douglas Gregorbca403c2010-01-13 23:51:12 +00001393static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1394static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1395static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001396 ResultBuilder &Results,
1397 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001398static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001399 ResultBuilder &Results,
1400 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001401static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001402 ResultBuilder &Results,
1403 bool NeedAt);
Douglas Gregorbca403c2010-01-13 23:51:12 +00001404static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001405
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001406static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001407 CodeCompletionBuilder Builder(Results.getAllocator(),
1408 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00001409 Builder.AddTypedTextChunk("typedef");
1410 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1411 Builder.AddPlaceholderChunk("type");
1412 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1413 Builder.AddPlaceholderChunk("name");
1414 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001415}
1416
John McCallf312b1e2010-08-26 23:41:50 +00001417static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001418 const LangOptions &LangOpts) {
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001419 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001420 case Sema::PCC_Namespace:
1421 case Sema::PCC_Class:
1422 case Sema::PCC_ObjCInstanceVariableList:
1423 case Sema::PCC_Template:
1424 case Sema::PCC_MemberTemplate:
1425 case Sema::PCC_Statement:
1426 case Sema::PCC_RecoveryInFunction:
1427 case Sema::PCC_Type:
Douglas Gregor02688102010-09-14 23:59:36 +00001428 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00001429 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001430 return true;
1431
John McCallf312b1e2010-08-26 23:41:50 +00001432 case Sema::PCC_Expression:
1433 case Sema::PCC_Condition:
Douglas Gregor02688102010-09-14 23:59:36 +00001434 return LangOpts.CPlusPlus;
1435
1436 case Sema::PCC_ObjCInterface:
1437 case Sema::PCC_ObjCImplementation:
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001438 return false;
1439
John McCallf312b1e2010-08-26 23:41:50 +00001440 case Sema::PCC_ForInit:
Douglas Gregor02688102010-09-14 23:59:36 +00001441 return LangOpts.CPlusPlus || LangOpts.ObjC1 || LangOpts.C99;
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001442 }
David Blaikie7530c032012-01-17 06:56:22 +00001443
1444 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor4710e5b2010-05-28 00:49:12 +00001445}
1446
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001447static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1448 const Preprocessor &PP) {
1449 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001450 Policy.AnonymousTagLocations = false;
1451 Policy.SuppressStrongLifetime = true;
Douglas Gregor25270b62011-11-03 00:16:13 +00001452 Policy.SuppressUnwrittenScope = true;
Douglas Gregor8ca72082011-10-18 21:20:17 +00001453 return Policy;
1454}
1455
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00001456/// \brief Retrieve a printing policy suitable for code completion.
1457static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1458 return getCompletionPrintingPolicy(S.Context, S.PP);
1459}
1460
Douglas Gregor8ca72082011-10-18 21:20:17 +00001461/// \brief Retrieve the string representation of the given type as a string
1462/// that has the appropriate lifetime for code completion.
1463///
1464/// This routine provides a fast path where we provide constant strings for
1465/// common type names.
1466static const char *GetCompletionTypeString(QualType T,
1467 ASTContext &Context,
1468 const PrintingPolicy &Policy,
1469 CodeCompletionAllocator &Allocator) {
1470 if (!T.getLocalQualifiers()) {
1471 // Built-in type names are constant strings.
1472 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidis27a00972012-05-05 04:20:28 +00001473 return BT->getNameAsCString(Policy);
Douglas Gregor8ca72082011-10-18 21:20:17 +00001474
1475 // Anonymous tag types are constant strings.
1476 if (const TagType *TagT = dyn_cast<TagType>(T))
1477 if (TagDecl *Tag = TagT->getDecl())
John McCall83972f12013-03-09 00:54:27 +00001478 if (!Tag->hasNameForLinkage()) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001479 switch (Tag->getTagKind()) {
1480 case TTK_Struct: return "struct <anonymous>";
Joao Matos6666ed42012-08-31 18:45:21 +00001481 case TTK_Interface: return "__interface <anonymous>";
1482 case TTK_Class: return "class <anonymous>";
Douglas Gregor8ca72082011-10-18 21:20:17 +00001483 case TTK_Union: return "union <anonymous>";
1484 case TTK_Enum: return "enum <anonymous>";
1485 }
1486 }
1487 }
1488
1489 // Slow path: format the type as a string.
1490 std::string Result;
1491 T.getAsStringInternal(Result, Policy);
1492 return Allocator.CopyString(Result);
1493}
1494
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001495/// \brief Add a completion for "this", if we're in a member function.
1496static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1497 QualType ThisTy = S.getCurrentThisType();
1498 if (ThisTy.isNull())
1499 return;
1500
1501 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001502 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001503 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
1504 Builder.AddResultTypeChunk(GetCompletionTypeString(ThisTy,
1505 S.Context,
1506 Policy,
1507 Allocator));
1508 Builder.AddTypedTextChunk("this");
Joao Matos6666ed42012-08-31 18:45:21 +00001509 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001510}
1511
Douglas Gregor01dfea02010-01-10 23:08:15 +00001512/// \brief Add language constructs that show up for "ordinary" names.
John McCallf312b1e2010-08-26 23:41:50 +00001513static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001514 Scope *S,
1515 Sema &SemaRef,
Douglas Gregor01dfea02010-01-10 23:08:15 +00001516 ResultBuilder &Results) {
Douglas Gregor8ca72082011-10-18 21:20:17 +00001517 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00001518 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor8ca72082011-10-18 21:20:17 +00001519 PrintingPolicy Policy = getCompletionPrintingPolicy(SemaRef);
Douglas Gregor218937c2011-02-01 19:23:04 +00001520
John McCall0a2c5e22010-08-25 06:19:51 +00001521 typedef CodeCompletionResult Result;
Douglas Gregor01dfea02010-01-10 23:08:15 +00001522 switch (CCC) {
John McCallf312b1e2010-08-26 23:41:50 +00001523 case Sema::PCC_Namespace:
David Blaikie4e4d0842012-03-11 07:00:24 +00001524 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001525 if (Results.includeCodePatterns()) {
1526 // namespace <identifier> { declarations }
Douglas Gregor218937c2011-02-01 19:23:04 +00001527 Builder.AddTypedTextChunk("namespace");
1528 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1529 Builder.AddPlaceholderChunk("identifier");
1530 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1531 Builder.AddPlaceholderChunk("declarations");
1532 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1533 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1534 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001535 }
1536
Douglas Gregor01dfea02010-01-10 23:08:15 +00001537 // namespace identifier = identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001538 Builder.AddTypedTextChunk("namespace");
1539 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1540 Builder.AddPlaceholderChunk("name");
1541 Builder.AddChunk(CodeCompletionString::CK_Equal);
1542 Builder.AddPlaceholderChunk("namespace");
1543 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001544
1545 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001546 Builder.AddTypedTextChunk("using");
1547 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1548 Builder.AddTextChunk("namespace");
1549 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1550 Builder.AddPlaceholderChunk("identifier");
1551 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001552
1553 // asm(string-literal)
Douglas Gregor218937c2011-02-01 19:23:04 +00001554 Builder.AddTypedTextChunk("asm");
1555 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1556 Builder.AddPlaceholderChunk("string-literal");
1557 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1558 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001559
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001560 if (Results.includeCodePatterns()) {
1561 // Explicit template instantiation
Douglas Gregor218937c2011-02-01 19:23:04 +00001562 Builder.AddTypedTextChunk("template");
1563 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1564 Builder.AddPlaceholderChunk("declaration");
1565 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001566 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001567 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001568
David Blaikie4e4d0842012-03-11 07:00:24 +00001569 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001570 AddObjCTopLevelResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001571
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001572 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001573 // Fall through
1574
John McCallf312b1e2010-08-26 23:41:50 +00001575 case Sema::PCC_Class:
David Blaikie4e4d0842012-03-11 07:00:24 +00001576 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001577 // Using declaration
Douglas Gregor218937c2011-02-01 19:23:04 +00001578 Builder.AddTypedTextChunk("using");
1579 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1580 Builder.AddPlaceholderChunk("qualifier");
1581 Builder.AddTextChunk("::");
1582 Builder.AddPlaceholderChunk("name");
1583 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001584
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001585 // using typename qualifier::name (only in a dependent context)
Douglas Gregor01dfea02010-01-10 23:08:15 +00001586 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001587 Builder.AddTypedTextChunk("using");
1588 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1589 Builder.AddTextChunk("typename");
1590 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1591 Builder.AddPlaceholderChunk("qualifier");
1592 Builder.AddTextChunk("::");
1593 Builder.AddPlaceholderChunk("name");
1594 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001595 }
1596
John McCallf312b1e2010-08-26 23:41:50 +00001597 if (CCC == Sema::PCC_Class) {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001598 AddTypedefResult(Results);
1599
Douglas Gregor01dfea02010-01-10 23:08:15 +00001600 // public:
Douglas Gregor218937c2011-02-01 19:23:04 +00001601 Builder.AddTypedTextChunk("public");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001602 if (Results.includeCodePatterns())
1603 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001604 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001605
1606 // protected:
Douglas Gregor218937c2011-02-01 19:23:04 +00001607 Builder.AddTypedTextChunk("protected");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001608 if (Results.includeCodePatterns())
1609 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001610 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001611
1612 // private:
Douglas Gregor218937c2011-02-01 19:23:04 +00001613 Builder.AddTypedTextChunk("private");
Douglas Gregor10ccf122012-04-10 17:56:28 +00001614 if (Results.includeCodePatterns())
1615 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregor218937c2011-02-01 19:23:04 +00001616 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001617 }
1618 }
1619 // Fall through
1620
John McCallf312b1e2010-08-26 23:41:50 +00001621 case Sema::PCC_Template:
1622 case Sema::PCC_MemberTemplate:
David Blaikie4e4d0842012-03-11 07:00:24 +00001623 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001624 // template < parameters >
Douglas Gregor218937c2011-02-01 19:23:04 +00001625 Builder.AddTypedTextChunk("template");
1626 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1627 Builder.AddPlaceholderChunk("parameters");
1628 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1629 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001630 }
1631
David Blaikie4e4d0842012-03-11 07:00:24 +00001632 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1633 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001634 break;
1635
John McCallf312b1e2010-08-26 23:41:50 +00001636 case Sema::PCC_ObjCInterface:
David Blaikie4e4d0842012-03-11 07:00:24 +00001637 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1638 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1639 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001640 break;
1641
John McCallf312b1e2010-08-26 23:41:50 +00001642 case Sema::PCC_ObjCImplementation:
David Blaikie4e4d0842012-03-11 07:00:24 +00001643 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1644 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1645 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001646 break;
1647
John McCallf312b1e2010-08-26 23:41:50 +00001648 case Sema::PCC_ObjCInstanceVariableList:
David Blaikie4e4d0842012-03-11 07:00:24 +00001649 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00001650 break;
1651
John McCallf312b1e2010-08-26 23:41:50 +00001652 case Sema::PCC_RecoveryInFunction:
1653 case Sema::PCC_Statement: {
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001654 AddTypedefResult(Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001655
David Blaikie4e4d0842012-03-11 07:00:24 +00001656 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1657 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001658 Builder.AddTypedTextChunk("try");
1659 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1660 Builder.AddPlaceholderChunk("statements");
1661 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1662 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1663 Builder.AddTextChunk("catch");
1664 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1665 Builder.AddPlaceholderChunk("declaration");
1666 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1667 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1668 Builder.AddPlaceholderChunk("statements");
1669 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1670 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1671 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001672 }
David Blaikie4e4d0842012-03-11 07:00:24 +00001673 if (SemaRef.getLangOpts().ObjC1)
Douglas Gregorbca403c2010-01-13 23:51:12 +00001674 AddObjCStatementResults(Results, true);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00001675
Douglas Gregord8e8a582010-05-25 21:41:55 +00001676 if (Results.includeCodePatterns()) {
1677 // if (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001678 Builder.AddTypedTextChunk("if");
1679 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001680 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001681 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001682 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001683 Builder.AddPlaceholderChunk("expression");
1684 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1685 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1686 Builder.AddPlaceholderChunk("statements");
1687 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1688 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1689 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001690
Douglas Gregord8e8a582010-05-25 21:41:55 +00001691 // switch (condition) { }
Douglas Gregor218937c2011-02-01 19:23:04 +00001692 Builder.AddTypedTextChunk("switch");
1693 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001694 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001695 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001696 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001697 Builder.AddPlaceholderChunk("expression");
1698 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1699 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1700 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1701 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1702 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001703 }
1704
Douglas Gregor01dfea02010-01-10 23:08:15 +00001705 // Switch-specific statements.
John McCall781472f2010-08-25 08:40:02 +00001706 if (!SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001707 // case expression:
Douglas Gregor218937c2011-02-01 19:23:04 +00001708 Builder.AddTypedTextChunk("case");
1709 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1710 Builder.AddPlaceholderChunk("expression");
1711 Builder.AddChunk(CodeCompletionString::CK_Colon);
1712 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001713
1714 // default:
Douglas Gregor218937c2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("default");
1716 Builder.AddChunk(CodeCompletionString::CK_Colon);
1717 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001718 }
1719
Douglas Gregord8e8a582010-05-25 21:41:55 +00001720 if (Results.includeCodePatterns()) {
1721 /// while (condition) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001722 Builder.AddTypedTextChunk("while");
1723 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001724 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor218937c2011-02-01 19:23:04 +00001725 Builder.AddPlaceholderChunk("condition");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001726 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001727 Builder.AddPlaceholderChunk("expression");
1728 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1729 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1730 Builder.AddPlaceholderChunk("statements");
1731 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1732 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1733 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001734
1735 // do { statements } while ( expression );
Douglas Gregor218937c2011-02-01 19:23:04 +00001736 Builder.AddTypedTextChunk("do");
1737 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1738 Builder.AddPlaceholderChunk("statements");
1739 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1740 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1741 Builder.AddTextChunk("while");
1742 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1743 Builder.AddPlaceholderChunk("expression");
1744 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1745 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001746
Douglas Gregord8e8a582010-05-25 21:41:55 +00001747 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregor218937c2011-02-01 19:23:04 +00001748 Builder.AddTypedTextChunk("for");
1749 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00001750 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregor218937c2011-02-01 19:23:04 +00001751 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregord8e8a582010-05-25 21:41:55 +00001752 else
Douglas Gregor218937c2011-02-01 19:23:04 +00001753 Builder.AddPlaceholderChunk("init-expression");
1754 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1755 Builder.AddPlaceholderChunk("condition");
1756 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1757 Builder.AddPlaceholderChunk("inc-expression");
1758 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1759 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1760 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1761 Builder.AddPlaceholderChunk("statements");
1762 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1763 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1764 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregord8e8a582010-05-25 21:41:55 +00001765 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001766
1767 if (S->getContinueParent()) {
1768 // continue ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001769 Builder.AddTypedTextChunk("continue");
1770 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001771 }
1772
1773 if (S->getBreakParent()) {
1774 // break ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001775 Builder.AddTypedTextChunk("break");
1776 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001777 }
1778
1779 // "return expression ;" or "return ;", depending on whether we
1780 // know the function is void or not.
1781 bool isVoid = false;
1782 if (FunctionDecl *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
1783 isVoid = Function->getResultType()->isVoidType();
1784 else if (ObjCMethodDecl *Method
1785 = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
1786 isVoid = Method->getResultType()->isVoidType();
Douglas Gregor9ea9bdb2010-03-01 23:15:13 +00001787 else if (SemaRef.getCurBlock() &&
1788 !SemaRef.getCurBlock()->ReturnType.isNull())
1789 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregor218937c2011-02-01 19:23:04 +00001790 Builder.AddTypedTextChunk("return");
Douglas Gregor93298002010-02-18 04:06:48 +00001791 if (!isVoid) {
Douglas Gregor218937c2011-02-01 19:23:04 +00001792 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1793 Builder.AddPlaceholderChunk("expression");
Douglas Gregor93298002010-02-18 04:06:48 +00001794 }
Douglas Gregor218937c2011-02-01 19:23:04 +00001795 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001796
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001797 // goto identifier ;
Douglas Gregor218937c2011-02-01 19:23:04 +00001798 Builder.AddTypedTextChunk("goto");
1799 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1800 Builder.AddPlaceholderChunk("label");
1801 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001802
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001803 // Using directives
Douglas Gregor218937c2011-02-01 19:23:04 +00001804 Builder.AddTypedTextChunk("using");
1805 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1806 Builder.AddTextChunk("namespace");
1807 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1808 Builder.AddPlaceholderChunk("identifier");
1809 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001810 }
1811
1812 // Fall through (for statement expressions).
John McCallf312b1e2010-08-26 23:41:50 +00001813 case Sema::PCC_ForInit:
1814 case Sema::PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00001815 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001816 // Fall through: conditions and statements can have expressions.
1817
Douglas Gregor02688102010-09-14 23:59:36 +00001818 case Sema::PCC_ParenthesizedExpression:
David Blaikie4e4d0842012-03-11 07:00:24 +00001819 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCallf85e1932011-06-15 23:02:42 +00001820 CCC == Sema::PCC_ParenthesizedExpression) {
1821 // (__bridge <type>)<expression>
1822 Builder.AddTypedTextChunk("__bridge");
1823 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1824 Builder.AddPlaceholderChunk("type");
1825 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1826 Builder.AddPlaceholderChunk("expression");
1827 Results.AddResult(Result(Builder.TakeString()));
1828
1829 // (__bridge_transfer <Objective-C type>)<expression>
1830 Builder.AddTypedTextChunk("__bridge_transfer");
1831 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1832 Builder.AddPlaceholderChunk("Objective-C type");
1833 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1834 Builder.AddPlaceholderChunk("expression");
1835 Results.AddResult(Result(Builder.TakeString()));
1836
1837 // (__bridge_retained <CF type>)<expression>
1838 Builder.AddTypedTextChunk("__bridge_retained");
1839 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1840 Builder.AddPlaceholderChunk("CF type");
1841 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1842 Builder.AddPlaceholderChunk("expression");
1843 Results.AddResult(Result(Builder.TakeString()));
1844 }
1845 // Fall through
1846
John McCallf312b1e2010-08-26 23:41:50 +00001847 case Sema::PCC_Expression: {
David Blaikie4e4d0842012-03-11 07:00:24 +00001848 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001849 // 'this', if we're in a non-static member function.
Douglas Gregor81f3bff2012-02-15 15:34:24 +00001850 addThisCompletion(SemaRef, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00001851
Douglas Gregor8ca72082011-10-18 21:20:17 +00001852 // true
1853 Builder.AddResultTypeChunk("bool");
1854 Builder.AddTypedTextChunk("true");
1855 Results.AddResult(Result(Builder.TakeString()));
1856
1857 // false
1858 Builder.AddResultTypeChunk("bool");
1859 Builder.AddTypedTextChunk("false");
1860 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001861
David Blaikie4e4d0842012-03-11 07:00:24 +00001862 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001863 // dynamic_cast < type-id > ( expression )
1864 Builder.AddTypedTextChunk("dynamic_cast");
1865 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1866 Builder.AddPlaceholderChunk("type");
1867 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1868 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1869 Builder.AddPlaceholderChunk("expression");
1870 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1871 Results.AddResult(Result(Builder.TakeString()));
1872 }
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001873
1874 // static_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001875 Builder.AddTypedTextChunk("static_cast");
1876 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1877 Builder.AddPlaceholderChunk("type");
1878 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1879 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1880 Builder.AddPlaceholderChunk("expression");
1881 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1882 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001883
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001884 // reinterpret_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001885 Builder.AddTypedTextChunk("reinterpret_cast");
1886 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1887 Builder.AddPlaceholderChunk("type");
1888 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1889 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1890 Builder.AddPlaceholderChunk("expression");
1891 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1892 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001893
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001894 // const_cast < type-id > ( expression )
Douglas Gregor218937c2011-02-01 19:23:04 +00001895 Builder.AddTypedTextChunk("const_cast");
1896 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1897 Builder.AddPlaceholderChunk("type");
1898 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1899 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1900 Builder.AddPlaceholderChunk("expression");
1901 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1902 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001903
David Blaikie4e4d0842012-03-11 07:00:24 +00001904 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001905 // typeid ( expression-or-type )
Douglas Gregor8ca72082011-10-18 21:20:17 +00001906 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001907 Builder.AddTypedTextChunk("typeid");
1908 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1909 Builder.AddPlaceholderChunk("expression-or-type");
1910 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1911 Results.AddResult(Result(Builder.TakeString()));
1912 }
1913
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001914 // new T ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001915 Builder.AddTypedTextChunk("new");
1916 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1917 Builder.AddPlaceholderChunk("type");
1918 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1919 Builder.AddPlaceholderChunk("expressions");
1920 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1921 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001922
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001923 // new T [ ] ( ... )
Douglas Gregor218937c2011-02-01 19:23:04 +00001924 Builder.AddTypedTextChunk("new");
1925 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1926 Builder.AddPlaceholderChunk("type");
1927 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1928 Builder.AddPlaceholderChunk("size");
1929 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1930 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1931 Builder.AddPlaceholderChunk("expressions");
1932 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1933 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001934
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001935 // delete expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001936 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001937 Builder.AddTypedTextChunk("delete");
1938 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1939 Builder.AddPlaceholderChunk("expression");
1940 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001941
Douglas Gregorc8bddde2010-05-28 00:22:41 +00001942 // delete [] expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001943 Builder.AddResultTypeChunk("void");
Douglas Gregor218937c2011-02-01 19:23:04 +00001944 Builder.AddTypedTextChunk("delete");
1945 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1946 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
1947 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
1948 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1949 Builder.AddPlaceholderChunk("expression");
1950 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00001951
David Blaikie4e4d0842012-03-11 07:00:24 +00001952 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorec3310a2011-04-12 02:47:21 +00001953 // throw expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001954 Builder.AddResultTypeChunk("void");
Douglas Gregorec3310a2011-04-12 02:47:21 +00001955 Builder.AddTypedTextChunk("throw");
1956 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1957 Builder.AddPlaceholderChunk("expression");
1958 Results.AddResult(Result(Builder.TakeString()));
1959 }
Douglas Gregora50216c2011-10-18 16:29:03 +00001960
Douglas Gregor12e13132010-05-26 22:00:08 +00001961 // FIXME: Rethrow?
Douglas Gregora50216c2011-10-18 16:29:03 +00001962
Richard Smith80ad52f2013-01-02 11:42:31 +00001963 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregora50216c2011-10-18 16:29:03 +00001964 // nullptr
Douglas Gregor8ca72082011-10-18 21:20:17 +00001965 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001966 Builder.AddTypedTextChunk("nullptr");
1967 Results.AddResult(Result(Builder.TakeString()));
1968
1969 // alignof
Douglas Gregor8ca72082011-10-18 21:20:17 +00001970 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001971 Builder.AddTypedTextChunk("alignof");
1972 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1973 Builder.AddPlaceholderChunk("type");
1974 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1975 Results.AddResult(Result(Builder.TakeString()));
1976
1977 // noexcept
Douglas Gregor8ca72082011-10-18 21:20:17 +00001978 Builder.AddResultTypeChunk("bool");
Douglas Gregora50216c2011-10-18 16:29:03 +00001979 Builder.AddTypedTextChunk("noexcept");
1980 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1981 Builder.AddPlaceholderChunk("expression");
1982 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1983 Results.AddResult(Result(Builder.TakeString()));
1984
1985 // sizeof... expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00001986 Builder.AddResultTypeChunk("size_t");
Douglas Gregora50216c2011-10-18 16:29:03 +00001987 Builder.AddTypedTextChunk("sizeof...");
1988 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1989 Builder.AddPlaceholderChunk("parameter-pack");
1990 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1991 Results.AddResult(Result(Builder.TakeString()));
1992 }
Douglas Gregor01dfea02010-01-10 23:08:15 +00001993 }
1994
David Blaikie4e4d0842012-03-11 07:00:24 +00001995 if (SemaRef.getLangOpts().ObjC1) {
Douglas Gregor01dfea02010-01-10 23:08:15 +00001996 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek681e2562010-05-31 21:43:10 +00001997 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
1998 // The interface can be NULL.
1999 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregor8ca72082011-10-18 21:20:17 +00002000 if (ID->getSuperClass()) {
2001 std::string SuperType;
2002 SuperType = ID->getSuperClass()->getNameAsString();
2003 if (Method->isInstanceMethod())
2004 SuperType += " *";
2005
2006 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2007 Builder.AddTypedTextChunk("super");
2008 Results.AddResult(Result(Builder.TakeString()));
2009 }
Ted Kremenek681e2562010-05-31 21:43:10 +00002010 }
2011
Douglas Gregorbca403c2010-01-13 23:51:12 +00002012 AddObjCExpressionResults(Results, true);
Douglas Gregor01dfea02010-01-10 23:08:15 +00002013 }
2014
Jordan Rosef70a8862012-06-30 21:33:57 +00002015 if (SemaRef.getLangOpts().C11) {
2016 // _Alignof
2017 Builder.AddResultTypeChunk("size_t");
2018 if (SemaRef.getASTContext().Idents.get("alignof").hasMacroDefinition())
2019 Builder.AddTypedTextChunk("alignof");
2020 else
2021 Builder.AddTypedTextChunk("_Alignof");
2022 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2023 Builder.AddPlaceholderChunk("type");
2024 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2025 Results.AddResult(Result(Builder.TakeString()));
2026 }
2027
Douglas Gregorc8bddde2010-05-28 00:22:41 +00002028 // sizeof expression
Douglas Gregor8ca72082011-10-18 21:20:17 +00002029 Builder.AddResultTypeChunk("size_t");
Douglas Gregor218937c2011-02-01 19:23:04 +00002030 Builder.AddTypedTextChunk("sizeof");
2031 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2032 Builder.AddPlaceholderChunk("expression-or-type");
2033 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2034 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor01dfea02010-01-10 23:08:15 +00002035 break;
2036 }
Douglas Gregord32b0222010-08-24 01:06:58 +00002037
John McCallf312b1e2010-08-26 23:41:50 +00002038 case Sema::PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00002039 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregord32b0222010-08-24 01:06:58 +00002040 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00002041 }
2042
David Blaikie4e4d0842012-03-11 07:00:24 +00002043 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2044 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00002045
David Blaikie4e4d0842012-03-11 07:00:24 +00002046 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregora4477812010-01-14 16:01:26 +00002047 Results.AddResult(Result("operator"));
Douglas Gregor01dfea02010-01-10 23:08:15 +00002048}
2049
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002050/// \brief If the given declaration has an associated type, add it as a result
2051/// type chunk.
2052static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002053 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002054 const NamedDecl *ND,
Douglas Gregor218937c2011-02-01 19:23:04 +00002055 CodeCompletionBuilder &Result) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002056 if (!ND)
2057 return;
Douglas Gregor6f942b22010-09-21 16:06:22 +00002058
2059 // Skip constructors and conversion functions, which have their return types
2060 // built into their names.
2061 if (isa<CXXConstructorDecl>(ND) || isa<CXXConversionDecl>(ND))
2062 return;
2063
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002064 // Determine the type of the declaration (if it has a type).
Douglas Gregor6f942b22010-09-21 16:06:22 +00002065 QualType T;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002066 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002067 T = Function->getResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002068 else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002069 T = Method->getResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002070 else if (const FunctionTemplateDecl *FunTmpl =
2071 dyn_cast<FunctionTemplateDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002072 T = FunTmpl->getTemplatedDecl()->getResultType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002073 else if (const EnumConstantDecl *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002074 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
2075 else if (isa<UnresolvedUsingValueDecl>(ND)) {
2076 /* Do nothing: ignore unresolved using declarations*/
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002077 } else if (const ValueDecl *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002078 T = Value->getType();
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002079 } else if (const ObjCPropertyDecl *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002080 T = Property->getType();
2081
2082 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2083 return;
2084
Douglas Gregor8987b232011-09-27 23:30:47 +00002085 Result.AddResultTypeChunk(GetCompletionTypeString(T, Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002086 Result.getAllocator()));
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002087}
2088
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002089static void MaybeAddSentinel(ASTContext &Context,
2090 const NamedDecl *FunctionOrMethod,
Douglas Gregor218937c2011-02-01 19:23:04 +00002091 CodeCompletionBuilder &Result) {
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002092 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2093 if (Sentinel->getSentinel() == 0) {
David Blaikie4e4d0842012-03-11 07:00:24 +00002094 if (Context.getLangOpts().ObjC1 &&
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002095 Context.Idents.get("nil").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002096 Result.AddTextChunk(", nil");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002097 else if (Context.Idents.get("NULL").hasMacroDefinition())
Douglas Gregor218937c2011-02-01 19:23:04 +00002098 Result.AddTextChunk(", NULL");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002099 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002100 Result.AddTextChunk(", (void*)0");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002101 }
2102}
2103
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002104static std::string formatObjCParamQualifiers(unsigned ObjCQuals) {
2105 std::string Result;
2106 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002107 Result += "in ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002108 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002109 Result += "inout ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002110 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002111 Result += "out ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002112 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002113 Result += "bycopy ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002114 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002115 Result += "byref ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002116 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor6ef92092011-11-09 02:13:45 +00002117 Result += "oneway ";
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002118 return Result;
2119}
2120
Douglas Gregor83482d12010-08-24 16:15:59 +00002121static std::string FormatFunctionParameter(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002122 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002123 const ParmVarDecl *Param,
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002124 bool SuppressName = false,
2125 bool SuppressBlock = false) {
Douglas Gregor83482d12010-08-24 16:15:59 +00002126 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2127 if (Param->getType()->isDependentType() ||
2128 !Param->getType()->isBlockPointerType()) {
2129 // The argument for a dependent or non-block parameter is a placeholder
2130 // containing that parameter's type.
2131 std::string Result;
2132
Douglas Gregoraba48082010-08-29 19:47:46 +00002133 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002134 Result = Param->getIdentifier()->getName();
2135
John McCallf85e1932011-06-15 23:02:42 +00002136 Param->getType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002137
2138 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002139 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2140 + Result + ")";
Douglas Gregoraba48082010-08-29 19:47:46 +00002141 if (Param->getIdentifier() && !SuppressName)
Douglas Gregor83482d12010-08-24 16:15:59 +00002142 Result += Param->getIdentifier()->getName();
2143 }
2144 return Result;
2145 }
2146
2147 // The argument for a block pointer parameter is a block literal with
2148 // the appropriate type.
David Blaikie39e6ab42013-02-18 22:06:02 +00002149 FunctionTypeLoc Block;
2150 FunctionProtoTypeLoc BlockProto;
Douglas Gregor83482d12010-08-24 16:15:59 +00002151 TypeLoc TL;
2152 if (TypeSourceInfo *TSInfo = Param->getTypeSourceInfo()) {
2153 TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2154 while (true) {
2155 // Look through typedefs.
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002156 if (!SuppressBlock) {
David Blaikie39e6ab42013-02-18 22:06:02 +00002157 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2158 if (TypeSourceInfo *InnerTSInfo =
2159 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002160 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2161 continue;
2162 }
2163 }
2164
2165 // Look through qualified types
David Blaikie39e6ab42013-02-18 22:06:02 +00002166 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2167 TL = QualifiedTL.getUnqualifiedLoc();
Douglas Gregor83482d12010-08-24 16:15:59 +00002168 continue;
2169 }
2170 }
2171
Douglas Gregor83482d12010-08-24 16:15:59 +00002172 // Try to get the function prototype behind the block pointer type,
2173 // then we're done.
David Blaikie39e6ab42013-02-18 22:06:02 +00002174 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2175 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2176 Block = TL.getAs<FunctionTypeLoc>();
2177 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
Douglas Gregor83482d12010-08-24 16:15:59 +00002178 }
2179 break;
2180 }
2181 }
2182
2183 if (!Block) {
2184 // We were unable to find a FunctionProtoTypeLoc with parameter names
2185 // for the block; just use the parameter type as a placeholder.
2186 std::string Result;
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002187 if (!ObjCMethodParam && Param->getIdentifier())
2188 Result = Param->getIdentifier()->getName();
2189
John McCallf85e1932011-06-15 23:02:42 +00002190 Param->getType().getUnqualifiedType().getAsStringInternal(Result, Policy);
Douglas Gregor83482d12010-08-24 16:15:59 +00002191
2192 if (ObjCMethodParam) {
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002193 Result = "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier())
2194 + Result + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002195 if (Param->getIdentifier())
2196 Result += Param->getIdentifier()->getName();
2197 }
2198
2199 return Result;
2200 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002201
Douglas Gregor83482d12010-08-24 16:15:59 +00002202 // We have the function prototype behind the block pointer type, as it was
2203 // written in the source.
Douglas Gregor38276252010-09-08 22:47:51 +00002204 std::string Result;
David Blaikie39e6ab42013-02-18 22:06:02 +00002205 QualType ResultType = Block.getTypePtr()->getResultType();
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002206 if (!ResultType->isVoidType() || SuppressBlock)
John McCallf85e1932011-06-15 23:02:42 +00002207 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002208
2209 // Format the parameter list.
2210 std::string Params;
David Blaikie39e6ab42013-02-18 22:06:02 +00002211 if (!BlockProto || Block.getNumArgs() == 0) {
2212 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002213 Params = "(...)";
Douglas Gregorc2760bc2010-10-02 23:49:58 +00002214 else
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002215 Params = "(void)";
Douglas Gregor38276252010-09-08 22:47:51 +00002216 } else {
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002217 Params += "(";
David Blaikie39e6ab42013-02-18 22:06:02 +00002218 for (unsigned I = 0, N = Block.getNumArgs(); I != N; ++I) {
Douglas Gregor38276252010-09-08 22:47:51 +00002219 if (I)
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002220 Params += ", ";
David Blaikie39e6ab42013-02-18 22:06:02 +00002221 Params += FormatFunctionParameter(Context, Policy, Block.getArg(I),
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002222 /*SuppressName=*/false,
2223 /*SuppressBlock=*/true);
Douglas Gregor38276252010-09-08 22:47:51 +00002224
David Blaikie39e6ab42013-02-18 22:06:02 +00002225 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002226 Params += ", ...";
Douglas Gregor38276252010-09-08 22:47:51 +00002227 }
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002228 Params += ")";
Douglas Gregore17794f2010-08-31 05:13:43 +00002229 }
Douglas Gregor38276252010-09-08 22:47:51 +00002230
Douglas Gregoree1c68a2011-10-18 04:23:19 +00002231 if (SuppressBlock) {
2232 // Format as a parameter.
2233 Result = Result + " (^";
2234 if (Param->getIdentifier())
2235 Result += Param->getIdentifier()->getName();
2236 Result += ")";
2237 Result += Params;
2238 } else {
2239 // Format as a block literal argument.
2240 Result = '^' + Result;
2241 Result += Params;
2242
2243 if (Param->getIdentifier())
2244 Result += Param->getIdentifier()->getName();
2245 }
2246
Douglas Gregor83482d12010-08-24 16:15:59 +00002247 return Result;
2248}
2249
Douglas Gregor86d9a522009-09-21 16:56:56 +00002250/// \brief Add function parameter chunks to the given code completion string.
2251static void AddFunctionParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002252 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002253 const FunctionDecl *Function,
Douglas Gregor218937c2011-02-01 19:23:04 +00002254 CodeCompletionBuilder &Result,
2255 unsigned Start = 0,
2256 bool InOptional = false) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002257 bool FirstParameter = true;
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002258
Douglas Gregor218937c2011-02-01 19:23:04 +00002259 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002260 const ParmVarDecl *Param = Function->getParamDecl(P);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002261
Douglas Gregor218937c2011-02-01 19:23:04 +00002262 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002263 // When we see an optional default argument, put that argument and
2264 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002265 CodeCompletionBuilder Opt(Result.getAllocator(),
2266 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002267 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002268 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002269 AddFunctionParameterChunks(Context, Policy, Function, Opt, P, true);
Douglas Gregor218937c2011-02-01 19:23:04 +00002270 Result.AddOptionalChunk(Opt.TakeString());
2271 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002272 }
2273
Douglas Gregor218937c2011-02-01 19:23:04 +00002274 if (FirstParameter)
2275 FirstParameter = false;
2276 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002277 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor218937c2011-02-01 19:23:04 +00002278
2279 InOptional = false;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002280
2281 // Format the placeholder string.
Douglas Gregor8987b232011-09-27 23:30:47 +00002282 std::string PlaceholderStr = FormatFunctionParameter(Context, Policy,
2283 Param);
Douglas Gregor83482d12010-08-24 16:15:59 +00002284
Douglas Gregore17794f2010-08-31 05:13:43 +00002285 if (Function->isVariadic() && P == N - 1)
2286 PlaceholderStr += ", ...";
2287
Douglas Gregor86d9a522009-09-21 16:56:56 +00002288 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002289 Result.AddPlaceholderChunk(
2290 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002291 }
Douglas Gregorb3d45252009-09-22 21:42:17 +00002292
2293 if (const FunctionProtoType *Proto
2294 = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002295 if (Proto->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002296 if (Proto->getNumArgs() == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00002297 Result.AddPlaceholderChunk("...");
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002298
Douglas Gregor218937c2011-02-01 19:23:04 +00002299 MaybeAddSentinel(Context, Function, Result);
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002300 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002301}
2302
2303/// \brief Add template parameter chunks to the given code completion string.
2304static void AddTemplateParameterChunks(ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00002305 const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002306 const TemplateDecl *Template,
Douglas Gregor218937c2011-02-01 19:23:04 +00002307 CodeCompletionBuilder &Result,
2308 unsigned MaxParameters = 0,
2309 unsigned Start = 0,
2310 bool InDefaultArg = false) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002311 bool FirstParameter = true;
2312
2313 TemplateParameterList *Params = Template->getTemplateParameters();
2314 TemplateParameterList::iterator PEnd = Params->end();
2315 if (MaxParameters)
2316 PEnd = Params->begin() + MaxParameters;
Douglas Gregor218937c2011-02-01 19:23:04 +00002317 for (TemplateParameterList::iterator P = Params->begin() + Start;
2318 P != PEnd; ++P) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002319 bool HasDefaultArg = false;
2320 std::string PlaceholderStr;
2321 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2322 if (TTP->wasDeclaredWithTypename())
2323 PlaceholderStr = "typename";
2324 else
2325 PlaceholderStr = "class";
2326
2327 if (TTP->getIdentifier()) {
2328 PlaceholderStr += ' ';
2329 PlaceholderStr += TTP->getIdentifier()->getName();
2330 }
2331
2332 HasDefaultArg = TTP->hasDefaultArgument();
2333 } else if (NonTypeTemplateParmDecl *NTTP
Douglas Gregor218937c2011-02-01 19:23:04 +00002334 = dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002335 if (NTTP->getIdentifier())
2336 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCallf85e1932011-06-15 23:02:42 +00002337 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002338 HasDefaultArg = NTTP->hasDefaultArgument();
2339 } else {
2340 assert(isa<TemplateTemplateParmDecl>(*P));
2341 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
2342
2343 // Since putting the template argument list into the placeholder would
2344 // be very, very long, we just use an abbreviation.
2345 PlaceholderStr = "template<...> class";
2346 if (TTP->getIdentifier()) {
2347 PlaceholderStr += ' ';
2348 PlaceholderStr += TTP->getIdentifier()->getName();
2349 }
2350
2351 HasDefaultArg = TTP->hasDefaultArgument();
2352 }
2353
Douglas Gregor218937c2011-02-01 19:23:04 +00002354 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00002355 // When we see an optional default argument, put that argument and
2356 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002357 CodeCompletionBuilder Opt(Result.getAllocator(),
2358 Result.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00002359 if (!FirstParameter)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002360 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor8987b232011-09-27 23:30:47 +00002361 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregor218937c2011-02-01 19:23:04 +00002362 P - Params->begin(), true);
2363 Result.AddOptionalChunk(Opt.TakeString());
2364 break;
Douglas Gregor86d9a522009-09-21 16:56:56 +00002365 }
2366
Douglas Gregor218937c2011-02-01 19:23:04 +00002367 InDefaultArg = false;
2368
Douglas Gregor86d9a522009-09-21 16:56:56 +00002369 if (FirstParameter)
2370 FirstParameter = false;
2371 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002372 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002373
2374 // Add the placeholder string.
Douglas Gregordae68752011-02-01 22:57:45 +00002375 Result.AddPlaceholderChunk(
2376 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor86d9a522009-09-21 16:56:56 +00002377 }
2378}
2379
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002380/// \brief Add a qualifier to the given code-completion string, if the
2381/// provided nested-name-specifier is non-NULL.
Douglas Gregora61a8792009-12-11 18:44:16 +00002382static void
Douglas Gregor218937c2011-02-01 19:23:04 +00002383AddQualifierToCompletionString(CodeCompletionBuilder &Result,
Douglas Gregora61a8792009-12-11 18:44:16 +00002384 NestedNameSpecifier *Qualifier,
2385 bool QualifierIsInformative,
Douglas Gregor8987b232011-09-27 23:30:47 +00002386 ASTContext &Context,
2387 const PrintingPolicy &Policy) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002388 if (!Qualifier)
2389 return;
2390
2391 std::string PrintedNNS;
2392 {
2393 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor8987b232011-09-27 23:30:47 +00002394 Qualifier->print(OS, Policy);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002395 }
Douglas Gregor0563c262009-09-22 23:15:58 +00002396 if (QualifierIsInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002397 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor0563c262009-09-22 23:15:58 +00002398 else
Douglas Gregordae68752011-02-01 22:57:45 +00002399 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00002400}
2401
Douglas Gregor218937c2011-02-01 19:23:04 +00002402static void
2403AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002404 const FunctionDecl *Function) {
Douglas Gregora61a8792009-12-11 18:44:16 +00002405 const FunctionProtoType *Proto
2406 = Function->getType()->getAs<FunctionProtoType>();
2407 if (!Proto || !Proto->getTypeQuals())
2408 return;
2409
Douglas Gregora63f6de2011-02-01 21:15:40 +00002410 // FIXME: Add ref-qualifier!
2411
2412 // Handle single qualifiers without copying
2413 if (Proto->getTypeQuals() == Qualifiers::Const) {
2414 Result.AddInformativeChunk(" const");
2415 return;
2416 }
2417
2418 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
2419 Result.AddInformativeChunk(" volatile");
2420 return;
2421 }
2422
2423 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
2424 Result.AddInformativeChunk(" restrict");
2425 return;
2426 }
2427
2428 // Handle multiple qualifiers.
Douglas Gregora61a8792009-12-11 18:44:16 +00002429 std::string QualsStr;
David Blaikie4ef832f2012-08-10 00:55:35 +00002430 if (Proto->isConst())
Douglas Gregora61a8792009-12-11 18:44:16 +00002431 QualsStr += " const";
David Blaikie4ef832f2012-08-10 00:55:35 +00002432 if (Proto->isVolatile())
Douglas Gregora61a8792009-12-11 18:44:16 +00002433 QualsStr += " volatile";
David Blaikie4ef832f2012-08-10 00:55:35 +00002434 if (Proto->isRestrict())
Douglas Gregora61a8792009-12-11 18:44:16 +00002435 QualsStr += " restrict";
Douglas Gregordae68752011-02-01 22:57:45 +00002436 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregora61a8792009-12-11 18:44:16 +00002437}
2438
Douglas Gregor6f942b22010-09-21 16:06:22 +00002439/// \brief Add the name of the given declaration
Douglas Gregor8987b232011-09-27 23:30:47 +00002440static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002441 const NamedDecl *ND,
2442 CodeCompletionBuilder &Result) {
Douglas Gregor6f942b22010-09-21 16:06:22 +00002443 DeclarationName Name = ND->getDeclName();
2444 if (!Name)
2445 return;
2446
2447 switch (Name.getNameKind()) {
Douglas Gregora63f6de2011-02-01 21:15:40 +00002448 case DeclarationName::CXXOperatorName: {
2449 const char *OperatorName = 0;
2450 switch (Name.getCXXOverloadedOperator()) {
2451 case OO_None:
2452 case OO_Conditional:
2453 case NUM_OVERLOADED_OPERATORS:
2454 OperatorName = "operator";
2455 break;
2456
2457#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
2458 case OO_##Name: OperatorName = "operator" Spelling; break;
2459#define OVERLOADED_OPERATOR_MULTI(Name,Spelling,Unary,Binary,MemberOnly)
2460#include "clang/Basic/OperatorKinds.def"
2461
2462 case OO_New: OperatorName = "operator new"; break;
2463 case OO_Delete: OperatorName = "operator delete"; break;
2464 case OO_Array_New: OperatorName = "operator new[]"; break;
2465 case OO_Array_Delete: OperatorName = "operator delete[]"; break;
2466 case OO_Call: OperatorName = "operator()"; break;
2467 case OO_Subscript: OperatorName = "operator[]"; break;
2468 }
2469 Result.AddTypedTextChunk(OperatorName);
2470 break;
2471 }
2472
Douglas Gregor6f942b22010-09-21 16:06:22 +00002473 case DeclarationName::Identifier:
2474 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor6f942b22010-09-21 16:06:22 +00002475 case DeclarationName::CXXDestructorName:
2476 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregordae68752011-02-01 22:57:45 +00002477 Result.AddTypedTextChunk(
2478 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002479 break;
2480
2481 case DeclarationName::CXXUsingDirective:
2482 case DeclarationName::ObjCZeroArgSelector:
2483 case DeclarationName::ObjCOneArgSelector:
2484 case DeclarationName::ObjCMultiArgSelector:
2485 break;
2486
2487 case DeclarationName::CXXConstructorName: {
2488 CXXRecordDecl *Record = 0;
2489 QualType Ty = Name.getCXXNameType();
2490 if (const RecordType *RecordTy = Ty->getAs<RecordType>())
2491 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
2492 else if (const InjectedClassNameType *InjectedTy
2493 = Ty->getAs<InjectedClassNameType>())
2494 Record = InjectedTy->getDecl();
2495 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002496 Result.AddTypedTextChunk(
2497 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002498 break;
2499 }
2500
Douglas Gregordae68752011-02-01 22:57:45 +00002501 Result.AddTypedTextChunk(
2502 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor6f942b22010-09-21 16:06:22 +00002503 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002504 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor8987b232011-09-27 23:30:47 +00002505 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002506 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002507 }
2508 break;
2509 }
2510 }
2511}
2512
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002513CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002514 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002515 CodeCompletionTUInfo &CCTUInfo,
2516 bool IncludeBriefComments) {
2517 return CreateCodeCompletionString(S.Context, S.PP, Allocator, CCTUInfo,
2518 IncludeBriefComments);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002519}
2520
Douglas Gregor86d9a522009-09-21 16:56:56 +00002521/// \brief If possible, create a new code completion string for the given
2522/// result.
2523///
2524/// \returns Either a new, heap-allocated code completion string describing
2525/// how to use this result, or NULL to indicate that the string or name of the
2526/// result is all that is needed.
2527CodeCompletionString *
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002528CodeCompletionResult::CreateCodeCompletionString(ASTContext &Ctx,
2529 Preprocessor &PP,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002530 CodeCompletionAllocator &Allocator,
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002531 CodeCompletionTUInfo &CCTUInfo,
2532 bool IncludeBriefComments) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002533 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002534
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002535 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregor218937c2011-02-01 19:23:04 +00002536 if (Kind == RK_Pattern) {
2537 Pattern->Priority = Priority;
2538 Pattern->Availability = Availability;
Douglas Gregorba103062012-03-27 23:34:16 +00002539
2540 if (Declaration) {
2541 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregorba103062012-03-27 23:34:16 +00002542 Pattern->ParentName = Result.getParentName();
Fariborz Jahanianc02ddb22013-03-22 17:55:27 +00002543 // Provide code completion comment for self.GetterName where
2544 // GetterName is the getter method for a property with name
2545 // different from the property name (declared via a property
2546 // getter attribute.
2547 const NamedDecl *ND = Declaration;
2548 if (const ObjCMethodDecl *M = dyn_cast<ObjCMethodDecl>(ND))
2549 if (M->isPropertyAccessor())
2550 if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl())
2551 if (PDecl->getGetterName() == M->getSelector() &&
Fariborz Jahanian16861372013-03-23 01:10:45 +00002552 PDecl->getIdentifier() != M->getIdentifier()) {
2553 if (const RawComment *RC =
2554 Ctx.getRawCommentForAnyRedecl(M)) {
Fariborz Jahanianc02ddb22013-03-22 17:55:27 +00002555 Result.addBriefComment(RC->getBriefText(Ctx));
2556 Pattern->BriefComment = Result.getBriefComment();
2557 }
Fariborz Jahanian16861372013-03-23 01:10:45 +00002558 else if (const RawComment *RC =
2559 Ctx.getRawCommentForAnyRedecl(PDecl)) {
2560 Result.addBriefComment(RC->getBriefText(Ctx));
2561 Pattern->BriefComment = Result.getBriefComment();
2562 }
2563 }
Douglas Gregorba103062012-03-27 23:34:16 +00002564 }
2565
Douglas Gregor218937c2011-02-01 19:23:04 +00002566 return Pattern;
2567 }
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002568
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002569 if (Kind == RK_Keyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00002570 Result.AddTypedTextChunk(Keyword);
2571 return Result.TakeString();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002572 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00002573
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002574 if (Kind == RK_Macro) {
Argyrios Kyrtzidis9818a1d2013-02-20 00:54:57 +00002575 const MacroDirective *MD = PP.getMacroDirectiveHistory(Macro);
2576 assert(MD && "Not a macro?");
Argyrios Kyrtzidisc56fff72013-03-26 17:17:01 +00002577 const MacroInfo *MI = MD->getMacroInfo();
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002578
Douglas Gregordae68752011-02-01 22:57:45 +00002579 Result.AddTypedTextChunk(
2580 Result.getAllocator().CopyString(Macro->getName()));
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002581
2582 if (!MI->isFunctionLike())
Douglas Gregor218937c2011-02-01 19:23:04 +00002583 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002584
2585 // Format a function-like macro with placeholders for the arguments.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002586 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregore4244702011-07-30 08:17:44 +00002587 MacroInfo::arg_iterator A = MI->arg_begin(), AEnd = MI->arg_end();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002588
2589 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2590 if (MI->isC99Varargs()) {
2591 --AEnd;
2592
2593 if (A == AEnd) {
2594 Result.AddPlaceholderChunk("...");
2595 }
Douglas Gregore4244702011-07-30 08:17:44 +00002596 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002597
Douglas Gregore4244702011-07-30 08:17:44 +00002598 for (MacroInfo::arg_iterator A = MI->arg_begin(); A != AEnd; ++A) {
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002599 if (A != MI->arg_begin())
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002600 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002601
2602 if (MI->isVariadic() && (A+1) == AEnd) {
Dylan Noblesmithf7ccbad2012-02-05 02:13:05 +00002603 SmallString<32> Arg = (*A)->getName();
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002604 if (MI->isC99Varargs())
2605 Arg += ", ...";
2606 else
2607 Arg += "...";
Douglas Gregordae68752011-02-01 22:57:45 +00002608 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002609 break;
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002610 }
Douglas Gregorc8dc1352012-01-21 00:43:38 +00002611
2612 // Non-variadic macros are simple.
2613 Result.AddPlaceholderChunk(
2614 Result.getAllocator().CopyString((*A)->getName()));
Douglas Gregore4244702011-07-30 08:17:44 +00002615 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002616 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002617 return Result.TakeString();
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002618 }
2619
Douglas Gregord8e8a582010-05-25 21:41:55 +00002620 assert(Kind == RK_Declaration && "Missed a result kind?");
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002621 const NamedDecl *ND = Declaration;
Douglas Gregorba103062012-03-27 23:34:16 +00002622 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002623
2624 if (IncludeBriefComments) {
2625 // Add documentation comment, if it exists.
Dmitri Gribenkof50555e2012-08-11 00:51:43 +00002626 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) {
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002627 Result.addBriefComment(RC->getBriefText(Ctx));
Fariborz Jahanianb98f7af2013-02-28 17:47:14 +00002628 }
2629 else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
2630 if (OMD->isPropertyAccessor())
2631 if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl())
2632 if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
2633 Result.addBriefComment(RC->getBriefText(Ctx));
Dmitri Gribenkod99ef532012-07-02 17:35:10 +00002634 }
2635
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002636 if (StartsNestedNameSpecifier) {
Douglas Gregordae68752011-02-01 22:57:45 +00002637 Result.AddTypedTextChunk(
2638 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002639 Result.AddTextChunk("::");
2640 return Result.TakeString();
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002641 }
Erik Verbruggen6164ea12011-10-14 15:31:08 +00002642
2643 for (Decl::attr_iterator i = ND->attr_begin(); i != ND->attr_end(); ++i) {
2644 if (AnnotateAttr *Attr = dyn_cast_or_null<AnnotateAttr>(*i)) {
2645 Result.AddAnnotation(Result.getAllocator().CopyString(Attr->getAnnotation()));
2646 }
2647 }
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002648
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002649 AddResultTypeChunk(Ctx, Policy, ND, Result);
Douglas Gregorff5ce6e2009-12-18 18:53:37 +00002650
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002651 if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002652 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002653 Ctx, Policy);
2654 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002655 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002656 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002657 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002658 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002659 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002660 }
2661
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002662 if (const FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002663 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002664 Ctx, Policy);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002665 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002666 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor6f942b22010-09-21 16:06:22 +00002667
Douglas Gregor86d9a522009-09-21 16:56:56 +00002668 // Figure out which template parameters are deduced (or have default
2669 // arguments).
Benjamin Kramer013b3662012-01-30 16:17:39 +00002670 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002671 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002672 unsigned LastDeducibleArgument;
2673 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
2674 --LastDeducibleArgument) {
2675 if (!Deduced[LastDeducibleArgument - 1]) {
2676 // C++0x: Figure out if the template argument has a default. If so,
2677 // the user doesn't need to type this argument.
2678 // FIXME: We need to abstract template parameters better!
2679 bool HasDefaultArg = false;
2680 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Douglas Gregor218937c2011-02-01 19:23:04 +00002681 LastDeducibleArgument - 1);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002682 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
2683 HasDefaultArg = TTP->hasDefaultArgument();
2684 else if (NonTypeTemplateParmDecl *NTTP
2685 = dyn_cast<NonTypeTemplateParmDecl>(Param))
2686 HasDefaultArg = NTTP->hasDefaultArgument();
2687 else {
2688 assert(isa<TemplateTemplateParmDecl>(Param));
2689 HasDefaultArg
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002690 = cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002691 }
2692
2693 if (!HasDefaultArg)
2694 break;
2695 }
2696 }
2697
2698 if (LastDeducibleArgument) {
2699 // Some of the function template arguments cannot be deduced from a
2700 // function call, so we introduce an explicit template argument list
2701 // containing all of the arguments up to the first deducible argument.
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002702 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002703 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor86d9a522009-09-21 16:56:56 +00002704 LastDeducibleArgument);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002705 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor86d9a522009-09-21 16:56:56 +00002706 }
2707
2708 // Add the function parameters
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002709 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002710 AddFunctionParameterChunks(Ctx, Policy, Function, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002711 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregora61a8792009-12-11 18:44:16 +00002712 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregor218937c2011-02-01 19:23:04 +00002713 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002714 }
2715
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002716 if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(ND)) {
Douglas Gregor0563c262009-09-22 23:15:58 +00002717 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002718 Ctx, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00002719 Result.AddTypedTextChunk(
2720 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002721 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002722 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002723 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor218937c2011-02-01 19:23:04 +00002724 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002725 }
2726
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002727 if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregor9630eb62009-11-17 16:44:22 +00002728 Selector Sel = Method->getSelector();
2729 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00002730 Result.AddTypedTextChunk(Result.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00002731 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00002732 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002733 }
2734
Douglas Gregor813d8342011-02-18 22:29:55 +00002735 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregord3c68542009-11-19 01:08:35 +00002736 SelName += ':';
2737 if (StartParameter == 0)
Douglas Gregordae68752011-02-01 22:57:45 +00002738 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002739 else {
Douglas Gregordae68752011-02-01 22:57:45 +00002740 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregord3c68542009-11-19 01:08:35 +00002741
2742 // If there is only one parameter, and we're past it, add an empty
2743 // typed-text chunk since there is nothing to type.
2744 if (Method->param_size() == 1)
Douglas Gregor218937c2011-02-01 19:23:04 +00002745 Result.AddTypedTextChunk("");
Douglas Gregord3c68542009-11-19 01:08:35 +00002746 }
Douglas Gregor9630eb62009-11-17 16:44:22 +00002747 unsigned Idx = 0;
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00002748 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
2749 PEnd = Method->param_end();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002750 P != PEnd; (void)++P, ++Idx) {
2751 if (Idx > 0) {
Douglas Gregord3c68542009-11-19 01:08:35 +00002752 std::string Keyword;
2753 if (Idx > StartParameter)
Douglas Gregor218937c2011-02-01 19:23:04 +00002754 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor9630eb62009-11-17 16:44:22 +00002755 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramera0651c52011-07-26 16:59:25 +00002756 Keyword += II->getName();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002757 Keyword += ":";
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002758 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002759 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002760 else
Douglas Gregordae68752011-02-01 22:57:45 +00002761 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002762 }
Douglas Gregord3c68542009-11-19 01:08:35 +00002763
2764 // If we're before the starting parameter, skip the placeholder.
2765 if (Idx < StartParameter)
2766 continue;
Douglas Gregor9630eb62009-11-17 16:44:22 +00002767
2768 std::string Arg;
Douglas Gregor83482d12010-08-24 16:15:59 +00002769
2770 if ((*P)->getType()->isBlockPointerType() && !DeclaringEntity)
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002771 Arg = FormatFunctionParameter(Ctx, Policy, *P, true);
Douglas Gregor83482d12010-08-24 16:15:59 +00002772 else {
John McCallf85e1932011-06-15 23:02:42 +00002773 (*P)->getType().getAsStringInternal(Arg, Policy);
Douglas Gregor6fa14dd2011-07-30 07:55:26 +00002774 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier())
2775 + Arg + ")";
Douglas Gregor83482d12010-08-24 16:15:59 +00002776 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregoraba48082010-08-29 19:47:46 +00002777 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramera0651c52011-07-26 16:59:25 +00002778 Arg += II->getName();
Douglas Gregor83482d12010-08-24 16:15:59 +00002779 }
2780
Douglas Gregore17794f2010-08-31 05:13:43 +00002781 if (Method->isVariadic() && (P + 1) == PEnd)
2782 Arg += ", ...";
2783
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002784 if (DeclaringEntity)
Douglas Gregordae68752011-02-01 22:57:45 +00002785 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor1f5537a2010-07-08 23:20:03 +00002786 else if (AllParametersAreInformative)
Douglas Gregordae68752011-02-01 22:57:45 +00002787 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor4ad96852009-11-19 07:41:15 +00002788 else
Douglas Gregordae68752011-02-01 22:57:45 +00002789 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor9630eb62009-11-17 16:44:22 +00002790 }
2791
Douglas Gregor2a17af02009-12-23 00:21:46 +00002792 if (Method->isVariadic()) {
Douglas Gregore17794f2010-08-31 05:13:43 +00002793 if (Method->param_size() == 0) {
2794 if (DeclaringEntity)
Douglas Gregor218937c2011-02-01 19:23:04 +00002795 Result.AddTextChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002796 else if (AllParametersAreInformative)
Douglas Gregor218937c2011-02-01 19:23:04 +00002797 Result.AddInformativeChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002798 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002799 Result.AddPlaceholderChunk(", ...");
Douglas Gregore17794f2010-08-31 05:13:43 +00002800 }
Douglas Gregoraaa107a2010-08-23 23:51:41 +00002801
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002802 MaybeAddSentinel(Ctx, Method, Result);
Douglas Gregor2a17af02009-12-23 00:21:46 +00002803 }
2804
Douglas Gregor218937c2011-02-01 19:23:04 +00002805 return Result.TakeString();
Douglas Gregor9630eb62009-11-17 16:44:22 +00002806 }
2807
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002808 if (Qualifier)
Douglas Gregor0563c262009-09-22 23:15:58 +00002809 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidisea8c59a2012-01-17 02:15:51 +00002810 Ctx, Policy);
Douglas Gregor2b4074f2009-12-01 05:55:20 +00002811
Douglas Gregordae68752011-02-01 22:57:45 +00002812 Result.AddTypedTextChunk(
2813 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor218937c2011-02-01 19:23:04 +00002814 return Result.TakeString();
Douglas Gregor86d9a522009-09-21 16:56:56 +00002815}
2816
Douglas Gregor86d802e2009-09-23 00:34:09 +00002817CodeCompletionString *
2818CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
2819 unsigned CurrentArg,
Douglas Gregor32be4a52010-10-11 21:37:58 +00002820 Sema &S,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002821 CodeCompletionAllocator &Allocator,
2822 CodeCompletionTUInfo &CCTUInfo) const {
Douglas Gregor8987b232011-09-27 23:30:47 +00002823 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCallf85e1932011-06-15 23:02:42 +00002824
Douglas Gregor218937c2011-02-01 19:23:04 +00002825 // FIXME: Set priority, availability appropriately.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00002826 CodeCompletionBuilder Result(Allocator,CCTUInfo, 1, CXAvailability_Available);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002827 FunctionDecl *FDecl = getFunction();
Douglas Gregor8987b232011-09-27 23:30:47 +00002828 AddResultTypeChunk(S.Context, Policy, FDecl, Result);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002829 const FunctionProtoType *Proto
2830 = dyn_cast<FunctionProtoType>(getFunctionType());
2831 if (!FDecl && !Proto) {
2832 // Function without a prototype. Just give the return type and a
2833 // highlighted ellipsis.
2834 const FunctionType *FT = getFunctionType();
Douglas Gregora63f6de2011-02-01 21:15:40 +00002835 Result.AddTextChunk(GetCompletionTypeString(FT->getResultType(),
Douglas Gregor8987b232011-09-27 23:30:47 +00002836 S.Context, Policy,
Douglas Gregora63f6de2011-02-01 21:15:40 +00002837 Result.getAllocator()));
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002838 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2839 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
2840 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor218937c2011-02-01 19:23:04 +00002841 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002842 }
2843
2844 if (FDecl)
Douglas Gregordae68752011-02-01 22:57:45 +00002845 Result.AddTextChunk(
2846 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002847 else
Douglas Gregor218937c2011-02-01 19:23:04 +00002848 Result.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00002849 Result.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00002850 Proto->getResultType().getAsString(Policy)));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002851
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002852 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002853 unsigned NumParams = FDecl? FDecl->getNumParams() : Proto->getNumArgs();
2854 for (unsigned I = 0; I != NumParams; ++I) {
2855 if (I)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002856 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002857
2858 std::string ArgString;
2859 QualType ArgType;
2860
2861 if (FDecl) {
2862 ArgString = FDecl->getParamDecl(I)->getNameAsString();
2863 ArgType = FDecl->getParamDecl(I)->getOriginalType();
2864 } else {
2865 ArgType = Proto->getArgType(I);
2866 }
2867
John McCallf85e1932011-06-15 23:02:42 +00002868 ArgType.getAsStringInternal(ArgString, Policy);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002869
2870 if (I == CurrentArg)
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002871 Result.AddChunk(CodeCompletionString::CK_CurrentParameter,
2872 Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002873 else
Douglas Gregordae68752011-02-01 22:57:45 +00002874 Result.AddTextChunk(Result.getAllocator().CopyString(ArgString));
Douglas Gregor86d802e2009-09-23 00:34:09 +00002875 }
2876
2877 if (Proto && Proto->isVariadic()) {
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002878 Result.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002879 if (CurrentArg < NumParams)
Douglas Gregor218937c2011-02-01 19:23:04 +00002880 Result.AddTextChunk("...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002881 else
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002882 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
Douglas Gregor86d802e2009-09-23 00:34:09 +00002883 }
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00002884 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor86d802e2009-09-23 00:34:09 +00002885
Douglas Gregor218937c2011-02-01 19:23:04 +00002886 return Result.TakeString();
Douglas Gregor86d802e2009-09-23 00:34:09 +00002887}
2888
Chris Lattner5f9e2722011-07-23 10:55:15 +00002889unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregorb05496d2010-09-20 21:11:48 +00002890 const LangOptions &LangOpts,
Douglas Gregor1827e102010-08-16 16:18:59 +00002891 bool PreferredTypeIsPointer) {
2892 unsigned Priority = CCP_Macro;
2893
Douglas Gregorb05496d2010-09-20 21:11:48 +00002894 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
2895 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
2896 MacroName.equals("Nil")) {
Douglas Gregor1827e102010-08-16 16:18:59 +00002897 Priority = CCP_Constant;
2898 if (PreferredTypeIsPointer)
2899 Priority = Priority / CCF_SimilarTypeMatch;
Douglas Gregorb05496d2010-09-20 21:11:48 +00002900 }
2901 // Treat "YES", "NO", "true", and "false" as constants.
2902 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
2903 MacroName.equals("true") || MacroName.equals("false"))
2904 Priority = CCP_Constant;
2905 // Treat "bool" as a type.
2906 else if (MacroName.equals("bool"))
2907 Priority = CCP_Type + (LangOpts.ObjC1? CCD_bool_in_ObjC : 0);
2908
Douglas Gregor1827e102010-08-16 16:18:59 +00002909
2910 return Priority;
2911}
2912
Dmitri Gribenko06d8c602013-01-11 20:32:41 +00002913CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002914 if (!D)
2915 return CXCursor_UnexposedDecl;
2916
2917 switch (D->getKind()) {
2918 case Decl::Enum: return CXCursor_EnumDecl;
2919 case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
2920 case Decl::Field: return CXCursor_FieldDecl;
2921 case Decl::Function:
2922 return CXCursor_FunctionDecl;
2923 case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
2924 case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002925 case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
Douglas Gregor375bb142011-12-27 22:43:10 +00002926
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002927 case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002928 case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
2929 case Decl::ObjCMethod:
2930 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
2931 ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
2932 case Decl::CXXMethod: return CXCursor_CXXMethod;
2933 case Decl::CXXConstructor: return CXCursor_Constructor;
2934 case Decl::CXXDestructor: return CXCursor_Destructor;
2935 case Decl::CXXConversion: return CXCursor_ConversionFunction;
2936 case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
Argyrios Kyrtzidisc15707d2012-01-24 21:39:26 +00002937 case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002938 case Decl::ParmVar: return CXCursor_ParmDecl;
2939 case Decl::Typedef: return CXCursor_TypedefDecl;
Richard Smith162e1c12011-04-15 14:24:37 +00002940 case Decl::TypeAlias: return CXCursor_TypeAliasDecl;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002941 case Decl::Var: return CXCursor_VarDecl;
2942 case Decl::Namespace: return CXCursor_Namespace;
2943 case Decl::NamespaceAlias: return CXCursor_NamespaceAlias;
2944 case Decl::TemplateTypeParm: return CXCursor_TemplateTypeParameter;
2945 case Decl::NonTypeTemplateParm:return CXCursor_NonTypeTemplateParameter;
2946 case Decl::TemplateTemplateParm:return CXCursor_TemplateTemplateParameter;
2947 case Decl::FunctionTemplate: return CXCursor_FunctionTemplate;
2948 case Decl::ClassTemplate: return CXCursor_ClassTemplate;
Argyrios Kyrtzidis2dfdb942011-09-30 17:58:23 +00002949 case Decl::AccessSpec: return CXCursor_CXXAccessSpecifier;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002950 case Decl::ClassTemplatePartialSpecialization:
2951 return CXCursor_ClassTemplatePartialSpecialization;
2952 case Decl::UsingDirective: return CXCursor_UsingDirective;
Douglas Gregor8e5900c2012-04-30 23:41:16 +00002953 case Decl::TranslationUnit: return CXCursor_TranslationUnit;
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002954
2955 case Decl::Using:
2956 case Decl::UnresolvedUsingValue:
2957 case Decl::UnresolvedUsingTypename:
2958 return CXCursor_UsingDeclaration;
2959
Douglas Gregor352697a2011-06-03 23:08:58 +00002960 case Decl::ObjCPropertyImpl:
2961 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
2962 case ObjCPropertyImplDecl::Dynamic:
2963 return CXCursor_ObjCDynamicDecl;
2964
2965 case ObjCPropertyImplDecl::Synthesize:
2966 return CXCursor_ObjCSynthesizeDecl;
2967 }
Argyrios Kyrtzidis6a010122012-10-05 00:22:24 +00002968
2969 case Decl::Import:
2970 return CXCursor_ModuleImportDecl;
Douglas Gregor352697a2011-06-03 23:08:58 +00002971
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002972 default:
Dmitri Gribenko06d8c602013-01-11 20:32:41 +00002973 if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002974 switch (TD->getTagKind()) {
Joao Matos6666ed42012-08-31 18:45:21 +00002975 case TTK_Interface: // fall through
Douglas Gregore8d7beb2010-09-03 23:30:36 +00002976 case TTK_Struct: return CXCursor_StructDecl;
2977 case TTK_Class: return CXCursor_ClassDecl;
2978 case TTK_Union: return CXCursor_UnionDecl;
2979 case TTK_Enum: return CXCursor_EnumDecl;
2980 }
2981 }
2982 }
2983
2984 return CXCursor_UnexposedDecl;
2985}
2986
Douglas Gregor590c7d52010-07-08 20:55:51 +00002987static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Douglas Gregor3644d972012-10-09 16:01:50 +00002988 bool IncludeUndefined,
Douglas Gregor590c7d52010-07-08 20:55:51 +00002989 bool TargetTypeIsPointer = false) {
John McCall0a2c5e22010-08-25 06:19:51 +00002990 typedef CodeCompletionResult Result;
Douglas Gregor590c7d52010-07-08 20:55:51 +00002991
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00002992 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00002993
Douglas Gregor0c8296d2009-11-07 00:00:49 +00002994 for (Preprocessor::macro_iterator M = PP.macro_begin(),
2995 MEnd = PP.macro_end();
Douglas Gregor590c7d52010-07-08 20:55:51 +00002996 M != MEnd; ++M) {
Douglas Gregor3644d972012-10-09 16:01:50 +00002997 if (IncludeUndefined || M->first->hasMacroDefinition())
2998 Results.AddResult(Result(M->first,
Douglas Gregor1827e102010-08-16 16:18:59 +00002999 getMacroUsagePriority(M->first->getName(),
David Blaikie4e4d0842012-03-11 07:00:24 +00003000 PP.getLangOpts(),
Douglas Gregor1827e102010-08-16 16:18:59 +00003001 TargetTypeIsPointer)));
Douglas Gregor590c7d52010-07-08 20:55:51 +00003002 }
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00003003
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00003004 Results.ExitScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00003005
Douglas Gregor3f7c7f42009-10-30 16:50:04 +00003006}
3007
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003008static void AddPrettyFunctionResults(const LangOptions &LangOpts,
3009 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003010 typedef CodeCompletionResult Result;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003011
3012 Results.EnterNewScope();
Douglas Gregorc7b7b7a2010-10-18 21:05:04 +00003013
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003014 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3015 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith80ad52f2013-01-02 11:42:31 +00003016 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003017 Results.AddResult(Result("__func__", CCP_Constant));
3018 Results.ExitScope();
3019}
3020
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003021static void HandleCodeCompleteResults(Sema *S,
3022 CodeCompleteConsumer *CodeCompleter,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003023 CodeCompletionContext Context,
John McCall0a2c5e22010-08-25 06:19:51 +00003024 CodeCompletionResult *Results,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003025 unsigned NumResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00003026 if (CodeCompleter)
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003027 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor86d9a522009-09-21 16:56:56 +00003028}
3029
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003030static enum CodeCompletionContext::Kind mapCodeCompletionContext(Sema &S,
3031 Sema::ParserCompletionContext PCC) {
3032 switch (PCC) {
John McCallf312b1e2010-08-26 23:41:50 +00003033 case Sema::PCC_Namespace:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003034 return CodeCompletionContext::CCC_TopLevel;
3035
John McCallf312b1e2010-08-26 23:41:50 +00003036 case Sema::PCC_Class:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003037 return CodeCompletionContext::CCC_ClassStructUnion;
3038
John McCallf312b1e2010-08-26 23:41:50 +00003039 case Sema::PCC_ObjCInterface:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003040 return CodeCompletionContext::CCC_ObjCInterface;
3041
John McCallf312b1e2010-08-26 23:41:50 +00003042 case Sema::PCC_ObjCImplementation:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003043 return CodeCompletionContext::CCC_ObjCImplementation;
3044
John McCallf312b1e2010-08-26 23:41:50 +00003045 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003046 return CodeCompletionContext::CCC_ObjCIvarList;
3047
John McCallf312b1e2010-08-26 23:41:50 +00003048 case Sema::PCC_Template:
3049 case Sema::PCC_MemberTemplate:
Douglas Gregor52779fb2010-09-23 23:01:17 +00003050 if (S.CurContext->isFileContext())
3051 return CodeCompletionContext::CCC_TopLevel;
David Blaikie7530c032012-01-17 06:56:22 +00003052 if (S.CurContext->isRecord())
Douglas Gregor52779fb2010-09-23 23:01:17 +00003053 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie7530c032012-01-17 06:56:22 +00003054 return CodeCompletionContext::CCC_Other;
Douglas Gregor52779fb2010-09-23 23:01:17 +00003055
John McCallf312b1e2010-08-26 23:41:50 +00003056 case Sema::PCC_RecoveryInFunction:
Douglas Gregor52779fb2010-09-23 23:01:17 +00003057 return CodeCompletionContext::CCC_Recovery;
Douglas Gregora5450a02010-10-18 22:01:46 +00003058
John McCallf312b1e2010-08-26 23:41:50 +00003059 case Sema::PCC_ForInit:
David Blaikie4e4d0842012-03-11 07:00:24 +00003060 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
3061 S.getLangOpts().ObjC1)
Douglas Gregora5450a02010-10-18 22:01:46 +00003062 return CodeCompletionContext::CCC_ParenthesizedExpression;
3063 else
3064 return CodeCompletionContext::CCC_Expression;
3065
3066 case Sema::PCC_Expression:
John McCallf312b1e2010-08-26 23:41:50 +00003067 case Sema::PCC_Condition:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003068 return CodeCompletionContext::CCC_Expression;
3069
John McCallf312b1e2010-08-26 23:41:50 +00003070 case Sema::PCC_Statement:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003071 return CodeCompletionContext::CCC_Statement;
Douglas Gregor72db1082010-08-24 01:11:00 +00003072
John McCallf312b1e2010-08-26 23:41:50 +00003073 case Sema::PCC_Type:
Douglas Gregor72db1082010-08-24 01:11:00 +00003074 return CodeCompletionContext::CCC_Type;
Douglas Gregor02688102010-09-14 23:59:36 +00003075
3076 case Sema::PCC_ParenthesizedExpression:
3077 return CodeCompletionContext::CCC_ParenthesizedExpression;
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003078
3079 case Sema::PCC_LocalDeclarationSpecifiers:
3080 return CodeCompletionContext::CCC_Type;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003081 }
David Blaikie7530c032012-01-17 06:56:22 +00003082
3083 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003084}
3085
Douglas Gregorf6961522010-08-27 21:18:54 +00003086/// \brief If we're in a C++ virtual member function, add completion results
3087/// that invoke the functions we override, since it's common to invoke the
3088/// overridden function as well as adding new functionality.
3089///
3090/// \param S The semantic analysis object for which we are generating results.
3091///
3092/// \param InContext This context in which the nested-name-specifier preceding
3093/// the code-completion point
3094static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3095 ResultBuilder &Results) {
3096 // Look through blocks.
3097 DeclContext *CurContext = S.CurContext;
3098 while (isa<BlockDecl>(CurContext))
3099 CurContext = CurContext->getParent();
3100
3101
3102 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3103 if (!Method || !Method->isVirtual())
3104 return;
3105
3106 // We need to have names for all of the parameters, if we're going to
3107 // generate a forwarding call.
3108 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3109 PEnd = Method->param_end();
3110 P != PEnd;
3111 ++P) {
3112 if (!(*P)->getDeclName())
3113 return;
3114 }
3115
Douglas Gregor8987b232011-09-27 23:30:47 +00003116 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Douglas Gregorf6961522010-08-27 21:18:54 +00003117 for (CXXMethodDecl::method_iterator M = Method->begin_overridden_methods(),
3118 MEnd = Method->end_overridden_methods();
3119 M != MEnd; ++M) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003120 CodeCompletionBuilder Builder(Results.getAllocator(),
3121 Results.getCodeCompletionTUInfo());
Dmitri Gribenko68a932d2013-02-14 13:53:30 +00003122 const CXXMethodDecl *Overridden = *M;
Douglas Gregorf6961522010-08-27 21:18:54 +00003123 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3124 continue;
3125
3126 // If we need a nested-name-specifier, add one now.
3127 if (!InContext) {
3128 NestedNameSpecifier *NNS
3129 = getRequiredQualification(S.Context, CurContext,
3130 Overridden->getDeclContext());
3131 if (NNS) {
3132 std::string Str;
3133 llvm::raw_string_ostream OS(Str);
Douglas Gregor8987b232011-09-27 23:30:47 +00003134 NNS->print(OS, Policy);
Douglas Gregordae68752011-02-01 22:57:45 +00003135 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003136 }
3137 } else if (!InContext->Equals(Overridden->getDeclContext()))
3138 continue;
3139
Douglas Gregordae68752011-02-01 22:57:45 +00003140 Builder.AddTypedTextChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003141 Overridden->getNameAsString()));
3142 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf6961522010-08-27 21:18:54 +00003143 bool FirstParam = true;
3144 for (CXXMethodDecl::param_iterator P = Method->param_begin(),
3145 PEnd = Method->param_end();
3146 P != PEnd; ++P) {
3147 if (FirstParam)
3148 FirstParam = false;
3149 else
Douglas Gregor218937c2011-02-01 19:23:04 +00003150 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorf6961522010-08-27 21:18:54 +00003151
Douglas Gregordae68752011-02-01 22:57:45 +00003152 Builder.AddPlaceholderChunk(Results.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00003153 (*P)->getIdentifier()->getName()));
Douglas Gregorf6961522010-08-27 21:18:54 +00003154 }
Douglas Gregor218937c2011-02-01 19:23:04 +00003155 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3156 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregorf6961522010-08-27 21:18:54 +00003157 CCP_SuperCompletion,
Douglas Gregorba103062012-03-27 23:34:16 +00003158 CXCursor_CXXMethod,
3159 CXAvailability_Available,
3160 Overridden));
Douglas Gregorf6961522010-08-27 21:18:54 +00003161 Results.Ignore(Overridden);
3162 }
3163}
3164
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003165void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
3166 ModuleIdPath Path) {
3167 typedef CodeCompletionResult Result;
3168 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003169 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003170 CodeCompletionContext::CCC_Other);
3171 Results.EnterNewScope();
3172
3173 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003174 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003175 typedef CodeCompletionResult Result;
3176 if (Path.empty()) {
3177 // Enumerate all top-level modules.
Dmitri Gribenkocfa88f82013-01-12 19:30:44 +00003178 SmallVector<Module *, 8> Modules;
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003179 PP.getHeaderSearchInfo().collectAllModules(Modules);
3180 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3181 Builder.AddTypedTextChunk(
3182 Builder.getAllocator().CopyString(Modules[I]->Name));
3183 Results.AddResult(Result(Builder.TakeString(),
3184 CCP_Declaration,
Argyrios Kyrtzidisfe038a32013-05-29 18:50:15 +00003185 CXCursor_ModuleImportDecl,
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003186 Modules[I]->isAvailable()
3187 ? CXAvailability_Available
3188 : CXAvailability_NotAvailable));
3189 }
Daniel Jasper056ec122013-08-05 20:26:17 +00003190 } else if (getLangOpts().Modules) {
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003191 // Load the named module.
3192 Module *Mod = PP.getModuleLoader().loadModule(ImportLoc, Path,
3193 Module::AllVisible,
3194 /*IsInclusionDirective=*/false);
3195 // Enumerate submodules.
3196 if (Mod) {
3197 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
3198 SubEnd = Mod->submodule_end();
3199 Sub != SubEnd; ++Sub) {
3200
3201 Builder.AddTypedTextChunk(
3202 Builder.getAllocator().CopyString((*Sub)->Name));
3203 Results.AddResult(Result(Builder.TakeString(),
3204 CCP_Declaration,
Argyrios Kyrtzidisfe038a32013-05-29 18:50:15 +00003205 CXCursor_ModuleImportDecl,
Douglas Gregorc5b2e582012-01-29 18:15:03 +00003206 (*Sub)->isAvailable()
3207 ? CXAvailability_Available
3208 : CXAvailability_NotAvailable));
3209 }
3210 }
3211 }
3212 Results.ExitScope();
3213 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3214 Results.data(),Results.size());
3215}
3216
Douglas Gregor01dfea02010-01-10 23:08:15 +00003217void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003218 ParserCompletionContext CompletionContext) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003219 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003220 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003221 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorf6961522010-08-27 21:18:54 +00003222 Results.EnterNewScope();
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003223
Douglas Gregor01dfea02010-01-10 23:08:15 +00003224 // Determine how to filter results, e.g., so that the names of
3225 // values (functions, enumerators, function templates, etc.) are
3226 // only allowed where we can have an expression.
3227 switch (CompletionContext) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003228 case PCC_Namespace:
3229 case PCC_Class:
3230 case PCC_ObjCInterface:
3231 case PCC_ObjCImplementation:
3232 case PCC_ObjCInstanceVariableList:
3233 case PCC_Template:
3234 case PCC_MemberTemplate:
Douglas Gregor72db1082010-08-24 01:11:00 +00003235 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003236 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor01dfea02010-01-10 23:08:15 +00003237 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3238 break;
3239
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003240 case PCC_Statement:
Douglas Gregor02688102010-09-14 23:59:36 +00003241 case PCC_ParenthesizedExpression:
Douglas Gregoreb0d0142010-08-24 23:58:17 +00003242 case PCC_Expression:
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003243 case PCC_ForInit:
3244 case PCC_Condition:
David Blaikie4e4d0842012-03-11 07:00:24 +00003245 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor4710e5b2010-05-28 00:49:12 +00003246 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3247 else
3248 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorf6961522010-08-27 21:18:54 +00003249
David Blaikie4e4d0842012-03-11 07:00:24 +00003250 if (getLangOpts().CPlusPlus)
Douglas Gregorf6961522010-08-27 21:18:54 +00003251 MaybeAddOverrideCalls(*this, /*InContext=*/0, Results);
Douglas Gregor01dfea02010-01-10 23:08:15 +00003252 break;
Douglas Gregordc845342010-05-25 05:58:43 +00003253
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003254 case PCC_RecoveryInFunction:
Douglas Gregordc845342010-05-25 05:58:43 +00003255 // Unfiltered
3256 break;
Douglas Gregor01dfea02010-01-10 23:08:15 +00003257 }
3258
Douglas Gregor3cdee122010-08-26 16:36:48 +00003259 // If we are in a C++ non-static member function, check the qualifiers on
3260 // the member function to filter/prioritize the results list.
3261 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext))
3262 if (CurMethod->isInstance())
3263 Results.setObjectTypeQualifiers(
3264 Qualifiers::fromCVRMask(CurMethod->getTypeQualifiers()));
3265
Douglas Gregor1ca6ae82010-01-14 01:09:38 +00003266 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003267 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3268 CodeCompleter->includeGlobals());
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003269
Douglas Gregorbca403c2010-01-13 23:51:12 +00003270 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor2a7925c2009-12-07 09:54:55 +00003271 Results.ExitScope();
3272
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003273 switch (CompletionContext) {
Douglas Gregor02688102010-09-14 23:59:36 +00003274 case PCC_ParenthesizedExpression:
Douglas Gregor72db1082010-08-24 01:11:00 +00003275 case PCC_Expression:
3276 case PCC_Statement:
3277 case PCC_RecoveryInFunction:
3278 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00003279 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregor72db1082010-08-24 01:11:00 +00003280 break;
3281
3282 case PCC_Namespace:
3283 case PCC_Class:
3284 case PCC_ObjCInterface:
3285 case PCC_ObjCImplementation:
3286 case PCC_ObjCInstanceVariableList:
3287 case PCC_Template:
3288 case PCC_MemberTemplate:
3289 case PCC_ForInit:
3290 case PCC_Condition:
3291 case PCC_Type:
Douglas Gregor68e3c2e2011-02-15 20:33:25 +00003292 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor72db1082010-08-24 01:11:00 +00003293 break;
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003294 }
3295
Douglas Gregor0c8296d2009-11-07 00:00:49 +00003296 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003297 AddMacroResults(PP, Results, false);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003298
Douglas Gregorcee9ff12010-09-20 22:39:41 +00003299 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003300 Results.data(),Results.size());
Douglas Gregor791215b2009-09-21 20:51:25 +00003301}
3302
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003303static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
3304 ParsedType Receiver,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00003305 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00003306 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003307 bool IsSuper,
3308 ResultBuilder &Results);
3309
3310void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3311 bool AllowNonIdentifiers,
3312 bool AllowNestedNameSpecifiers) {
John McCall0a2c5e22010-08-25 06:19:51 +00003313 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00003314 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003315 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00003316 AllowNestedNameSpecifiers
3317 ? CodeCompletionContext::CCC_PotentiallyQualifiedName
3318 : CodeCompletionContext::CCC_Name);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003319 Results.EnterNewScope();
3320
3321 // Type qualifiers can come after names.
3322 Results.AddResult(Result("const"));
3323 Results.AddResult(Result("volatile"));
David Blaikie4e4d0842012-03-11 07:00:24 +00003324 if (getLangOpts().C99)
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003325 Results.AddResult(Result("restrict"));
3326
David Blaikie4e4d0842012-03-11 07:00:24 +00003327 if (getLangOpts().CPlusPlus) {
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003328 if (AllowNonIdentifiers) {
3329 Results.AddResult(Result("operator"));
3330 }
3331
3332 // Add nested-name-specifiers.
3333 if (AllowNestedNameSpecifiers) {
3334 Results.allowNestedNameSpecifiers();
Douglas Gregor52779fb2010-09-23 23:01:17 +00003335 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003336 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3337 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
3338 CodeCompleter->includeGlobals());
Douglas Gregor52779fb2010-09-23 23:01:17 +00003339 Results.setFilter(0);
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003340 }
3341 }
3342 Results.ExitScope();
3343
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003344 // If we're in a context where we might have an expression (rather than a
3345 // declaration), and what we've seen so far is an Objective-C type that could
3346 // be a receiver of a class message, this may be a class message send with
3347 // the initial opening bracket '[' missing. Add appropriate completions.
3348 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithec642442013-04-12 22:46:28 +00003349 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003350 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003351 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3352 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Richard Smithec642442013-04-12 22:46:28 +00003353 !DS.isTypeAltiVecVector() &&
3354 S &&
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003355 (S->getFlags() & Scope::DeclScope) != 0 &&
3356 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
3357 Scope::FunctionPrototypeScope |
3358 Scope::AtCatchScope)) == 0) {
3359 ParsedType T = DS.getRepAsType();
3360 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko050315b2013-06-16 03:47:57 +00003361 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00003362 }
3363
Douglas Gregor4497dd42010-08-24 04:59:56 +00003364 // Note that we intentionally suppress macro results here, since we do not
3365 // encourage using macros to produce the names of entities.
3366
Douglas Gregor52779fb2010-09-23 23:01:17 +00003367 HandleCodeCompleteResults(this, CodeCompleter,
3368 Results.getCompletionContext(),
Douglas Gregor2ccccb32010-08-23 18:23:48 +00003369 Results.data(), Results.size());
3370}
3371
Douglas Gregorfb629412010-08-23 21:17:50 +00003372struct Sema::CodeCompleteExpressionData {
3373 CodeCompleteExpressionData(QualType PreferredType = QualType())
3374 : PreferredType(PreferredType), IntegralConstantExpression(false),
3375 ObjCCollection(false) { }
3376
3377 QualType PreferredType;
3378 bool IntegralConstantExpression;
3379 bool ObjCCollection;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003380 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregorfb629412010-08-23 21:17:50 +00003381};
3382
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003383/// \brief Perform code-completion in an expression context when we know what
3384/// type we're looking for.
Douglas Gregorfb629412010-08-23 21:17:50 +00003385void Sema::CodeCompleteExpression(Scope *S,
3386 const CodeCompleteExpressionData &Data) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003387 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003388 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003389 CodeCompletionContext::CCC_Expression);
Douglas Gregorfb629412010-08-23 21:17:50 +00003390 if (Data.ObjCCollection)
3391 Results.setFilter(&ResultBuilder::IsObjCCollection);
3392 else if (Data.IntegralConstantExpression)
Douglas Gregorf9578432010-07-28 21:50:18 +00003393 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikie4e4d0842012-03-11 07:00:24 +00003394 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003395 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3396 else
3397 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregorfb629412010-08-23 21:17:50 +00003398
3399 if (!Data.PreferredType.isNull())
3400 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
3401
3402 // Ignore any declarations that we were told that we don't care about.
3403 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3404 Results.Ignore(Data.IgnoreDecls[I]);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003405
3406 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003407 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
3408 CodeCompleter->includeGlobals());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003409
3410 Results.EnterNewScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003411 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003412 Results.ExitScope();
3413
Douglas Gregor590c7d52010-07-08 20:55:51 +00003414 bool PreferredTypeIsPointer = false;
Douglas Gregorfb629412010-08-23 21:17:50 +00003415 if (!Data.PreferredType.isNull())
3416 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType()
3417 || Data.PreferredType->isMemberPointerType()
3418 || Data.PreferredType->isBlockPointerType();
Douglas Gregor590c7d52010-07-08 20:55:51 +00003419
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003420 if (S->getFnParent() &&
3421 !Data.ObjCCollection &&
3422 !Data.IntegralConstantExpression)
David Blaikie4e4d0842012-03-11 07:00:24 +00003423 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregoraa5f77b2010-08-23 21:54:33 +00003424
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003425 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00003426 AddMacroResults(PP, Results, false, PreferredTypeIsPointer);
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003427 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregorfb629412010-08-23 21:17:50 +00003428 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3429 Data.PreferredType),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003430 Results.data(),Results.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003431}
3432
Douglas Gregorac5fd842010-09-18 01:28:11 +00003433void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3434 if (E.isInvalid())
3435 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
David Blaikie4e4d0842012-03-11 07:00:24 +00003436 else if (getLangOpts().ObjC1)
Dmitri Gribenko050315b2013-06-16 03:47:57 +00003437 CodeCompleteObjCInstanceMessage(S, E.take(), None, false);
Douglas Gregor78edf512010-09-15 16:23:04 +00003438}
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003439
Douglas Gregor73449212010-12-09 23:01:55 +00003440/// \brief The set of properties that have already been added, referenced by
3441/// property name.
3442typedef llvm::SmallPtrSet<IdentifierInfo*, 16> AddedPropertiesSet;
3443
Douglas Gregorb92a4082012-06-12 13:44:08 +00003444/// \brief Retrieve the container definition, if any?
3445static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3446 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3447 if (Interface->hasDefinition())
3448 return Interface->getDefinition();
3449
3450 return Interface;
3451 }
3452
3453 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3454 if (Protocol->hasDefinition())
3455 return Protocol->getDefinition();
3456
3457 return Protocol;
3458 }
3459 return Container;
3460}
3461
3462static void AddObjCProperties(ObjCContainerDecl *Container,
Douglas Gregor322328b2009-11-18 22:32:06 +00003463 bool AllowCategories,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003464 bool AllowNullaryMethods,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003465 DeclContext *CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003466 AddedPropertiesSet &AddedProperties,
Douglas Gregor95ac6552009-11-18 01:29:26 +00003467 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00003468 typedef CodeCompletionResult Result;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003469
Douglas Gregorb92a4082012-06-12 13:44:08 +00003470 // Retrieve the definition.
3471 Container = getContainerDef(Container);
3472
Douglas Gregor95ac6552009-11-18 01:29:26 +00003473 // Add properties in this container.
3474 for (ObjCContainerDecl::prop_iterator P = Container->prop_begin(),
3475 PEnd = Container->prop_end();
3476 P != PEnd;
Douglas Gregor73449212010-12-09 23:01:55 +00003477 ++P) {
3478 if (AddedProperties.insert(P->getIdentifier()))
Douglas Gregord1f09b42013-01-31 04:52:16 +00003479 Results.MaybeAddResult(Result(*P, Results.getBasePriority(*P), 0),
3480 CurContext);
Douglas Gregor73449212010-12-09 23:01:55 +00003481 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003482
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003483 // Add nullary methods
3484 if (AllowNullaryMethods) {
3485 ASTContext &Context = Container->getASTContext();
Douglas Gregor8987b232011-09-27 23:30:47 +00003486 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003487 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
3488 MEnd = Container->meth_end();
3489 M != MEnd; ++M) {
3490 if (M->getSelector().isUnarySelector())
3491 if (IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0))
3492 if (AddedProperties.insert(Name)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003493 CodeCompletionBuilder Builder(Results.getAllocator(),
3494 Results.getCodeCompletionTUInfo());
David Blaikie581deb32012-06-06 20:45:41 +00003495 AddResultTypeChunk(Context, Policy, *M, Builder);
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003496 Builder.AddTypedTextChunk(
3497 Results.getAllocator().CopyString(Name->getName()));
3498
David Blaikie581deb32012-06-06 20:45:41 +00003499 Results.MaybeAddResult(Result(Builder.TakeString(), *M,
Douglas Gregorba103062012-03-27 23:34:16 +00003500 CCP_MemberDeclaration + CCD_MethodAsProperty),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003501 CurContext);
3502 }
3503 }
3504 }
3505
3506
Douglas Gregor95ac6552009-11-18 01:29:26 +00003507 // Add properties in referenced protocols.
3508 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3509 for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(),
3510 PEnd = Protocol->protocol_end();
3511 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003512 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3513 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003514 } else if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)){
Douglas Gregor322328b2009-11-18 22:32:06 +00003515 if (AllowCategories) {
3516 // Look through categories.
Douglas Gregord3297242013-01-16 23:00:23 +00003517 for (ObjCInterfaceDecl::known_categories_iterator
3518 Cat = IFace->known_categories_begin(),
3519 CatEnd = IFace->known_categories_end();
3520 Cat != CatEnd; ++Cat)
3521 AddObjCProperties(*Cat, AllowCategories, AllowNullaryMethods,
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003522 CurContext, AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00003523 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003524
3525 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003526 for (ObjCInterfaceDecl::all_protocol_iterator
3527 I = IFace->all_referenced_protocol_begin(),
3528 E = IFace->all_referenced_protocol_end(); I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003529 AddObjCProperties(*I, AllowCategories, AllowNullaryMethods, CurContext,
3530 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003531
3532 // Look in the superclass.
3533 if (IFace->getSuperClass())
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003534 AddObjCProperties(IFace->getSuperClass(), AllowCategories,
3535 AllowNullaryMethods, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003536 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003537 } else if (const ObjCCategoryDecl *Category
3538 = dyn_cast<ObjCCategoryDecl>(Container)) {
3539 // Look through protocols.
Ted Kremenek53b94412010-09-01 01:21:15 +00003540 for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(),
3541 PEnd = Category->protocol_end();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003542 P != PEnd; ++P)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003543 AddObjCProperties(*P, AllowCategories, AllowNullaryMethods, CurContext,
3544 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003545 }
3546}
3547
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003548void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Douglas Gregor81b747b2009-09-17 21:32:03 +00003549 SourceLocation OpLoc,
3550 bool IsArrow) {
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003551 if (!Base || !CodeCompleter)
Douglas Gregor81b747b2009-09-17 21:32:03 +00003552 return;
3553
Douglas Gregorf5cd27d2012-01-23 15:59:30 +00003554 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
3555 if (ConvertedBase.isInvalid())
3556 return;
3557 Base = ConvertedBase.get();
3558
John McCall0a2c5e22010-08-25 06:19:51 +00003559 typedef CodeCompletionResult Result;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003560
Douglas Gregor81b747b2009-09-17 21:32:03 +00003561 QualType BaseType = Base->getType();
Douglas Gregor86d9a522009-09-21 16:56:56 +00003562
3563 if (IsArrow) {
3564 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
3565 BaseType = Ptr->getPointeeType();
3566 else if (BaseType->isObjCObjectPointerType())
Douglas Gregor3cdee122010-08-26 16:36:48 +00003567 /*Do nothing*/ ;
Douglas Gregor86d9a522009-09-21 16:56:56 +00003568 else
3569 return;
3570 }
3571
Douglas Gregor3da626b2011-07-07 16:03:39 +00003572 enum CodeCompletionContext::Kind contextKind;
3573
3574 if (IsArrow) {
3575 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
3576 }
3577 else {
3578 if (BaseType->isObjCObjectPointerType() ||
3579 BaseType->isObjCObjectOrInterfaceType()) {
3580 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
3581 }
3582 else {
3583 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
3584 }
3585 }
3586
Douglas Gregor218937c2011-02-01 19:23:04 +00003587 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003588 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00003589 CodeCompletionContext(contextKind,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003590 BaseType),
3591 &ResultBuilder::IsMember);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003592 Results.EnterNewScope();
3593 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
Douglas Gregor3cdee122010-08-26 16:36:48 +00003594 // Indicate that we are performing a member access, and the cv-qualifiers
3595 // for the base object type.
3596 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
3597
Douglas Gregor95ac6552009-11-18 01:29:26 +00003598 // Access to a C/C++ class, struct, or union.
Douglas Gregor45bcd432010-01-14 03:21:49 +00003599 Results.allowNestedNameSpecifiers();
Douglas Gregor0cc84042010-01-14 15:47:35 +00003600 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00003601 LookupVisibleDecls(Record->getDecl(), LookupMemberName, Consumer,
3602 CodeCompleter->includeGlobals());
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003603
David Blaikie4e4d0842012-03-11 07:00:24 +00003604 if (getLangOpts().CPlusPlus) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003605 if (!Results.empty()) {
3606 // The "template" keyword can follow "->" or "." in the grammar.
3607 // However, we only want to suggest the template keyword if something
3608 // is dependent.
3609 bool IsDependent = BaseType->isDependentType();
3610 if (!IsDependent) {
3611 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
3612 if (DeclContext *Ctx = (DeclContext *)DepScope->getEntity()) {
3613 IsDependent = Ctx->isDependentContext();
3614 break;
3615 }
3616 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003617
Douglas Gregor95ac6552009-11-18 01:29:26 +00003618 if (IsDependent)
Douglas Gregora4477812010-01-14 16:01:26 +00003619 Results.AddResult(Result("template"));
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003620 }
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003621 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003622 } else if (!IsArrow && BaseType->getAsObjCInterfacePointerType()) {
3623 // Objective-C property reference.
Douglas Gregor73449212010-12-09 23:01:55 +00003624 AddedPropertiesSet AddedProperties;
Douglas Gregor95ac6552009-11-18 01:29:26 +00003625
3626 // Add property results based on our interface.
3627 const ObjCObjectPointerType *ObjCPtr
3628 = BaseType->getAsObjCInterfacePointerType();
3629 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003630 AddObjCProperties(ObjCPtr->getInterfaceDecl(), true,
3631 /*AllowNullaryMethods=*/true, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00003632 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003633
3634 // Add properties from the protocols in a qualified interface.
3635 for (ObjCObjectPointerType::qual_iterator I = ObjCPtr->qual_begin(),
3636 E = ObjCPtr->qual_end();
3637 I != E; ++I)
Douglas Gregor4b81cde2011-05-05 15:50:42 +00003638 AddObjCProperties(*I, true, /*AllowNullaryMethods=*/true, CurContext,
3639 AddedProperties, Results);
Douglas Gregor95ac6552009-11-18 01:29:26 +00003640 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
John McCallc12c5bb2010-05-15 11:32:37 +00003641 (!IsArrow && BaseType->isObjCObjectType())) {
Douglas Gregor95ac6552009-11-18 01:29:26 +00003642 // Objective-C instance variable access.
3643 ObjCInterfaceDecl *Class = 0;
3644 if (const ObjCObjectPointerType *ObjCPtr
3645 = BaseType->getAs<ObjCObjectPointerType>())
3646 Class = ObjCPtr->getInterfaceDecl();
3647 else
John McCallc12c5bb2010-05-15 11:32:37 +00003648 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
Douglas Gregor95ac6552009-11-18 01:29:26 +00003649
3650 // Add all ivars from this class and its superclasses.
Douglas Gregor80f4f4c2010-01-14 16:08:12 +00003651 if (Class) {
3652 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3653 Results.setFilter(&ResultBuilder::IsObjCIvar);
Douglas Gregor8071e422010-08-15 06:18:01 +00003654 LookupVisibleDecls(Class, LookupMemberName, Consumer,
3655 CodeCompleter->includeGlobals());
Douglas Gregor95ac6552009-11-18 01:29:26 +00003656 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003657 }
Douglas Gregor95ac6552009-11-18 01:29:26 +00003658
3659 // FIXME: How do we cope with isa?
3660
3661 Results.ExitScope();
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003662
Daniel Dunbar3a2838d2009-11-13 08:58:20 +00003663 // Hand off the results found for code completion.
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003664 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003665 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003666 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00003667}
3668
Douglas Gregor374929f2009-09-18 15:37:17 +00003669void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
3670 if (!CodeCompleter)
3671 return;
3672
Douglas Gregor86d9a522009-09-21 16:56:56 +00003673 ResultBuilder::LookupFilter Filter = 0;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003674 enum CodeCompletionContext::Kind ContextKind
3675 = CodeCompletionContext::CCC_Other;
Douglas Gregor374929f2009-09-18 15:37:17 +00003676 switch ((DeclSpec::TST)TagSpec) {
3677 case DeclSpec::TST_enum:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003678 Filter = &ResultBuilder::IsEnum;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003679 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003680 break;
3681
3682 case DeclSpec::TST_union:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003683 Filter = &ResultBuilder::IsUnion;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003684 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003685 break;
3686
3687 case DeclSpec::TST_struct:
Douglas Gregor374929f2009-09-18 15:37:17 +00003688 case DeclSpec::TST_class:
Joao Matos6666ed42012-08-31 18:45:21 +00003689 case DeclSpec::TST_interface:
Douglas Gregor86d9a522009-09-21 16:56:56 +00003690 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003691 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregor374929f2009-09-18 15:37:17 +00003692 break;
3693
3694 default:
David Blaikieb219cfc2011-09-23 05:06:16 +00003695 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregor374929f2009-09-18 15:37:17 +00003696 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003697
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003698 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
3699 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00003700 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCall0d6b1642010-04-23 18:46:30 +00003701
3702 // First pass: look for tags.
3703 Results.setFilter(Filter);
Douglas Gregor8071e422010-08-15 06:18:01 +00003704 LookupVisibleDecls(S, LookupTagName, Consumer,
3705 CodeCompleter->includeGlobals());
John McCall0d6b1642010-04-23 18:46:30 +00003706
Douglas Gregor8071e422010-08-15 06:18:01 +00003707 if (CodeCompleter->includeGlobals()) {
3708 // Second pass: look for nested name specifiers.
3709 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
3710 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer);
3711 }
Douglas Gregor86d9a522009-09-21 16:56:56 +00003712
Douglas Gregor52779fb2010-09-23 23:01:17 +00003713 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003714 Results.data(),Results.size());
Douglas Gregor374929f2009-09-18 15:37:17 +00003715}
3716
Douglas Gregor1a480c42010-08-27 17:35:51 +00003717void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregor218937c2011-02-01 19:23:04 +00003718 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003719 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003720 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor1a480c42010-08-27 17:35:51 +00003721 Results.EnterNewScope();
3722 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
3723 Results.AddResult("const");
3724 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
3725 Results.AddResult("volatile");
David Blaikie4e4d0842012-03-11 07:00:24 +00003726 if (getLangOpts().C99 &&
Douglas Gregor1a480c42010-08-27 17:35:51 +00003727 !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
3728 Results.AddResult("restrict");
Richard Smith4cf4a5e2013-03-28 01:55:44 +00003729 if (getLangOpts().C11 &&
3730 !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
3731 Results.AddResult("_Atomic");
Douglas Gregor1a480c42010-08-27 17:35:51 +00003732 Results.ExitScope();
3733 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00003734 Results.getCompletionContext(),
Douglas Gregor1a480c42010-08-27 17:35:51 +00003735 Results.data(), Results.size());
3736}
3737
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003738void Sema::CodeCompleteCase(Scope *S) {
John McCall781472f2010-08-25 08:40:02 +00003739 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003740 return;
John McCalla8e0cd82011-08-06 07:30:58 +00003741
John McCall781472f2010-08-25 08:40:02 +00003742 SwitchStmt *Switch = getCurFunction()->SwitchStack.back();
John McCalla8e0cd82011-08-06 07:30:58 +00003743 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
3744 if (!type->isEnumeralType()) {
3745 CodeCompleteExpressionData Data(type);
Douglas Gregorfb629412010-08-23 21:17:50 +00003746 Data.IntegralConstantExpression = true;
3747 CodeCompleteExpression(S, Data);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003748 return;
Douglas Gregorf9578432010-07-28 21:50:18 +00003749 }
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003750
3751 // Code-complete the cases of a switch statement over an enumeration type
3752 // by providing the list of
John McCalla8e0cd82011-08-06 07:30:58 +00003753 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregorb92a4082012-06-12 13:44:08 +00003754 if (EnumDecl *Def = Enum->getDefinition())
3755 Enum = Def;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003756
3757 // Determine which enumerators we have already seen in the switch statement.
3758 // FIXME: Ideally, we would also be able to look *past* the code-completion
3759 // token, in case we are code-completing in the middle of the switch and not
3760 // at the end. However, we aren't able to do so at the moment.
3761 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003762 NestedNameSpecifier *Qualifier = 0;
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003763 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
3764 SC = SC->getNextSwitchCase()) {
3765 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
3766 if (!Case)
3767 continue;
3768
3769 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
3770 if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(CaseVal))
3771 if (EnumConstantDecl *Enumerator
3772 = dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
3773 // We look into the AST of the case statement to determine which
3774 // enumerator was named. Alternatively, we could compute the value of
3775 // the integral constant expression, then compare it against the
3776 // values of each enumerator. However, value-based approach would not
3777 // work as well with C++ templates where enumerators declared within a
3778 // template are type- and value-dependent.
3779 EnumeratorsSeen.insert(Enumerator);
3780
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003781 // If this is a qualified-id, keep track of the nested-name-specifier
3782 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003783 //
3784 // switch (TagD.getKind()) {
3785 // case TagDecl::TK_enum:
3786 // break;
3787 // case XXX
3788 //
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003789 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003790 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
3791 // TK_struct, and TK_class.
Douglas Gregora2813ce2009-10-23 18:54:35 +00003792 Qualifier = DRE->getQualifier();
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003793 }
3794 }
3795
David Blaikie4e4d0842012-03-11 07:00:24 +00003796 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003797 // If there are no prior enumerators in C++, check whether we have to
3798 // qualify the names of the enumerators that we suggest, because they
3799 // may not be visible in this scope.
Douglas Gregorb223d8c2012-02-01 05:02:47 +00003800 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorb9d0ef72009-09-21 19:57:38 +00003801 }
3802
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003803 // Add any enumerators that have not yet been mentioned.
Douglas Gregor218937c2011-02-01 19:23:04 +00003804 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003805 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00003806 CodeCompletionContext::CCC_Expression);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003807 Results.EnterNewScope();
3808 for (EnumDecl::enumerator_iterator E = Enum->enumerator_begin(),
3809 EEnd = Enum->enumerator_end();
3810 E != EEnd; ++E) {
David Blaikie581deb32012-06-06 20:45:41 +00003811 if (EnumeratorsSeen.count(*E))
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003812 continue;
3813
Douglas Gregord1f09b42013-01-31 04:52:16 +00003814 CodeCompletionResult R(*E, CCP_EnumInCase, Qualifier);
Douglas Gregor5c722c702011-02-18 23:30:37 +00003815 Results.AddResult(R, CurContext, 0, false);
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003816 }
3817 Results.ExitScope();
Douglas Gregor2f880e42010-04-06 20:02:15 +00003818
Douglas Gregor3da626b2011-07-07 16:03:39 +00003819 //We need to make sure we're setting the right context,
3820 //so only say we include macros if the code completer says we do
3821 enum CodeCompletionContext::Kind kind = CodeCompletionContext::CCC_Other;
3822 if (CodeCompleter->includeMacros()) {
Douglas Gregor3644d972012-10-09 16:01:50 +00003823 AddMacroResults(PP, Results, false);
Douglas Gregor3da626b2011-07-07 16:03:39 +00003824 kind = CodeCompletionContext::CCC_OtherWithMacros;
3825 }
3826
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003827 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00003828 kind,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003829 Results.data(),Results.size());
Douglas Gregor3e1005f2009-09-21 18:10:23 +00003830}
3831
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003832namespace {
3833 struct IsBetterOverloadCandidate {
3834 Sema &S;
John McCall5769d612010-02-08 23:07:23 +00003835 SourceLocation Loc;
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003836
3837 public:
John McCall5769d612010-02-08 23:07:23 +00003838 explicit IsBetterOverloadCandidate(Sema &S, SourceLocation Loc)
3839 : S(S), Loc(Loc) { }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003840
3841 bool
3842 operator()(const OverloadCandidate &X, const OverloadCandidate &Y) const {
John McCall120d63c2010-08-24 20:38:10 +00003843 return isBetterOverloadCandidate(S, X, Y, Loc);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003844 }
3845 };
3846}
3847
Robert Wilhelm834c0582013-08-09 18:02:13 +00003848static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003849 if (Args.size() && !Args.data())
Douglas Gregord28dcd72010-05-30 06:10:08 +00003850 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003851
3852 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregord28dcd72010-05-30 06:10:08 +00003853 if (!Args[I])
3854 return true;
Ahmed Charles13a140c2012-02-25 11:00:22 +00003855
Douglas Gregord28dcd72010-05-30 06:10:08 +00003856 return false;
3857}
3858
Robert Wilhelm834c0582013-08-09 18:02:13 +00003859void Sema::CodeCompleteCall(Scope *S, Expr *FnIn, ArrayRef<Expr *> Args) {
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003860 if (!CodeCompleter)
3861 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003862
3863 // When we're code-completing for a call, we fall back to ordinary
3864 // name code-completion whenever we can't produce specific
3865 // results. We may want to revisit this strategy in the future,
3866 // e.g., by merging the two kinds of results.
3867
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003868 Expr *Fn = (Expr *)FnIn;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003869
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003870 // Ignore type-dependent call expressions entirely.
Ahmed Charles13a140c2012-02-25 11:00:22 +00003871 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
3872 Expr::hasAnyTypeDependentArguments(Args)) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003873 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003874 return;
Douglas Gregoref96eac2009-12-11 19:06:04 +00003875 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003876
John McCall3b4294e2009-12-16 12:17:52 +00003877 // Build an overload candidate set based on the functions we find.
John McCall5769d612010-02-08 23:07:23 +00003878 SourceLocation Loc = Fn->getExprLoc();
3879 OverloadCandidateSet CandidateSet(Loc);
John McCall3b4294e2009-12-16 12:17:52 +00003880
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003881 // FIXME: What if we're calling something that isn't a function declaration?
3882 // FIXME: What if we're calling a pseudo-destructor?
3883 // FIXME: What if we're calling a member function?
3884
Douglas Gregorc0265402010-01-21 15:46:19 +00003885 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
Chris Lattner5f9e2722011-07-23 10:55:15 +00003886 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorc0265402010-01-21 15:46:19 +00003887
John McCall3b4294e2009-12-16 12:17:52 +00003888 Expr *NakedFn = Fn->IgnoreParenCasts();
3889 if (UnresolvedLookupExpr *ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003890 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
John McCall3b4294e2009-12-16 12:17:52 +00003891 /*PartialOverloading=*/ true);
3892 else if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(NakedFn)) {
3893 FunctionDecl *FDecl = dyn_cast<FunctionDecl>(DRE->getDecl());
Douglas Gregorc0265402010-01-21 15:46:19 +00003894 if (FDecl) {
David Blaikie4e4d0842012-03-11 07:00:24 +00003895 if (!getLangOpts().CPlusPlus ||
Douglas Gregord28dcd72010-05-30 06:10:08 +00003896 !FDecl->getType()->getAs<FunctionProtoType>())
Douglas Gregorc0265402010-01-21 15:46:19 +00003897 Results.push_back(ResultCandidate(FDecl));
3898 else
John McCall86820f52010-01-26 01:37:31 +00003899 // FIXME: access?
Ahmed Charles13a140c2012-02-25 11:00:22 +00003900 AddOverloadCandidate(FDecl, DeclAccessPair::make(FDecl, AS_none), Args,
3901 CandidateSet, false, /*PartialOverloading*/true);
Douglas Gregorc0265402010-01-21 15:46:19 +00003902 }
John McCall3b4294e2009-12-16 12:17:52 +00003903 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003904
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003905 QualType ParamType;
3906
Douglas Gregorc0265402010-01-21 15:46:19 +00003907 if (!CandidateSet.empty()) {
3908 // Sort the overload candidate set by placing the best overloads first.
3909 std::stable_sort(CandidateSet.begin(), CandidateSet.end(),
John McCall5769d612010-02-08 23:07:23 +00003910 IsBetterOverloadCandidate(*this, Loc));
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003911
Douglas Gregorc0265402010-01-21 15:46:19 +00003912 // Add the remaining viable overload candidates as code-completion reslults.
3913 for (OverloadCandidateSet::iterator Cand = CandidateSet.begin(),
3914 CandEnd = CandidateSet.end();
3915 Cand != CandEnd; ++Cand) {
3916 if (Cand->Viable)
3917 Results.push_back(ResultCandidate(Cand->Function));
3918 }
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003919
3920 // From the viable candidates, try to determine the type of this parameter.
3921 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
3922 if (const FunctionType *FType = Results[I].getFunctionType())
3923 if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FType))
Ahmed Charles13a140c2012-02-25 11:00:22 +00003924 if (Args.size() < Proto->getNumArgs()) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003925 if (ParamType.isNull())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003926 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003927 else if (!Context.hasSameUnqualifiedType(
3928 ParamType.getNonReferenceType(),
Ahmed Charles13a140c2012-02-25 11:00:22 +00003929 Proto->getArgType(Args.size()).getNonReferenceType())) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003930 ParamType = QualType();
3931 break;
3932 }
3933 }
3934 }
3935 } else {
3936 // Try to determine the parameter type from the type of the expression
3937 // being called.
3938 QualType FunctionType = Fn->getType();
3939 if (const PointerType *Ptr = FunctionType->getAs<PointerType>())
3940 FunctionType = Ptr->getPointeeType();
3941 else if (const BlockPointerType *BlockPtr
3942 = FunctionType->getAs<BlockPointerType>())
3943 FunctionType = BlockPtr->getPointeeType();
3944 else if (const MemberPointerType *MemPtr
3945 = FunctionType->getAs<MemberPointerType>())
3946 FunctionType = MemPtr->getPointeeType();
3947
3948 if (const FunctionProtoType *Proto
3949 = FunctionType->getAs<FunctionProtoType>()) {
Ahmed Charles13a140c2012-02-25 11:00:22 +00003950 if (Args.size() < Proto->getNumArgs())
3951 ParamType = Proto->getArgType(Args.size());
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003952 }
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003953 }
Douglas Gregoref96eac2009-12-11 19:06:04 +00003954
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003955 if (ParamType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003956 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003957 else
3958 CodeCompleteExpression(S, ParamType);
3959
Douglas Gregor2e4c7a52010-04-06 20:19:47 +00003960 if (!Results.empty())
Ahmed Charles13a140c2012-02-25 11:00:22 +00003961 CodeCompleter->ProcessOverloadCandidates(*this, Args.size(), Results.data(),
Douglas Gregoref96eac2009-12-11 19:06:04 +00003962 Results.size());
Douglas Gregor9c6a0e92009-09-22 15:41:20 +00003963}
3964
John McCalld226f652010-08-21 09:40:31 +00003965void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
3966 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003967 if (!VD) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003968 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003969 return;
3970 }
3971
3972 CodeCompleteExpression(S, VD->getType());
3973}
3974
3975void Sema::CodeCompleteReturn(Scope *S) {
3976 QualType ResultType;
3977 if (isa<BlockDecl>(CurContext)) {
3978 if (BlockScopeInfo *BSI = getCurBlock())
3979 ResultType = BSI->ReturnType;
3980 } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(CurContext))
3981 ResultType = Function->getResultType();
3982 else if (ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(CurContext))
3983 ResultType = Method->getResultType();
3984
3985 if (ResultType.isNull())
Douglas Gregore6b1bb62010-08-11 21:23:17 +00003986 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00003987 else
3988 CodeCompleteExpression(S, ResultType);
3989}
3990
Douglas Gregord2d8be62011-07-30 08:36:53 +00003991void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregord2d8be62011-07-30 08:36:53 +00003992 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00003993 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord2d8be62011-07-30 08:36:53 +00003994 mapCodeCompletionContext(*this, PCC_Statement));
3995 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3996 Results.EnterNewScope();
3997
3998 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3999 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4000 CodeCompleter->includeGlobals());
4001
4002 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
4003
4004 // "else" block
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004005 CodeCompletionBuilder Builder(Results.getAllocator(),
4006 Results.getCodeCompletionTUInfo());
Douglas Gregord2d8be62011-07-30 08:36:53 +00004007 Builder.AddTypedTextChunk("else");
Douglas Gregorf11641a2012-02-16 17:49:04 +00004008 if (Results.includeCodePatterns()) {
4009 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4010 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4011 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4012 Builder.AddPlaceholderChunk("statements");
4013 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4014 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4015 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00004016 Results.AddResult(Builder.TakeString());
4017
4018 // "else if" block
4019 Builder.AddTypedTextChunk("else");
4020 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4021 Builder.AddTextChunk("if");
4022 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4023 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikie4e4d0842012-03-11 07:00:24 +00004024 if (getLangOpts().CPlusPlus)
Douglas Gregord2d8be62011-07-30 08:36:53 +00004025 Builder.AddPlaceholderChunk("condition");
4026 else
4027 Builder.AddPlaceholderChunk("expression");
4028 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf11641a2012-02-16 17:49:04 +00004029 if (Results.includeCodePatterns()) {
4030 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4031 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4032 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4033 Builder.AddPlaceholderChunk("statements");
4034 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4035 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4036 }
Douglas Gregord2d8be62011-07-30 08:36:53 +00004037 Results.AddResult(Builder.TakeString());
4038
4039 Results.ExitScope();
4040
4041 if (S->getFnParent())
David Blaikie4e4d0842012-03-11 07:00:24 +00004042 AddPrettyFunctionResults(PP.getLangOpts(), Results);
Douglas Gregord2d8be62011-07-30 08:36:53 +00004043
4044 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00004045 AddMacroResults(PP, Results, false);
Douglas Gregord2d8be62011-07-30 08:36:53 +00004046
4047 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4048 Results.data(),Results.size());
4049}
4050
Richard Trieuf81e5a92011-09-09 02:00:50 +00004051void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00004052 if (LHS)
4053 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4054 else
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004055 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor5ac3bdb2010-05-30 01:49:25 +00004056}
4057
Jeffrey Yasskin9ab14542010-04-08 16:38:48 +00004058void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Douglas Gregor81b747b2009-09-17 21:32:03 +00004059 bool EnteringContext) {
4060 if (!SS.getScopeRep() || !CodeCompleter)
4061 return;
4062
Douglas Gregor86d9a522009-09-21 16:56:56 +00004063 DeclContext *Ctx = computeDeclContext(SS, EnteringContext);
4064 if (!Ctx)
4065 return;
Douglas Gregord1cd31a2009-12-11 18:28:39 +00004066
4067 // Try to instantiate any non-dependent declaration contexts before
4068 // we look in them.
John McCall77bb1aa2010-05-01 00:40:08 +00004069 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregord1cd31a2009-12-11 18:28:39 +00004070 return;
4071
Douglas Gregor218937c2011-02-01 19:23:04 +00004072 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004073 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004074 CodeCompletionContext::CCC_Name);
Douglas Gregorf6961522010-08-27 21:18:54 +00004075 Results.EnterNewScope();
Douglas Gregor52779fb2010-09-23 23:01:17 +00004076
Douglas Gregor86d9a522009-09-21 16:56:56 +00004077 // The "template" keyword can follow "::" in the grammar, but only
4078 // put it into the grammar if the nested-name-specifier is dependent.
4079 NestedNameSpecifier *NNS = (NestedNameSpecifier *)SS.getScopeRep();
4080 if (!Results.empty() && NNS->isDependent())
Douglas Gregora4477812010-01-14 16:01:26 +00004081 Results.AddResult("template");
Douglas Gregorf6961522010-08-27 21:18:54 +00004082
4083 // Add calls to overridden virtual functions, if there are any.
4084 //
4085 // FIXME: This isn't wonderful, because we don't know whether we're actually
4086 // in a context that permits expressions. This is a general issue with
4087 // qualified-id completions.
4088 if (!EnteringContext)
4089 MaybeAddOverrideCalls(*this, Ctx, Results);
4090 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004091
Douglas Gregorf6961522010-08-27 21:18:54 +00004092 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4093 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer);
4094
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004095 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor430d7a12011-07-25 17:48:11 +00004096 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004097 Results.data(),Results.size());
Douglas Gregor81b747b2009-09-17 21:32:03 +00004098}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004099
4100void Sema::CodeCompleteUsing(Scope *S) {
4101 if (!CodeCompleter)
4102 return;
4103
Douglas Gregor218937c2011-02-01 19:23:04 +00004104 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004105 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004106 CodeCompletionContext::CCC_PotentiallyQualifiedName,
4107 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004108 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004109
4110 // If we aren't in class scope, we could see the "namespace" keyword.
4111 if (!S->isClassScope())
John McCall0a2c5e22010-08-25 06:19:51 +00004112 Results.AddResult(CodeCompletionResult("namespace"));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004113
4114 // After "using", we can see anything that would start a
4115 // nested-name-specifier.
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004116 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004117 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4118 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004119 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004120
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004121 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004122 CodeCompletionContext::CCC_PotentiallyQualifiedName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004123 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004124}
4125
4126void Sema::CodeCompleteUsingDirective(Scope *S) {
4127 if (!CodeCompleter)
4128 return;
4129
Douglas Gregor86d9a522009-09-21 16:56:56 +00004130 // After "using namespace", we expect to see a namespace name or namespace
4131 // alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004132 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004133 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004134 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004135 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004136 Results.EnterNewScope();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004137 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004138 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4139 CodeCompleter->includeGlobals());
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004140 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004141 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004142 CodeCompletionContext::CCC_Namespace,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004143 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004144}
4145
4146void Sema::CodeCompleteNamespaceDecl(Scope *S) {
4147 if (!CodeCompleter)
4148 return;
4149
Douglas Gregor86d9a522009-09-21 16:56:56 +00004150 DeclContext *Ctx = (DeclContext *)S->getEntity();
4151 if (!S->getParent())
4152 Ctx = Context.getTranslationUnitDecl();
4153
Douglas Gregor52779fb2010-09-23 23:01:17 +00004154 bool SuppressedGlobalResults
4155 = Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
4156
Douglas Gregor218937c2011-02-01 19:23:04 +00004157 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004158 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004159 SuppressedGlobalResults
4160 ? CodeCompletionContext::CCC_Namespace
4161 : CodeCompletionContext::CCC_Other,
4162 &ResultBuilder::IsNamespace);
4163
4164 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor86d9a522009-09-21 16:56:56 +00004165 // We only want to see those namespaces that have already been defined
4166 // within this scope, because its likely that the user is creating an
4167 // extended namespace declaration. Keep track of the most recent
4168 // definition of each namespace.
4169 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
4170 for (DeclContext::specific_decl_iterator<NamespaceDecl>
4171 NS(Ctx->decls_begin()), NSEnd(Ctx->decls_end());
4172 NS != NSEnd; ++NS)
David Blaikie581deb32012-06-06 20:45:41 +00004173 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004174
4175 // Add the most recent definition (or extended definition) of each
4176 // namespace to the list of results.
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004177 Results.EnterNewScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004178 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Douglas Gregorba103062012-03-27 23:34:16 +00004179 NS = OrigToLatest.begin(),
4180 NSEnd = OrigToLatest.end();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004181 NS != NSEnd; ++NS)
Douglas Gregord1f09b42013-01-31 04:52:16 +00004182 Results.AddResult(CodeCompletionResult(
4183 NS->second, Results.getBasePriority(NS->second), 0),
Douglas Gregor608300b2010-01-14 16:14:35 +00004184 CurContext, 0, false);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004185 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004186 }
4187
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004188 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004189 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004190 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004191}
4192
4193void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
4194 if (!CodeCompleter)
4195 return;
4196
Douglas Gregor86d9a522009-09-21 16:56:56 +00004197 // After "namespace", we expect to see a namespace or alias.
Douglas Gregor218937c2011-02-01 19:23:04 +00004198 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004199 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004200 CodeCompletionContext::CCC_Namespace,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004201 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004202 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004203 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4204 CodeCompleter->includeGlobals());
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004205 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004206 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004207 Results.data(),Results.size());
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004208}
4209
Douglas Gregored8d3222009-09-18 20:05:18 +00004210void Sema::CodeCompleteOperatorName(Scope *S) {
4211 if (!CodeCompleter)
4212 return;
Douglas Gregor86d9a522009-09-21 16:56:56 +00004213
John McCall0a2c5e22010-08-25 06:19:51 +00004214 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00004215 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004216 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004217 CodeCompletionContext::CCC_Type,
Douglas Gregor52779fb2010-09-23 23:01:17 +00004218 &ResultBuilder::IsType);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004219 Results.EnterNewScope();
Douglas Gregored8d3222009-09-18 20:05:18 +00004220
Douglas Gregor86d9a522009-09-21 16:56:56 +00004221 // Add the names of overloadable operators.
4222#define OVERLOADED_OPERATOR(Name,Spelling,Token,Unary,Binary,MemberOnly) \
4223 if (std::strcmp(Spelling, "?")) \
Douglas Gregora4477812010-01-14 16:01:26 +00004224 Results.AddResult(Result(Spelling));
Douglas Gregor86d9a522009-09-21 16:56:56 +00004225#include "clang/Basic/OperatorKinds.def"
4226
4227 // Add any type names visible from the current scope
Douglas Gregor45bcd432010-01-14 03:21:49 +00004228 Results.allowNestedNameSpecifiers();
Douglas Gregor5d2fc402010-01-14 03:27:13 +00004229 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor8071e422010-08-15 06:18:01 +00004230 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
4231 CodeCompleter->includeGlobals());
Douglas Gregor86d9a522009-09-21 16:56:56 +00004232
4233 // Add any type specifiers
David Blaikie4e4d0842012-03-11 07:00:24 +00004234 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor8e0a0e42009-09-22 23:31:26 +00004235 Results.ExitScope();
Douglas Gregor86d9a522009-09-21 16:56:56 +00004236
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004237 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor8071e422010-08-15 06:18:01 +00004238 CodeCompletionContext::CCC_Type,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004239 Results.data(),Results.size());
Douglas Gregored8d3222009-09-18 20:05:18 +00004240}
Douglas Gregor49f40bd2009-09-18 19:03:04 +00004241
Dmitri Gribenko572cf582013-06-23 22:58:02 +00004242void Sema::CodeCompleteConstructorInitializer(
4243 Decl *ConstructorD,
4244 ArrayRef <CXXCtorInitializer *> Initializers) {
Douglas Gregor8987b232011-09-27 23:30:47 +00004245 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregor0133f522010-08-28 00:00:50 +00004246 CXXConstructorDecl *Constructor
4247 = static_cast<CXXConstructorDecl *>(ConstructorD);
4248 if (!Constructor)
4249 return;
4250
Douglas Gregor218937c2011-02-01 19:23:04 +00004251 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004252 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00004253 CodeCompletionContext::CCC_PotentiallyQualifiedName);
Douglas Gregor0133f522010-08-28 00:00:50 +00004254 Results.EnterNewScope();
4255
4256 // Fill in any already-initialized fields or base classes.
4257 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
4258 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko572cf582013-06-23 22:58:02 +00004259 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregor0133f522010-08-28 00:00:50 +00004260 if (Initializers[I]->isBaseInitializer())
4261 InitializedBases.insert(
4262 Context.getCanonicalType(QualType(Initializers[I]->getBaseClass(), 0)));
4263 else
Francois Pichet00eb3f92010-12-04 09:14:42 +00004264 InitializedFields.insert(cast<FieldDecl>(
4265 Initializers[I]->getAnyMember()));
Douglas Gregor0133f522010-08-28 00:00:50 +00004266 }
4267
4268 // Add completions for base classes.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004269 CodeCompletionBuilder Builder(Results.getAllocator(),
4270 Results.getCodeCompletionTUInfo());
Dmitri Gribenko572cf582013-06-23 22:58:02 +00004271 bool SawLastInitializer = Initializers.empty();
Douglas Gregor0133f522010-08-28 00:00:50 +00004272 CXXRecordDecl *ClassDecl = Constructor->getParent();
4273 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->bases_begin(),
4274 BaseEnd = ClassDecl->bases_end();
4275 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004276 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4277 SawLastInitializer
Dmitri Gribenko572cf582013-06-23 22:58:02 +00004278 = !Initializers.empty() &&
4279 Initializers.back()->isBaseInitializer() &&
Douglas Gregor0c431c82010-08-29 19:27:27 +00004280 Context.hasSameUnqualifiedType(Base->getType(),
Dmitri Gribenko572cf582013-06-23 22:58:02 +00004281 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004282 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004283 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004284
Douglas Gregor218937c2011-02-01 19:23:04 +00004285 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004286 Results.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004287 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004288 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4289 Builder.AddPlaceholderChunk("args");
4290 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4291 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004292 SawLastInitializer? CCP_NextInitializer
4293 : CCP_MemberDeclaration));
4294 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004295 }
4296
4297 // Add completions for virtual base classes.
4298 for (CXXRecordDecl::base_class_iterator Base = ClassDecl->vbases_begin(),
4299 BaseEnd = ClassDecl->vbases_end();
4300 Base != BaseEnd; ++Base) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004301 if (!InitializedBases.insert(Context.getCanonicalType(Base->getType()))) {
4302 SawLastInitializer
Dmitri Gribenko572cf582013-06-23 22:58:02 +00004303 = !Initializers.empty() &&
4304 Initializers.back()->isBaseInitializer() &&
Douglas Gregor0c431c82010-08-29 19:27:27 +00004305 Context.hasSameUnqualifiedType(Base->getType(),
Dmitri Gribenko572cf582013-06-23 22:58:02 +00004306 QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregor0133f522010-08-28 00:00:50 +00004307 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004308 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004309
Douglas Gregor218937c2011-02-01 19:23:04 +00004310 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00004311 Builder.getAllocator().CopyString(
John McCallf85e1932011-06-15 23:02:42 +00004312 Base->getType().getAsString(Policy)));
Douglas Gregor218937c2011-02-01 19:23:04 +00004313 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4314 Builder.AddPlaceholderChunk("args");
4315 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4316 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004317 SawLastInitializer? CCP_NextInitializer
4318 : CCP_MemberDeclaration));
4319 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004320 }
4321
4322 // Add completions for members.
4323 for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
4324 FieldEnd = ClassDecl->field_end();
4325 Field != FieldEnd; ++Field) {
Douglas Gregor0c431c82010-08-29 19:27:27 +00004326 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))) {
4327 SawLastInitializer
Dmitri Gribenko572cf582013-06-23 22:58:02 +00004328 = !Initializers.empty() &&
4329 Initializers.back()->isAnyMemberInitializer() &&
4330 Initializers.back()->getAnyMember() == *Field;
Douglas Gregor0133f522010-08-28 00:00:50 +00004331 continue;
Douglas Gregor0c431c82010-08-29 19:27:27 +00004332 }
Douglas Gregor0133f522010-08-28 00:00:50 +00004333
4334 if (!Field->getDeclName())
4335 continue;
4336
Douglas Gregordae68752011-02-01 22:57:45 +00004337 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00004338 Field->getIdentifier()->getName()));
4339 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4340 Builder.AddPlaceholderChunk("args");
4341 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4342 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
Douglas Gregor0c431c82010-08-29 19:27:27 +00004343 SawLastInitializer? CCP_NextInitializer
Douglas Gregora67e03f2010-09-09 21:42:20 +00004344 : CCP_MemberDeclaration,
Douglas Gregorba103062012-03-27 23:34:16 +00004345 CXCursor_MemberRef,
4346 CXAvailability_Available,
David Blaikie581deb32012-06-06 20:45:41 +00004347 *Field));
Douglas Gregor0c431c82010-08-29 19:27:27 +00004348 SawLastInitializer = false;
Douglas Gregor0133f522010-08-28 00:00:50 +00004349 }
4350 Results.ExitScope();
4351
Douglas Gregor52779fb2010-09-23 23:01:17 +00004352 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor0133f522010-08-28 00:00:50 +00004353 Results.data(), Results.size());
4354}
4355
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004356/// \brief Determine whether this scope denotes a namespace.
4357static bool isNamespaceScope(Scope *S) {
4358 DeclContext *DC = static_cast<DeclContext *>(S->getEntity());
4359 if (!DC)
4360 return false;
4361
4362 return DC->isFileContext();
4363}
4364
4365void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
4366 bool AfterAmpersand) {
4367 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004368 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004369 CodeCompletionContext::CCC_Other);
4370 Results.EnterNewScope();
4371
4372 // Note what has already been captured.
4373 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
4374 bool IncludedThis = false;
4375 for (SmallVectorImpl<LambdaCapture>::iterator C = Intro.Captures.begin(),
4376 CEnd = Intro.Captures.end();
4377 C != CEnd; ++C) {
4378 if (C->Kind == LCK_This) {
4379 IncludedThis = true;
4380 continue;
4381 }
4382
4383 Known.insert(C->Id);
4384 }
4385
4386 // Look for other capturable variables.
4387 for (; S && !isNamespaceScope(S); S = S->getParent()) {
4388 for (Scope::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
4389 D != DEnd; ++D) {
4390 VarDecl *Var = dyn_cast<VarDecl>(*D);
4391 if (!Var ||
4392 !Var->hasLocalStorage() ||
4393 Var->hasAttr<BlocksAttr>())
4394 continue;
4395
4396 if (Known.insert(Var->getIdentifier()))
Douglas Gregord1f09b42013-01-31 04:52:16 +00004397 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
4398 CurContext, 0, false);
Douglas Gregor81f3bff2012-02-15 15:34:24 +00004399 }
4400 }
4401
4402 // Add 'this', if it would be valid.
4403 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
4404 addThisCompletion(*this, Results);
4405
4406 Results.ExitScope();
4407
4408 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4409 Results.data(), Results.size());
4410}
4411
James Dennetta40f7922012-06-14 03:11:41 +00004412/// Macro that optionally prepends an "@" to the string literal passed in via
4413/// Keyword, depending on whether NeedAt is true or false.
4414#define OBJC_AT_KEYWORD_NAME(NeedAt,Keyword) ((NeedAt)? "@" Keyword : Keyword)
4415
Douglas Gregorbca403c2010-01-13 23:51:12 +00004416static void AddObjCImplementationResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004417 ResultBuilder &Results,
4418 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004419 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004420 // Since we have an implementation, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004421 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004422
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004423 CodeCompletionBuilder Builder(Results.getAllocator(),
4424 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004425 if (LangOpts.ObjC2) {
4426 // @dynamic
James Dennetta40f7922012-06-14 03:11:41 +00004427 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"dynamic"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004428 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4429 Builder.AddPlaceholderChunk("property");
4430 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004431
4432 // @synthesize
James Dennetta40f7922012-06-14 03:11:41 +00004433 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synthesize"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004434 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4435 Builder.AddPlaceholderChunk("property");
4436 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004437 }
4438}
4439
Douglas Gregorbca403c2010-01-13 23:51:12 +00004440static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004441 ResultBuilder &Results,
4442 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004443 typedef CodeCompletionResult Result;
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004444
4445 // Since we have an interface or protocol, we can end it.
James Dennetta40f7922012-06-14 03:11:41 +00004446 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"end")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004447
4448 if (LangOpts.ObjC2) {
4449 // @property
James Dennetta40f7922012-06-14 03:11:41 +00004450 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"property")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004451
4452 // @required
James Dennetta40f7922012-06-14 03:11:41 +00004453 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"required")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004454
4455 // @optional
James Dennetta40f7922012-06-14 03:11:41 +00004456 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"optional")));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004457 }
4458}
4459
Douglas Gregorbca403c2010-01-13 23:51:12 +00004460static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004461 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004462 CodeCompletionBuilder Builder(Results.getAllocator(),
4463 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004464
4465 // @class name ;
James Dennetta40f7922012-06-14 03:11:41 +00004466 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"class"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004467 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4468 Builder.AddPlaceholderChunk("name");
4469 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004470
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004471 if (Results.includeCodePatterns()) {
4472 // @interface name
4473 // FIXME: Could introduce the whole pattern, including superclasses and
4474 // such.
James Dennetta40f7922012-06-14 03:11:41 +00004475 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"interface"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004476 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4477 Builder.AddPlaceholderChunk("class");
4478 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004479
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004480 // @protocol name
James Dennetta40f7922012-06-14 03:11:41 +00004481 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004482 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4483 Builder.AddPlaceholderChunk("protocol");
4484 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004485
4486 // @implementation name
James Dennetta40f7922012-06-14 03:11:41 +00004487 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"implementation"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004488 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4489 Builder.AddPlaceholderChunk("class");
4490 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004491 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004492
4493 // @compatibility_alias name
James Dennetta40f7922012-06-14 03:11:41 +00004494 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"compatibility_alias"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004495 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4496 Builder.AddPlaceholderChunk("alias");
4497 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4498 Builder.AddPlaceholderChunk("class");
4499 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor06898632013-03-07 23:26:24 +00004500
4501 if (Results.getSema().getLangOpts().Modules) {
4502 // @import name
4503 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
4504 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4505 Builder.AddPlaceholderChunk("module");
4506 Results.AddResult(Result(Builder.TakeString()));
4507 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004508}
4509
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004510void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004511 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004512 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004513 CodeCompletionContext::CCC_Other);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004514 Results.EnterNewScope();
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004515 if (isa<ObjCImplDecl>(CurContext))
David Blaikie4e4d0842012-03-11 07:00:24 +00004516 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004517 else if (CurContext->isObjCContainer())
David Blaikie4e4d0842012-03-11 07:00:24 +00004518 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004519 else
Douglas Gregorbca403c2010-01-13 23:51:12 +00004520 AddObjCTopLevelResults(Results, false);
Douglas Gregorc464ae82009-12-07 09:27:33 +00004521 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004522 HandleCodeCompleteResults(this, CodeCompleter,
4523 CodeCompletionContext::CCC_Other,
4524 Results.data(),Results.size());
Douglas Gregorc464ae82009-12-07 09:27:33 +00004525}
4526
Douglas Gregorbca403c2010-01-13 23:51:12 +00004527static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004528 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004529 CodeCompletionBuilder Builder(Results.getAllocator(),
4530 Results.getCodeCompletionTUInfo());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004531
4532 // @encode ( type-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004533 const char *EncodeType = "char[]";
David Blaikie4e4d0842012-03-11 07:00:24 +00004534 if (Results.getSema().getLangOpts().CPlusPlus ||
4535 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004536 EncodeType = "const char[]";
Douglas Gregor8ca72082011-10-18 21:20:17 +00004537 Builder.AddResultTypeChunk(EncodeType);
James Dennetta40f7922012-06-14 03:11:41 +00004538 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"encode"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004539 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4540 Builder.AddPlaceholderChunk("type-name");
4541 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4542 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004543
4544 // @protocol ( protocol-name )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004545 Builder.AddResultTypeChunk("Protocol *");
James Dennetta40f7922012-06-14 03:11:41 +00004546 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"protocol"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004547 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4548 Builder.AddPlaceholderChunk("protocol-name");
4549 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4550 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004551
4552 // @selector ( selector )
Douglas Gregor8ca72082011-10-18 21:20:17 +00004553 Builder.AddResultTypeChunk("SEL");
James Dennetta40f7922012-06-14 03:11:41 +00004554 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"selector"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004555 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4556 Builder.AddPlaceholderChunk("selector");
4557 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4558 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004559
4560 // @"string"
4561 Builder.AddResultTypeChunk("NSString *");
4562 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"\""));
4563 Builder.AddPlaceholderChunk("string");
4564 Builder.AddTextChunk("\"");
4565 Results.AddResult(Result(Builder.TakeString()));
4566
Douglas Gregor79615892012-07-17 23:24:47 +00004567 // @[objects, ...]
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004568 Builder.AddResultTypeChunk("NSArray *");
James Dennetta40f7922012-06-14 03:11:41 +00004569 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"["));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004570 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004571 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
4572 Results.AddResult(Result(Builder.TakeString()));
4573
Douglas Gregor79615892012-07-17 23:24:47 +00004574 // @{key : object, ...}
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004575 Builder.AddResultTypeChunk("NSDictionary *");
James Dennetta40f7922012-06-14 03:11:41 +00004576 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"{"));
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004577 Builder.AddPlaceholderChunk("key");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004578 Builder.AddChunk(CodeCompletionString::CK_Colon);
4579 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4580 Builder.AddPlaceholderChunk("object, ...");
Ted Kremenekebcb57a2012-03-06 20:05:56 +00004581 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4582 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004583
Douglas Gregor79615892012-07-17 23:24:47 +00004584 // @(expression)
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004585 Builder.AddResultTypeChunk("id");
4586 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004587 Builder.AddPlaceholderChunk("expression");
Jordan Rose1f6e22d2012-06-15 18:19:56 +00004588 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4589 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004590}
4591
Douglas Gregorbca403c2010-01-13 23:51:12 +00004592static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004593 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004594 CodeCompletionBuilder Builder(Results.getAllocator(),
4595 Results.getCodeCompletionTUInfo());
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004596
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004597 if (Results.includeCodePatterns()) {
4598 // @try { statements } @catch ( declaration ) { statements } @finally
4599 // { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004600 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"try"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004601 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4602 Builder.AddPlaceholderChunk("statements");
4603 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4604 Builder.AddTextChunk("@catch");
4605 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4606 Builder.AddPlaceholderChunk("parameter");
4607 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4608 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4609 Builder.AddPlaceholderChunk("statements");
4610 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4611 Builder.AddTextChunk("@finally");
4612 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4613 Builder.AddPlaceholderChunk("statements");
4614 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4615 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004616 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004617
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004618 // @throw
James Dennetta40f7922012-06-14 03:11:41 +00004619 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"throw"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004620 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4621 Builder.AddPlaceholderChunk("expression");
4622 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004623
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004624 if (Results.includeCodePatterns()) {
4625 // @synchronized ( expression ) { statements }
James Dennetta40f7922012-06-14 03:11:41 +00004626 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt,"synchronized"));
Douglas Gregor218937c2011-02-01 19:23:04 +00004627 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4628 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
4629 Builder.AddPlaceholderChunk("expression");
4630 Builder.AddChunk(CodeCompletionString::CK_RightParen);
4631 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4632 Builder.AddPlaceholderChunk("statements");
4633 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4634 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc8bddde2010-05-28 00:22:41 +00004635 }
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004636}
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004637
Douglas Gregorbca403c2010-01-13 23:51:12 +00004638static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004639 ResultBuilder &Results,
4640 bool NeedAt) {
John McCall0a2c5e22010-08-25 06:19:51 +00004641 typedef CodeCompletionResult Result;
James Dennetta40f7922012-06-14 03:11:41 +00004642 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"private")));
4643 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"protected")));
4644 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"public")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004645 if (LangOpts.ObjC2)
James Dennetta40f7922012-06-14 03:11:41 +00004646 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt,"package")));
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004647}
4648
4649void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004650 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004651 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004652 CodeCompletionContext::CCC_Other);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004653 Results.EnterNewScope();
David Blaikie4e4d0842012-03-11 07:00:24 +00004654 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004655 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004656 HandleCodeCompleteResults(this, CodeCompleter,
4657 CodeCompletionContext::CCC_Other,
4658 Results.data(),Results.size());
Douglas Gregorc38c3e12010-01-13 21:54:15 +00004659}
4660
4661void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004662 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004663 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004664 CodeCompletionContext::CCC_Other);
Douglas Gregorb6ac2452010-01-13 21:24:21 +00004665 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004666 AddObjCStatementResults(Results, false);
4667 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004668 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004669 HandleCodeCompleteResults(this, CodeCompleter,
4670 CodeCompletionContext::CCC_Other,
4671 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004672}
4673
4674void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00004675 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004676 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004677 CodeCompletionContext::CCC_Other);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004678 Results.EnterNewScope();
Douglas Gregorbca403c2010-01-13 23:51:12 +00004679 AddObjCExpressionResults(Results, false);
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004680 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004681 HandleCodeCompleteResults(this, CodeCompleter,
4682 CodeCompletionContext::CCC_Other,
4683 Results.data(),Results.size());
Douglas Gregor9a0c85e2009-12-07 09:51:25 +00004684}
4685
Douglas Gregor988358f2009-11-19 00:14:45 +00004686/// \brief Determine whether the addition of the given flag to an Objective-C
4687/// property's attributes will cause a conflict.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004688static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregor988358f2009-11-19 00:14:45 +00004689 // Check if we've already added this flag.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004690 if (Attributes & NewFlag)
Douglas Gregor988358f2009-11-19 00:14:45 +00004691 return true;
4692
Bill Wendlingad017fa2012-12-20 19:22:21 +00004693 Attributes |= NewFlag;
Douglas Gregor988358f2009-11-19 00:14:45 +00004694
4695 // Check for collisions with "readonly".
Bill Wendlingad017fa2012-12-20 19:22:21 +00004696 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
4697 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregor988358f2009-11-19 00:14:45 +00004698 return true;
4699
Jordan Rosed7403a72012-08-20 20:01:13 +00004700 // Check for more than one of { assign, copy, retain, strong, weak }.
Bill Wendlingad017fa2012-12-20 19:22:21 +00004701 unsigned AssignCopyRetMask = Attributes & (ObjCDeclSpec::DQ_PR_assign |
John McCallf85e1932011-06-15 23:02:42 +00004702 ObjCDeclSpec::DQ_PR_unsafe_unretained |
Douglas Gregor988358f2009-11-19 00:14:45 +00004703 ObjCDeclSpec::DQ_PR_copy |
Jordan Rosed7403a72012-08-20 20:01:13 +00004704 ObjCDeclSpec::DQ_PR_retain |
4705 ObjCDeclSpec::DQ_PR_strong |
4706 ObjCDeclSpec::DQ_PR_weak);
Douglas Gregor988358f2009-11-19 00:14:45 +00004707 if (AssignCopyRetMask &&
4708 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCallf85e1932011-06-15 23:02:42 +00004709 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregor988358f2009-11-19 00:14:45 +00004710 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCallf85e1932011-06-15 23:02:42 +00004711 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rosed7403a72012-08-20 20:01:13 +00004712 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
4713 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregor988358f2009-11-19 00:14:45 +00004714 return true;
4715
4716 return false;
4717}
4718
Douglas Gregora93b1082009-11-18 23:08:07 +00004719void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroffece8e712009-10-08 21:55:05 +00004720 if (!CodeCompleter)
4721 return;
Douglas Gregord3c68542009-11-19 01:08:35 +00004722
Bill Wendlingad017fa2012-12-20 19:22:21 +00004723 unsigned Attributes = ODS.getPropertyAttributes();
Steve Naroffece8e712009-10-08 21:55:05 +00004724
Douglas Gregor218937c2011-02-01 19:23:04 +00004725 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004726 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004727 CodeCompletionContext::CCC_Other);
Steve Naroffece8e712009-10-08 21:55:05 +00004728 Results.EnterNewScope();
Bill Wendlingad017fa2012-12-20 19:22:21 +00004729 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall0a2c5e22010-08-25 06:19:51 +00004730 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004731 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall0a2c5e22010-08-25 06:19:51 +00004732 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004733 if (!ObjCPropertyFlagConflicts(Attributes,
John McCallf85e1932011-06-15 23:02:42 +00004734 ObjCDeclSpec::DQ_PR_unsafe_unretained))
4735 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004736 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall0a2c5e22010-08-25 06:19:51 +00004737 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004738 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall0a2c5e22010-08-25 06:19:51 +00004739 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004740 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCallf85e1932011-06-15 23:02:42 +00004741 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004742 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall0a2c5e22010-08-25 06:19:51 +00004743 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004744 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall0a2c5e22010-08-25 06:19:51 +00004745 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendlingad017fa2012-12-20 19:22:21 +00004746 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian27f45232011-06-11 17:14:27 +00004747 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rosed7403a72012-08-20 20:01:13 +00004748
4749 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall0a7dd782012-08-21 02:47:43 +00004750 if (getLangOpts().ObjCARCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendlingad017fa2012-12-20 19:22:21 +00004751 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rosed7403a72012-08-20 20:01:13 +00004752 Results.AddResult(CodeCompletionResult("weak"));
4753
Bill Wendlingad017fa2012-12-20 19:22:21 +00004754 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004755 CodeCompletionBuilder Setter(Results.getAllocator(),
4756 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004757 Setter.AddTypedTextChunk("setter");
4758 Setter.AddTextChunk(" = ");
4759 Setter.AddPlaceholderChunk("method");
4760 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004761 }
Bill Wendlingad017fa2012-12-20 19:22:21 +00004762 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004763 CodeCompletionBuilder Getter(Results.getAllocator(),
4764 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00004765 Getter.AddTypedTextChunk("getter");
4766 Getter.AddTextChunk(" = ");
4767 Getter.AddPlaceholderChunk("method");
4768 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor54f01612009-11-19 00:01:57 +00004769 }
Steve Naroffece8e712009-10-08 21:55:05 +00004770 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004771 HandleCodeCompleteResults(this, CodeCompleter,
4772 CodeCompletionContext::CCC_Other,
4773 Results.data(),Results.size());
Steve Naroffece8e712009-10-08 21:55:05 +00004774}
Steve Naroffc4df6d22009-11-07 02:08:14 +00004775
James Dennettde23c7e2012-06-17 05:33:25 +00004776/// \brief Describes the kind of Objective-C method that we want to find
Douglas Gregor4ad96852009-11-19 07:41:15 +00004777/// via code completion.
4778enum ObjCMethodKind {
Dmitri Gribenko49fdccb2012-06-08 23:13:42 +00004779 MK_Any, ///< Any kind of method, provided it means other specified criteria.
4780 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
4781 MK_OneArgSelector ///< One-argument selector.
Douglas Gregor4ad96852009-11-19 07:41:15 +00004782};
4783
Douglas Gregor458433d2010-08-26 15:07:07 +00004784static bool isAcceptableObjCSelector(Selector Sel,
4785 ObjCMethodKind WantKind,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004786 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004787 bool AllowSameLength = true) {
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004788 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor458433d2010-08-26 15:07:07 +00004789 if (NumSelIdents > Sel.getNumArgs())
4790 return false;
4791
4792 switch (WantKind) {
4793 case MK_Any: break;
4794 case MK_ZeroArgSelector: return Sel.isUnarySelector();
4795 case MK_OneArgSelector: return Sel.getNumArgs() == 1;
4796 }
4797
Douglas Gregorcf544262010-11-17 21:36:08 +00004798 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
4799 return false;
4800
Douglas Gregor458433d2010-08-26 15:07:07 +00004801 for (unsigned I = 0; I != NumSelIdents; ++I)
4802 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
4803 return false;
4804
4805 return true;
4806}
4807
Douglas Gregor4ad96852009-11-19 07:41:15 +00004808static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
4809 ObjCMethodKind WantKind,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004810 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004811 bool AllowSameLength = true) {
Douglas Gregor458433d2010-08-26 15:07:07 +00004812 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004813 AllowSameLength);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004814}
Douglas Gregord36adf52010-09-16 16:06:31 +00004815
4816namespace {
4817 /// \brief A set of selectors, which is used to avoid introducing multiple
4818 /// completions with the same selector into the result set.
4819 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
4820}
4821
Douglas Gregor36ecb042009-11-17 23:22:23 +00004822/// \brief Add all of the Objective-C methods in the given Objective-C
4823/// container to the set of results.
4824///
4825/// The container will be a class, protocol, category, or implementation of
4826/// any of the above. This mether will recurse to include methods from
4827/// the superclasses of classes along with their categories, protocols, and
4828/// implementations.
4829///
4830/// \param Container the container in which we'll look to find methods.
4831///
James Dennetta40f7922012-06-14 03:11:41 +00004832/// \param WantInstanceMethods Whether to add instance methods (only); if
4833/// false, this routine will add factory methods (only).
Douglas Gregor36ecb042009-11-17 23:22:23 +00004834///
4835/// \param CurContext the context in which we're performing the lookup that
4836/// finds methods.
4837///
Douglas Gregorcf544262010-11-17 21:36:08 +00004838/// \param AllowSameLength Whether we allow a method to be added to the list
4839/// when it has the same number of parameters as we have selector identifiers.
4840///
Douglas Gregor36ecb042009-11-17 23:22:23 +00004841/// \param Results the structure into which we'll add results.
4842static void AddObjCMethods(ObjCContainerDecl *Container,
4843 bool WantInstanceMethods,
Douglas Gregor4ad96852009-11-19 07:41:15 +00004844 ObjCMethodKind WantKind,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004845 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregor36ecb042009-11-17 23:22:23 +00004846 DeclContext *CurContext,
Douglas Gregord36adf52010-09-16 16:06:31 +00004847 VisitedSelectorSet &Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004848 bool AllowSameLength,
Douglas Gregor408be5a2010-08-25 01:08:01 +00004849 ResultBuilder &Results,
4850 bool InOriginalClass = true) {
John McCall0a2c5e22010-08-25 06:19:51 +00004851 typedef CodeCompletionResult Result;
Douglas Gregorb92a4082012-06-12 13:44:08 +00004852 Container = getContainerDef(Container);
Douglas Gregor5824b802013-01-30 06:58:39 +00004853 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
4854 bool isRootClass = IFace && !IFace->getSuperClass();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004855 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
4856 MEnd = Container->meth_end();
4857 M != MEnd; ++M) {
Douglas Gregor5824b802013-01-30 06:58:39 +00004858 // The instance methods on the root class can be messaged via the
4859 // metaclass.
4860 if (M->isInstanceMethod() == WantInstanceMethods ||
4861 (isRootClass && !WantInstanceMethods)) {
Douglas Gregord3c68542009-11-19 01:08:35 +00004862 // Check whether the selector identifiers we've been given are a
4863 // subset of the identifiers for this particular method.
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004864 if (!isAcceptableObjCMethod(*M, WantKind, SelIdents, AllowSameLength))
Douglas Gregord3c68542009-11-19 01:08:35 +00004865 continue;
Douglas Gregor4ad96852009-11-19 07:41:15 +00004866
David Blaikie262bc182012-04-30 02:36:29 +00004867 if (!Selectors.insert(M->getSelector()))
Douglas Gregord36adf52010-09-16 16:06:31 +00004868 continue;
4869
Douglas Gregord1f09b42013-01-31 04:52:16 +00004870 Result R = Result(*M, Results.getBasePriority(*M), 0);
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004871 R.StartParameter = SelIdents.size();
Douglas Gregor4ad96852009-11-19 07:41:15 +00004872 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor408be5a2010-08-25 01:08:01 +00004873 if (!InOriginalClass)
4874 R.Priority += CCD_InBaseClass;
Douglas Gregord3c68542009-11-19 01:08:35 +00004875 Results.MaybeAddResult(R, CurContext);
4876 }
Douglas Gregor36ecb042009-11-17 23:22:23 +00004877 }
4878
Douglas Gregore396c7b2010-09-16 15:34:59 +00004879 // Visit the protocols of protocols.
4880 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004881 if (Protocol->hasDefinition()) {
4882 const ObjCList<ObjCProtocolDecl> &Protocols
4883 = Protocol->getReferencedProtocols();
4884 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4885 E = Protocols.end();
4886 I != E; ++I)
4887 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004888 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00004889 }
Douglas Gregore396c7b2010-09-16 15:34:59 +00004890 }
4891
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00004892 if (!IFace || !IFace->hasDefinition())
Douglas Gregor36ecb042009-11-17 23:22:23 +00004893 return;
4894
4895 // Add methods in protocols.
Argyrios Kyrtzidisa5f44412012-03-13 01:09:41 +00004896 for (ObjCInterfaceDecl::protocol_iterator I = IFace->protocol_begin(),
4897 E = IFace->protocol_end();
Douglas Gregor36ecb042009-11-17 23:22:23 +00004898 I != E; ++I)
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004899 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00004900 CurContext, Selectors, AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004901
4902 // Add methods in categories.
Douglas Gregord3297242013-01-16 23:00:23 +00004903 for (ObjCInterfaceDecl::known_categories_iterator
4904 Cat = IFace->known_categories_begin(),
4905 CatEnd = IFace->known_categories_end();
4906 Cat != CatEnd; ++Cat) {
4907 ObjCCategoryDecl *CatDecl = *Cat;
4908
4909 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004910 CurContext, Selectors, AllowSameLength,
Douglas Gregorcf544262010-11-17 21:36:08 +00004911 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004912
4913 // Add a categories protocol methods.
4914 const ObjCList<ObjCProtocolDecl> &Protocols
4915 = CatDecl->getReferencedProtocols();
4916 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
4917 E = Protocols.end();
4918 I != E; ++I)
Douglas Gregor4ad96852009-11-19 07:41:15 +00004919 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004920 CurContext, Selectors, AllowSameLength,
Douglas Gregorcf544262010-11-17 21:36:08 +00004921 Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004922
4923 // Add methods in category implementations.
4924 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004925 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004926 CurContext, Selectors, AllowSameLength,
Douglas Gregorcf544262010-11-17 21:36:08 +00004927 Results, InOriginalClass);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004928 }
4929
4930 // Add methods in superclass.
4931 if (IFace->getSuperClass())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004932 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004933 SelIdents, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004934 AllowSameLength, Results, false);
Douglas Gregor36ecb042009-11-17 23:22:23 +00004935
4936 // Add methods in our implementation, if any.
4937 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Douglas Gregor4ad96852009-11-19 07:41:15 +00004938 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004939 CurContext, Selectors, AllowSameLength,
Douglas Gregorcf544262010-11-17 21:36:08 +00004940 Results, InOriginalClass);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004941}
4942
4943
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004944void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004945 // Try to find the interface where getters might live.
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004946 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004947 if (!Class) {
4948 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004949 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004950 Class = Category->getClassInterface();
4951
4952 if (!Class)
4953 return;
4954 }
4955
4956 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004957 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004958 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004959 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004960 Results.EnterNewScope();
4961
Douglas Gregord36adf52010-09-16 16:06:31 +00004962 VisitedSelectorSet Selectors;
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004963 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorcf544262010-11-17 21:36:08 +00004964 /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004965 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004966 HandleCodeCompleteResults(this, CodeCompleter,
4967 CodeCompletionContext::CCC_Other,
4968 Results.data(),Results.size());
Douglas Gregor4ad96852009-11-19 07:41:15 +00004969}
4970
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004971void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregor4ad96852009-11-19 07:41:15 +00004972 // Try to find the interface where setters might live.
4973 ObjCInterfaceDecl *Class
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004974 = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004975 if (!Class) {
4976 if (ObjCCategoryDecl *Category
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00004977 = dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregor4ad96852009-11-19 07:41:15 +00004978 Class = Category->getClassInterface();
4979
4980 if (!Class)
4981 return;
4982 }
4983
4984 // Find all of the potential getters.
Douglas Gregor218937c2011-02-01 19:23:04 +00004985 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00004986 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00004987 CodeCompletionContext::CCC_Other);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004988 Results.EnterNewScope();
4989
Douglas Gregord36adf52010-09-16 16:06:31 +00004990 VisitedSelectorSet Selectors;
Dmitri Gribenko050315b2013-06-16 03:47:57 +00004991 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00004992 Selectors, /*AllowSameLength=*/true, Results);
Douglas Gregor4ad96852009-11-19 07:41:15 +00004993
4994 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00004995 HandleCodeCompleteResults(this, CodeCompleter,
4996 CodeCompletionContext::CCC_Other,
4997 Results.data(),Results.size());
Douglas Gregor36ecb042009-11-17 23:22:23 +00004998}
4999
Douglas Gregorafc45782011-02-15 22:19:42 +00005000void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5001 bool IsParameter) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005002 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005003 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005004 CodeCompletionContext::CCC_Type);
Douglas Gregord32b0222010-08-24 01:06:58 +00005005 Results.EnterNewScope();
5006
5007 // Add context-sensitive, Objective-C parameter-passing keywords.
5008 bool AddedInOut = false;
5009 if ((DS.getObjCDeclQualifier() &
5010 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5011 Results.AddResult("in");
5012 Results.AddResult("inout");
5013 AddedInOut = true;
5014 }
5015 if ((DS.getObjCDeclQualifier() &
5016 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5017 Results.AddResult("out");
5018 if (!AddedInOut)
5019 Results.AddResult("inout");
5020 }
5021 if ((DS.getObjCDeclQualifier() &
5022 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5023 ObjCDeclSpec::DQ_Oneway)) == 0) {
5024 Results.AddResult("bycopy");
5025 Results.AddResult("byref");
5026 Results.AddResult("oneway");
5027 }
5028
Douglas Gregorafc45782011-02-15 22:19:42 +00005029 // If we're completing the return type of an Objective-C method and the
5030 // identifier IBAction refers to a macro, provide a completion item for
5031 // an action, e.g.,
5032 // IBAction)<#selector#>:(id)sender
5033 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
5034 Context.Idents.get("IBAction").hasMacroDefinition()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005035 CodeCompletionBuilder Builder(Results.getAllocator(),
5036 Results.getCodeCompletionTUInfo(),
5037 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorafc45782011-02-15 22:19:42 +00005038 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00005039 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00005040 Builder.AddPlaceholderChunk("selector");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00005041 Builder.AddChunk(CodeCompletionString::CK_Colon);
5042 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00005043 Builder.AddTextChunk("id");
Benjamin Kramer1eb18af2012-03-26 16:57:36 +00005044 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorafc45782011-02-15 22:19:42 +00005045 Builder.AddTextChunk("sender");
5046 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5047 }
Douglas Gregor31aa5772013-01-30 07:11:43 +00005048
5049 // If we're completing the return type, provide 'instancetype'.
5050 if (!IsParameter) {
5051 Results.AddResult(CodeCompletionResult("instancetype"));
5052 }
Douglas Gregorafc45782011-02-15 22:19:42 +00005053
Douglas Gregord32b0222010-08-24 01:06:58 +00005054 // Add various builtin type names and specifiers.
5055 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5056 Results.ExitScope();
5057
5058 // Add the various type names
5059 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5060 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5061 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5062 CodeCompleter->includeGlobals());
5063
5064 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00005065 AddMacroResults(PP, Results, false);
Douglas Gregord32b0222010-08-24 01:06:58 +00005066
5067 HandleCodeCompleteResults(this, CodeCompleter,
5068 CodeCompletionContext::CCC_Type,
5069 Results.data(), Results.size());
5070}
5071
Douglas Gregor22f56992010-04-06 19:22:33 +00005072/// \brief When we have an expression with type "id", we may assume
5073/// that it has some more-specific class type based on knowledge of
5074/// common uses of Objective-C. This routine returns that class type,
5075/// or NULL if no better result could be determined.
5076static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Douglas Gregor78edf512010-09-15 16:23:04 +00005077 ObjCMessageExpr *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor22f56992010-04-06 19:22:33 +00005078 if (!Msg)
5079 return 0;
5080
5081 Selector Sel = Msg->getSelector();
5082 if (Sel.isNull())
5083 return 0;
5084
5085 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5086 if (!Id)
5087 return 0;
5088
5089 ObjCMethodDecl *Method = Msg->getMethodDecl();
5090 if (!Method)
5091 return 0;
5092
5093 // Determine the class that we're sending the message to.
Douglas Gregor04badcf2010-04-21 00:45:42 +00005094 ObjCInterfaceDecl *IFace = 0;
5095 switch (Msg->getReceiverKind()) {
5096 case ObjCMessageExpr::Class:
John McCallc12c5bb2010-05-15 11:32:37 +00005097 if (const ObjCObjectType *ObjType
5098 = Msg->getClassReceiver()->getAs<ObjCObjectType>())
5099 IFace = ObjType->getInterface();
Douglas Gregor04badcf2010-04-21 00:45:42 +00005100 break;
5101
5102 case ObjCMessageExpr::Instance: {
5103 QualType T = Msg->getInstanceReceiver()->getType();
5104 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5105 IFace = Ptr->getInterfaceDecl();
5106 break;
5107 }
5108
5109 case ObjCMessageExpr::SuperInstance:
5110 case ObjCMessageExpr::SuperClass:
5111 break;
Douglas Gregor22f56992010-04-06 19:22:33 +00005112 }
5113
5114 if (!IFace)
5115 return 0;
5116
5117 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5118 if (Method->isInstanceMethod())
5119 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5120 .Case("retain", IFace)
John McCallf85e1932011-06-15 23:02:42 +00005121 .Case("strong", IFace)
Douglas Gregor22f56992010-04-06 19:22:33 +00005122 .Case("autorelease", IFace)
5123 .Case("copy", IFace)
5124 .Case("copyWithZone", IFace)
5125 .Case("mutableCopy", IFace)
5126 .Case("mutableCopyWithZone", IFace)
5127 .Case("awakeFromCoder", IFace)
5128 .Case("replacementObjectFromCoder", IFace)
5129 .Case("class", IFace)
5130 .Case("classForCoder", IFace)
5131 .Case("superclass", Super)
5132 .Default(0);
5133
5134 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
5135 .Case("new", IFace)
5136 .Case("alloc", IFace)
5137 .Case("allocWithZone", IFace)
5138 .Case("class", IFace)
5139 .Case("superclass", Super)
5140 .Default(0);
5141}
5142
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005143// Add a special completion for a message send to "super", which fills in the
5144// most likely case of forwarding all of our arguments to the superclass
5145// function.
5146///
5147/// \param S The semantic analysis object.
5148///
Dmitri Gribenko70517ca2012-08-23 17:58:28 +00005149/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005150/// the "super" keyword. Otherwise, we just need to provide the arguments.
5151///
5152/// \param SelIdents The identifiers in the selector that have already been
5153/// provided as arguments for a send to "super".
5154///
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005155/// \param Results The set of results to augment.
5156///
5157/// \returns the Objective-C method declaration that would be invoked by
5158/// this "super" completion. If NULL, no completion was added.
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005159static ObjCMethodDecl *AddSuperSendCompletion(
5160 Sema &S, bool NeedSuperKeyword,
5161 ArrayRef<IdentifierInfo *> SelIdents,
5162 ResultBuilder &Results) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005163 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
5164 if (!CurMethod)
5165 return 0;
5166
5167 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
5168 if (!Class)
5169 return 0;
5170
5171 // Try to find a superclass method with the same selector.
5172 ObjCMethodDecl *SuperMethod = 0;
Douglas Gregor78bcd912011-02-16 00:51:18 +00005173 while ((Class = Class->getSuperClass()) && !SuperMethod) {
5174 // Check in the class
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005175 SuperMethod = Class->getMethod(CurMethod->getSelector(),
5176 CurMethod->isInstanceMethod());
5177
Douglas Gregor78bcd912011-02-16 00:51:18 +00005178 // Check in categories or class extensions.
5179 if (!SuperMethod) {
Douglas Gregord3297242013-01-16 23:00:23 +00005180 for (ObjCInterfaceDecl::known_categories_iterator
5181 Cat = Class->known_categories_begin(),
5182 CatEnd = Class->known_categories_end();
5183 Cat != CatEnd; ++Cat) {
5184 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Douglas Gregor78bcd912011-02-16 00:51:18 +00005185 CurMethod->isInstanceMethod())))
5186 break;
Douglas Gregord3297242013-01-16 23:00:23 +00005187 }
Douglas Gregor78bcd912011-02-16 00:51:18 +00005188 }
5189 }
5190
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005191 if (!SuperMethod)
5192 return 0;
5193
5194 // Check whether the superclass method has the same signature.
5195 if (CurMethod->param_size() != SuperMethod->param_size() ||
5196 CurMethod->isVariadic() != SuperMethod->isVariadic())
5197 return 0;
5198
5199 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
5200 CurPEnd = CurMethod->param_end(),
5201 SuperP = SuperMethod->param_begin();
5202 CurP != CurPEnd; ++CurP, ++SuperP) {
5203 // Make sure the parameter types are compatible.
5204 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
5205 (*SuperP)->getType()))
5206 return 0;
5207
5208 // Make sure we have a parameter name to forward!
5209 if (!(*CurP)->getIdentifier())
5210 return 0;
5211 }
5212
5213 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005214 CodeCompletionBuilder Builder(Results.getAllocator(),
5215 Results.getCodeCompletionTUInfo());
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005216
5217 // Give this completion a return type.
Douglas Gregor8987b232011-09-27 23:30:47 +00005218 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
5219 Builder);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005220
5221 // If we need the "super" keyword, add it (plus some spacing).
5222 if (NeedSuperKeyword) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005223 Builder.AddTypedTextChunk("super");
5224 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005225 }
5226
5227 Selector Sel = CurMethod->getSelector();
5228 if (Sel.isUnarySelector()) {
5229 if (NeedSuperKeyword)
Douglas Gregordae68752011-02-01 22:57:45 +00005230 Builder.AddTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005231 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005232 else
Douglas Gregordae68752011-02-01 22:57:45 +00005233 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005234 Sel.getNameForSlot(0)));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005235 } else {
5236 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
5237 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005238 if (I > SelIdents.size())
Douglas Gregor218937c2011-02-01 19:23:04 +00005239 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005240
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005241 if (I < SelIdents.size())
Douglas Gregor218937c2011-02-01 19:23:04 +00005242 Builder.AddInformativeChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005243 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005244 Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005245 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005246 Builder.AddTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005247 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005248 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005249 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005250 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005251 } else {
Douglas Gregor218937c2011-02-01 19:23:04 +00005252 Builder.AddTypedTextChunk(
Douglas Gregordae68752011-02-01 22:57:45 +00005253 Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005254 Sel.getNameForSlot(I) + ":"));
Douglas Gregordae68752011-02-01 22:57:45 +00005255 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005256 (*CurP)->getIdentifier()->getName()));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005257 }
5258 }
5259 }
5260
Douglas Gregorba103062012-03-27 23:34:16 +00005261 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
5262 CCP_SuperCompletion));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005263 return SuperMethod;
5264}
5265
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005266void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall0a2c5e22010-08-25 06:19:51 +00005267 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00005268 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005269 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005270 CodeCompletionContext::CCC_ObjCMessageReceiver,
Richard Smith80ad52f2013-01-02 11:42:31 +00005271 getLangOpts().CPlusPlus11
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005272 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
5273 : &ResultBuilder::IsObjCMessageReceiver);
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005274
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005275 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5276 Results.EnterNewScope();
Douglas Gregor8071e422010-08-15 06:18:01 +00005277 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
5278 CodeCompleter->includeGlobals());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005279
5280 // If we are in an Objective-C method inside a class that has a superclass,
5281 // add "super" as an option.
5282 if (ObjCMethodDecl *Method = getCurMethodDecl())
5283 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005284 if (Iface->getSuperClass()) {
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005285 Results.AddResult(Result("super"));
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005286
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005287 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005288 }
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005289
Richard Smith80ad52f2013-01-02 11:42:31 +00005290 if (getLangOpts().CPlusPlus11)
Douglas Gregor81f3bff2012-02-15 15:34:24 +00005291 addThisCompletion(*this, Results);
5292
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005293 Results.ExitScope();
5294
5295 if (CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00005296 AddMacroResults(PP, Results, false);
Douglas Gregorcee9ff12010-09-20 22:39:41 +00005297 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005298 Results.data(), Results.size());
Douglas Gregor8e254cf2010-05-27 23:06:34 +00005299
5300}
5301
Douglas Gregor2725ca82010-04-21 19:57:20 +00005302void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005303 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005304 bool AtArgumentExpression) {
Douglas Gregor2725ca82010-04-21 19:57:20 +00005305 ObjCInterfaceDecl *CDecl = 0;
5306 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5307 // Figure out which interface we're in.
5308 CDecl = CurMethod->getClassInterface();
5309 if (!CDecl)
5310 return;
5311
5312 // Find the superclass of this class.
5313 CDecl = CDecl->getSuperClass();
5314 if (!CDecl)
5315 return;
5316
5317 if (CurMethod->isInstanceMethod()) {
5318 // We are inside an instance method, which means that the message
5319 // send [super ...] is actually calling an instance method on the
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005320 // current object.
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005321 return CodeCompleteObjCInstanceMessage(S, 0, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005322 AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005323 CDecl);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005324 }
5325
5326 // Fall through to send to the superclass in CDecl.
5327 } else {
5328 // "super" may be the name of a type or variable. Figure out which
5329 // it is.
Argyrios Kyrtzidis57f8da52013-03-14 22:56:43 +00005330 IdentifierInfo *Super = getSuperIdentifier();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005331 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc,
5332 LookupOrdinaryName);
5333 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
5334 // "super" names an interface. Use it.
5335 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
John McCallc12c5bb2010-05-15 11:32:37 +00005336 if (const ObjCObjectType *Iface
5337 = Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
5338 CDecl = Iface->getInterface();
Douglas Gregor2725ca82010-04-21 19:57:20 +00005339 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
5340 // "super" names an unresolved type; we can't be more specific.
5341 } else {
5342 // Assume that "super" names some kind of value and parse that way.
5343 CXXScopeSpec SS;
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005344 SourceLocation TemplateKWLoc;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005345 UnqualifiedId id;
5346 id.setIdentifier(Super, SuperLoc);
Abramo Bagnarae4b92762012-01-27 09:46:47 +00005347 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id,
5348 false, false);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005349 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005350 SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005351 AtArgumentExpression);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005352 }
5353
5354 // Fall through
5355 }
5356
John McCallb3d87482010-08-24 05:47:05 +00005357 ParsedType Receiver;
Douglas Gregor2725ca82010-04-21 19:57:20 +00005358 if (CDecl)
John McCallb3d87482010-08-24 05:47:05 +00005359 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Douglas Gregor2725ca82010-04-21 19:57:20 +00005360 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005361 AtArgumentExpression,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005362 /*IsSuper=*/true);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005363}
5364
Douglas Gregorb9d77572010-09-21 00:03:25 +00005365/// \brief Given a set of code-completion results for the argument of a message
5366/// send, determine the preferred type (if any) for that argument expression.
5367static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
5368 unsigned NumSelIdents) {
5369 typedef CodeCompletionResult Result;
5370 ASTContext &Context = Results.getSema().Context;
5371
5372 QualType PreferredType;
5373 unsigned BestPriority = CCP_Unlikely * 2;
5374 Result *ResultsData = Results.data();
5375 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
5376 Result &R = ResultsData[I];
5377 if (R.Kind == Result::RK_Declaration &&
5378 isa<ObjCMethodDecl>(R.Declaration)) {
5379 if (R.Priority <= BestPriority) {
Dmitri Gribenko89cf4252013-01-23 17:21:11 +00005380 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005381 if (NumSelIdents <= Method->param_size()) {
5382 QualType MyPreferredType = Method->param_begin()[NumSelIdents - 1]
5383 ->getType();
5384 if (R.Priority < BestPriority || PreferredType.isNull()) {
5385 BestPriority = R.Priority;
5386 PreferredType = MyPreferredType;
5387 } else if (!Context.hasSameUnqualifiedType(PreferredType,
5388 MyPreferredType)) {
5389 PreferredType = QualType();
5390 }
5391 }
5392 }
5393 }
5394 }
5395
5396 return PreferredType;
5397}
5398
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005399static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
5400 ParsedType Receiver,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005401 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005402 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005403 bool IsSuper,
5404 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005405 typedef CodeCompletionResult Result;
Douglas Gregor24a069f2009-11-17 17:59:40 +00005406 ObjCInterfaceDecl *CDecl = 0;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005407
Douglas Gregor24a069f2009-11-17 17:59:40 +00005408 // If the given name refers to an interface type, retrieve the
5409 // corresponding declaration.
Douglas Gregor2725ca82010-04-21 19:57:20 +00005410 if (Receiver) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005411 QualType T = SemaRef.GetTypeFromParser(Receiver, 0);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005412 if (!T.isNull())
John McCallc12c5bb2010-05-15 11:32:37 +00005413 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
5414 CDecl = Interface->getInterface();
Douglas Gregor24a069f2009-11-17 17:59:40 +00005415 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005416
Douglas Gregor36ecb042009-11-17 23:22:23 +00005417 // Add all of the factory methods in this Objective-C class, its protocols,
5418 // superclasses, categories, implementation, etc.
Steve Naroffc4df6d22009-11-07 02:08:14 +00005419 Results.EnterNewScope();
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005420
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005421 // If this is a send-to-super, try to add the special "super" send
5422 // completion.
5423 if (IsSuper) {
5424 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005425 = AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005426 Results.Ignore(SuperMethod);
5427 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005428
Douglas Gregor265f7492010-08-27 15:29:55 +00005429 // If we're inside an Objective-C method definition, prefer its selector to
5430 // others.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005431 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregor265f7492010-08-27 15:29:55 +00005432 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005433
Douglas Gregord36adf52010-09-16 16:06:31 +00005434 VisitedSelectorSet Selectors;
Douglas Gregor13438f92010-04-06 16:40:00 +00005435 if (CDecl)
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005436 AddObjCMethods(CDecl, false, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005437 SemaRef.CurContext, Selectors, AtArgumentExpression,
5438 Results);
Douglas Gregor2725ca82010-04-21 19:57:20 +00005439 else {
Douglas Gregor13438f92010-04-06 16:40:00 +00005440 // We're messaging "id" as a type; provide all class/factory methods.
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005441
Douglas Gregor719770d2010-04-06 17:30:22 +00005442 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005443 // pool from the AST file.
Axel Naumann0ec56b72012-10-18 19:05:02 +00005444 if (SemaRef.getExternalSource()) {
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005445 for (uint32_t I = 0,
Axel Naumann0ec56b72012-10-18 19:05:02 +00005446 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall76bd1f32010-06-01 09:23:16 +00005447 I != N; ++I) {
Axel Naumann0ec56b72012-10-18 19:05:02 +00005448 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005449 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005450 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005451
5452 SemaRef.ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005453 }
5454 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005455
5456 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
5457 MEnd = SemaRef.MethodPool.end();
Sebastian Redldb9d2142010-08-02 23:18:59 +00005458 M != MEnd; ++M) {
5459 for (ObjCMethodList *MethList = &M->second.second;
5460 MethList && MethList->Method;
Argyrios Kyrtzidis2e3d8c02013-04-17 00:08:58 +00005461 MethList = MethList->getNext()) {
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005462 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
Douglas Gregor13438f92010-04-06 16:40:00 +00005463 continue;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005464
Douglas Gregord1f09b42013-01-31 04:52:16 +00005465 Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005466 R.StartParameter = SelIdents.size();
Douglas Gregor13438f92010-04-06 16:40:00 +00005467 R.AllParametersAreInformative = false;
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005468 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor13438f92010-04-06 16:40:00 +00005469 }
5470 }
5471 }
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005472
5473 Results.ExitScope();
5474}
Douglas Gregor13438f92010-04-06 16:40:00 +00005475
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005476void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005477 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005478 bool AtArgumentExpression,
Douglas Gregorc7b6d882010-09-16 15:14:18 +00005479 bool IsSuper) {
Douglas Gregore081a612011-07-21 01:05:26 +00005480
5481 QualType T = this->GetTypeFromParser(Receiver);
5482
Douglas Gregor218937c2011-02-01 19:23:04 +00005483 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005484 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005485 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005486 T, SelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005487
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005488 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005489 AtArgumentExpression, IsSuper, Results);
Douglas Gregorb9d77572010-09-21 00:03:25 +00005490
5491 // If we're actually at the argument expression (rather than prior to the
5492 // selector), we're actually performing code completion for an expression.
5493 // Determine whether we have a single, best method. If so, we can
5494 // code-complete the expression using the corresponding parameter type as
5495 // our preferred type, improving completion results.
5496 if (AtArgumentExpression) {
5497 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005498 SelIdents.size());
Douglas Gregorb9d77572010-09-21 00:03:25 +00005499 if (PreferredType.isNull())
5500 CodeCompleteOrdinaryName(S, PCC_Expression);
5501 else
5502 CodeCompleteExpression(S, PreferredType);
5503 return;
5504 }
5505
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005506 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005507 Results.getCompletionContext(),
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005508 Results.data(), Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005509}
5510
Richard Trieuf81e5a92011-09-09 02:00:50 +00005511void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005512 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregor70c5ac72010-09-20 23:34:21 +00005513 bool AtArgumentExpression,
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005514 ObjCInterfaceDecl *Super) {
John McCall0a2c5e22010-08-25 06:19:51 +00005515 typedef CodeCompletionResult Result;
Steve Naroffc4df6d22009-11-07 02:08:14 +00005516
5517 Expr *RecExpr = static_cast<Expr *>(Receiver);
Steve Naroffc4df6d22009-11-07 02:08:14 +00005518
Douglas Gregor36ecb042009-11-17 23:22:23 +00005519 // If necessary, apply function/array conversion to the receiver.
5520 // C99 6.7.5.3p[7,8].
John Wiegley429bb272011-04-08 18:41:53 +00005521 if (RecExpr) {
5522 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
5523 if (Conv.isInvalid()) // conversion failed. bail.
5524 return;
5525 RecExpr = Conv.take();
5526 }
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005527 QualType ReceiverType = RecExpr? RecExpr->getType()
5528 : Super? Context.getObjCObjectPointerType(
5529 Context.getObjCInterfaceType(Super))
5530 : Context.getObjCIdType();
Steve Naroffc4df6d22009-11-07 02:08:14 +00005531
Douglas Gregorda892642010-11-08 21:12:30 +00005532 // If we're messaging an expression with type "id" or "Class", check
5533 // whether we know something special about the receiver that allows
5534 // us to assume a more-specific receiver type.
5535 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType())
5536 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
5537 if (ReceiverType->isObjCClassType())
5538 return CodeCompleteObjCClassMessage(S,
5539 ParsedType::make(Context.getObjCInterfaceType(IFace)),
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005540 SelIdents,
Douglas Gregorda892642010-11-08 21:12:30 +00005541 AtArgumentExpression, Super);
5542
5543 ReceiverType = Context.getObjCObjectPointerType(
5544 Context.getObjCInterfaceType(IFace));
5545 }
5546
Douglas Gregor36ecb042009-11-17 23:22:23 +00005547 // Build the set of methods we can see.
Douglas Gregor218937c2011-02-01 19:23:04 +00005548 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005549 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregore081a612011-07-21 01:05:26 +00005550 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005551 ReceiverType, SelIdents));
Douglas Gregore081a612011-07-21 01:05:26 +00005552
Douglas Gregor36ecb042009-11-17 23:22:23 +00005553 Results.EnterNewScope();
Douglas Gregor22f56992010-04-06 19:22:33 +00005554
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005555 // If this is a send-to-super, try to add the special "super" send
5556 // completion.
Douglas Gregor6b0656a2010-10-13 21:24:53 +00005557 if (Super) {
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005558 if (ObjCMethodDecl *SuperMethod
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005559 = AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor03d8aec2010-08-27 15:10:57 +00005560 Results.Ignore(SuperMethod);
5561 }
5562
Douglas Gregor265f7492010-08-27 15:29:55 +00005563 // If we're inside an Objective-C method definition, prefer its selector to
5564 // others.
5565 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
5566 Results.setPreferredSelector(CurMethod->getSelector());
Douglas Gregor36ecb042009-11-17 23:22:23 +00005567
Douglas Gregord36adf52010-09-16 16:06:31 +00005568 // Keep track of the selectors we've already added.
5569 VisitedSelectorSet Selectors;
5570
Douglas Gregorf74a4192009-11-18 00:06:18 +00005571 // Handle messages to Class. This really isn't a message to an instance
5572 // method, so we treat it the same way we would treat a message send to a
5573 // class method.
5574 if (ReceiverType->isObjCClassType() ||
5575 ReceiverType->isObjCQualifiedClassType()) {
5576 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
5577 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005578 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents,
Douglas Gregorcf544262010-11-17 21:36:08 +00005579 CurContext, Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005580 }
5581 }
5582 // Handle messages to a qualified ID ("id<foo>").
5583 else if (const ObjCObjectPointerType *QualID
5584 = ReceiverType->getAsObjCQualifiedIdType()) {
5585 // Search protocols for instance methods.
5586 for (ObjCObjectPointerType::qual_iterator I = QualID->qual_begin(),
5587 E = QualID->qual_end();
5588 I != E; ++I)
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005589 AddObjCMethods(*I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005590 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005591 }
5592 // Handle messages to a pointer to interface type.
5593 else if (const ObjCObjectPointerType *IFacePtr
5594 = ReceiverType->getAsObjCInterfacePointerType()) {
5595 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregor4ad96852009-11-19 07:41:15 +00005596 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005597 CurContext, Selectors, AtArgumentExpression,
Douglas Gregorcf544262010-11-17 21:36:08 +00005598 Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005599
5600 // Search protocols for instance methods.
5601 for (ObjCObjectPointerType::qual_iterator I = IFacePtr->qual_begin(),
5602 E = IFacePtr->qual_end();
5603 I != E; ++I)
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005604 AddObjCMethods(*I, true, MK_Any, SelIdents, CurContext,
Douglas Gregorcf544262010-11-17 21:36:08 +00005605 Selectors, AtArgumentExpression, Results);
Douglas Gregorf74a4192009-11-18 00:06:18 +00005606 }
Douglas Gregor13438f92010-04-06 16:40:00 +00005607 // Handle messages to "id".
5608 else if (ReceiverType->isObjCIdType()) {
Douglas Gregor719770d2010-04-06 17:30:22 +00005609 // We're messaging "id", so provide all instance methods we know
5610 // about as code-completion results.
5611
5612 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00005613 // pool from the AST file.
Douglas Gregor719770d2010-04-06 17:30:22 +00005614 if (ExternalSource) {
John McCall76bd1f32010-06-01 09:23:16 +00005615 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5616 I != N; ++I) {
5617 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00005618 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor719770d2010-04-06 17:30:22 +00005619 continue;
5620
Sebastian Redldb9d2142010-08-02 23:18:59 +00005621 ReadMethodPool(Sel);
Douglas Gregor719770d2010-04-06 17:30:22 +00005622 }
5623 }
5624
Sebastian Redldb9d2142010-08-02 23:18:59 +00005625 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5626 MEnd = MethodPool.end();
5627 M != MEnd; ++M) {
5628 for (ObjCMethodList *MethList = &M->second.first;
5629 MethList && MethList->Method;
Argyrios Kyrtzidis2e3d8c02013-04-17 00:08:58 +00005630 MethList = MethList->getNext()) {
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005631 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
Douglas Gregor13438f92010-04-06 16:40:00 +00005632 continue;
Douglas Gregord36adf52010-09-16 16:06:31 +00005633
5634 if (!Selectors.insert(MethList->Method->getSelector()))
5635 continue;
5636
Douglas Gregord1f09b42013-01-31 04:52:16 +00005637 Result R(MethList->Method, Results.getBasePriority(MethList->Method),0);
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005638 R.StartParameter = SelIdents.size();
Douglas Gregor13438f92010-04-06 16:40:00 +00005639 R.AllParametersAreInformative = false;
5640 Results.MaybeAddResult(R, CurContext);
5641 }
5642 }
5643 }
Steve Naroffc4df6d22009-11-07 02:08:14 +00005644 Results.ExitScope();
Douglas Gregorb9d77572010-09-21 00:03:25 +00005645
5646
5647 // If we're actually at the argument expression (rather than prior to the
5648 // selector), we're actually performing code completion for an expression.
5649 // Determine whether we have a single, best method. If so, we can
5650 // code-complete the expression using the corresponding parameter type as
5651 // our preferred type, improving completion results.
5652 if (AtArgumentExpression) {
5653 QualType PreferredType = getPreferredArgumentTypeForMessageSend(Results,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005654 SelIdents.size());
Douglas Gregorb9d77572010-09-21 00:03:25 +00005655 if (PreferredType.isNull())
5656 CodeCompleteOrdinaryName(S, PCC_Expression);
5657 else
5658 CodeCompleteExpression(S, PreferredType);
5659 return;
5660 }
5661
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005662 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregore081a612011-07-21 01:05:26 +00005663 Results.getCompletionContext(),
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005664 Results.data(),Results.size());
Steve Naroffc4df6d22009-11-07 02:08:14 +00005665}
Douglas Gregor55385fe2009-11-18 04:19:12 +00005666
Douglas Gregorfb629412010-08-23 21:17:50 +00005667void Sema::CodeCompleteObjCForCollection(Scope *S,
5668 DeclGroupPtrTy IterationVar) {
5669 CodeCompleteExpressionData Data;
5670 Data.ObjCCollection = true;
5671
5672 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov18062392013-08-27 13:15:56 +00005673 DeclGroupRef DG = IterationVar.get();
Douglas Gregorfb629412010-08-23 21:17:50 +00005674 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
5675 if (*I)
5676 Data.IgnoreDecls.push_back(*I);
5677 }
5678 }
5679
5680 CodeCompleteExpression(S, Data);
5681}
5682
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005683void Sema::CodeCompleteObjCSelector(Scope *S,
5684 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor458433d2010-08-26 15:07:07 +00005685 // If we have an external source, load the entire class method
5686 // pool from the AST file.
5687 if (ExternalSource) {
5688 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
5689 I != N; ++I) {
5690 Selector Sel = ExternalSource->GetExternalSelector(I);
5691 if (Sel.isNull() || MethodPool.count(Sel))
5692 continue;
5693
5694 ReadMethodPool(Sel);
5695 }
5696 }
5697
Douglas Gregor218937c2011-02-01 19:23:04 +00005698 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005699 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005700 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor458433d2010-08-26 15:07:07 +00005701 Results.EnterNewScope();
5702 for (GlobalMethodPool::iterator M = MethodPool.begin(),
5703 MEnd = MethodPool.end();
5704 M != MEnd; ++M) {
5705
5706 Selector Sel = M->first;
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005707 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor458433d2010-08-26 15:07:07 +00005708 continue;
5709
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005710 CodeCompletionBuilder Builder(Results.getAllocator(),
5711 Results.getCodeCompletionTUInfo());
Douglas Gregor458433d2010-08-26 15:07:07 +00005712 if (Sel.isUnarySelector()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005713 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00005714 Sel.getNameForSlot(0)));
Douglas Gregor218937c2011-02-01 19:23:04 +00005715 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005716 continue;
5717 }
5718
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005719 std::string Accumulator;
Douglas Gregor458433d2010-08-26 15:07:07 +00005720 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko050315b2013-06-16 03:47:57 +00005721 if (I == SelIdents.size()) {
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005722 if (!Accumulator.empty()) {
Douglas Gregordae68752011-02-01 22:57:45 +00005723 Builder.AddInformativeChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00005724 Accumulator));
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005725 Accumulator.clear();
5726 }
5727 }
5728
Benjamin Kramera0651c52011-07-26 16:59:25 +00005729 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor2d9e21f2010-08-26 16:46:39 +00005730 Accumulator += ':';
Douglas Gregor458433d2010-08-26 15:07:07 +00005731 }
Douglas Gregordae68752011-02-01 22:57:45 +00005732 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( Accumulator));
Douglas Gregor218937c2011-02-01 19:23:04 +00005733 Results.AddResult(Builder.TakeString());
Douglas Gregor458433d2010-08-26 15:07:07 +00005734 }
5735 Results.ExitScope();
5736
5737 HandleCodeCompleteResults(this, CodeCompleter,
5738 CodeCompletionContext::CCC_SelectorName,
5739 Results.data(), Results.size());
5740}
5741
Douglas Gregor55385fe2009-11-18 04:19:12 +00005742/// \brief Add all of the protocol declarations that we find in the given
5743/// (translation unit) context.
5744static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor083128f2009-11-18 04:49:41 +00005745 bool OnlyForwardDeclarations,
Douglas Gregor55385fe2009-11-18 04:19:12 +00005746 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005747 typedef CodeCompletionResult Result;
Douglas Gregor55385fe2009-11-18 04:19:12 +00005748
5749 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5750 DEnd = Ctx->decls_end();
5751 D != DEnd; ++D) {
5752 // Record any protocols we find.
5753 if (ObjCProtocolDecl *Proto = dyn_cast<ObjCProtocolDecl>(*D))
Douglas Gregor5e2a1ff2012-01-01 19:29:29 +00005754 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Douglas Gregord1f09b42013-01-31 04:52:16 +00005755 Results.AddResult(Result(Proto, Results.getBasePriority(Proto), 0),
5756 CurContext, 0, false);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005757 }
5758}
5759
5760void Sema::CodeCompleteObjCProtocolReferences(IdentifierLocPair *Protocols,
5761 unsigned NumProtocols) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005762 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005763 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005764 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005765
Douglas Gregor70c23352010-12-09 21:44:02 +00005766 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5767 Results.EnterNewScope();
5768
5769 // Tell the result set to ignore all of the protocols we have
5770 // already seen.
5771 // FIXME: This doesn't work when caching code-completion results.
5772 for (unsigned I = 0; I != NumProtocols; ++I)
5773 if (ObjCProtocolDecl *Protocol = LookupProtocol(Protocols[I].first,
5774 Protocols[I].second))
5775 Results.Ignore(Protocol);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005776
Douglas Gregor70c23352010-12-09 21:44:02 +00005777 // Add all protocols.
5778 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
5779 Results);
Douglas Gregor083128f2009-11-18 04:49:41 +00005780
Douglas Gregor70c23352010-12-09 21:44:02 +00005781 Results.ExitScope();
5782 }
5783
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005784 HandleCodeCompleteResults(this, CodeCompleter,
5785 CodeCompletionContext::CCC_ObjCProtocolName,
5786 Results.data(),Results.size());
Douglas Gregor083128f2009-11-18 04:49:41 +00005787}
5788
5789void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005790 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005791 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005792 CodeCompletionContext::CCC_ObjCProtocolName);
Douglas Gregor083128f2009-11-18 04:49:41 +00005793
Douglas Gregor70c23352010-12-09 21:44:02 +00005794 if (CodeCompleter && CodeCompleter->includeGlobals()) {
5795 Results.EnterNewScope();
5796
5797 // Add all protocols.
5798 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
5799 Results);
Douglas Gregor55385fe2009-11-18 04:19:12 +00005800
Douglas Gregor70c23352010-12-09 21:44:02 +00005801 Results.ExitScope();
5802 }
5803
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005804 HandleCodeCompleteResults(this, CodeCompleter,
5805 CodeCompletionContext::CCC_ObjCProtocolName,
5806 Results.data(),Results.size());
Douglas Gregor55385fe2009-11-18 04:19:12 +00005807}
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005808
5809/// \brief Add all of the Objective-C interface declarations that we find in
5810/// the given (translation unit) context.
5811static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
5812 bool OnlyForwardDeclarations,
5813 bool OnlyUnimplemented,
5814 ResultBuilder &Results) {
John McCall0a2c5e22010-08-25 06:19:51 +00005815 typedef CodeCompletionResult Result;
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005816
5817 for (DeclContext::decl_iterator D = Ctx->decls_begin(),
5818 DEnd = Ctx->decls_end();
5819 D != DEnd; ++D) {
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005820 // Record any interfaces we find.
5821 if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(*D))
Douglas Gregor7723fec2011-12-15 20:29:51 +00005822 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregordeacbdc2010-08-11 12:19:30 +00005823 (!OnlyUnimplemented || !Class->getImplementation()))
Douglas Gregord1f09b42013-01-31 04:52:16 +00005824 Results.AddResult(Result(Class, Results.getBasePriority(Class), 0),
5825 CurContext, 0, false);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005826 }
5827}
5828
5829void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005830 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005831 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005832 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005833 Results.EnterNewScope();
5834
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005835 if (CodeCompleter->includeGlobals()) {
5836 // Add all classes.
5837 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5838 false, Results);
5839 }
5840
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005841 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005842
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005843 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005844 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005845 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005846}
5847
Douglas Gregorc83c6872010-04-15 22:33:43 +00005848void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
5849 SourceLocation ClassNameLoc) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005850 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005851 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005852 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005853 Results.EnterNewScope();
5854
5855 // Make sure that we ignore the class we're currently defining.
5856 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005857 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005858 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005859 Results.Ignore(CurClass);
5860
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005861 if (CodeCompleter->includeGlobals()) {
5862 // Add all classes.
5863 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5864 false, Results);
5865 }
5866
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005867 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005868
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005869 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005870 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005871 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005872}
5873
5874void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005875 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005876 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005877 CodeCompletionContext::CCC_Other);
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005878 Results.EnterNewScope();
5879
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005880 if (CodeCompleter->includeGlobals()) {
5881 // Add all unimplemented classes.
5882 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
5883 true, Results);
5884 }
5885
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005886 Results.ExitScope();
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005887
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005888 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor0f91c8c2011-07-30 06:55:39 +00005889 CodeCompletionContext::CCC_ObjCInterfaceName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005890 Results.data(),Results.size());
Douglas Gregor3b49aca2009-11-18 16:26:39 +00005891}
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005892
5893void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005894 IdentifierInfo *ClassName,
5895 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005896 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005897
Douglas Gregor218937c2011-02-01 19:23:04 +00005898 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005899 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005900 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005901
5902 // Ignore any categories we find that have already been implemented by this
5903 // interface.
5904 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5905 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005906 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregord3297242013-01-16 23:00:23 +00005907 if (ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)){
5908 for (ObjCInterfaceDecl::visible_categories_iterator
5909 Cat = Class->visible_categories_begin(),
5910 CatEnd = Class->visible_categories_end();
5911 Cat != CatEnd; ++Cat) {
5912 CategoryNames.insert(Cat->getIdentifier());
5913 }
5914 }
5915
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005916 // Add all of the categories we know about.
5917 Results.EnterNewScope();
5918 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
5919 for (DeclContext::decl_iterator D = TU->decls_begin(),
5920 DEnd = TU->decls_end();
5921 D != DEnd; ++D)
5922 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(*D))
5923 if (CategoryNames.insert(Category->getIdentifier()))
Douglas Gregord1f09b42013-01-31 04:52:16 +00005924 Results.AddResult(Result(Category, Results.getBasePriority(Category),0),
5925 CurContext, 0, false);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005926 Results.ExitScope();
5927
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005928 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005929 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005930 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005931}
5932
5933void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorc83c6872010-04-15 22:33:43 +00005934 IdentifierInfo *ClassName,
5935 SourceLocation ClassNameLoc) {
John McCall0a2c5e22010-08-25 06:19:51 +00005936 typedef CodeCompletionResult Result;
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005937
5938 // Find the corresponding interface. If we couldn't find the interface, the
5939 // program itself is ill-formed. However, we'll try to be helpful still by
5940 // providing the list of all of the categories we know about.
5941 NamedDecl *CurClass
Douglas Gregorc83c6872010-04-15 22:33:43 +00005942 = LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005943 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
5944 if (!Class)
Douglas Gregorc83c6872010-04-15 22:33:43 +00005945 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005946
Douglas Gregor218937c2011-02-01 19:23:04 +00005947 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005948 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor3da626b2011-07-07 16:03:39 +00005949 CodeCompletionContext::CCC_ObjCCategoryName);
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005950
5951 // Add all of the categories that have have corresponding interface
5952 // declarations in this class and any of its superclasses, except for
5953 // already-implemented categories in the class itself.
5954 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
5955 Results.EnterNewScope();
5956 bool IgnoreImplemented = true;
5957 while (Class) {
Douglas Gregord3297242013-01-16 23:00:23 +00005958 for (ObjCInterfaceDecl::visible_categories_iterator
5959 Cat = Class->visible_categories_begin(),
5960 CatEnd = Class->visible_categories_end();
5961 Cat != CatEnd; ++Cat) {
5962 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
5963 CategoryNames.insert(Cat->getIdentifier()))
Douglas Gregord1f09b42013-01-31 04:52:16 +00005964 Results.AddResult(Result(*Cat, Results.getBasePriority(*Cat), 0),
5965 CurContext, 0, false);
Douglas Gregord3297242013-01-16 23:00:23 +00005966 }
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005967
5968 Class = Class->getSuperClass();
5969 IgnoreImplemented = false;
5970 }
5971 Results.ExitScope();
5972
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005973 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor3da626b2011-07-07 16:03:39 +00005974 CodeCompletionContext::CCC_ObjCCategoryName,
Douglas Gregore6b1bb62010-08-11 21:23:17 +00005975 Results.data(),Results.size());
Douglas Gregor33ced0b2009-11-18 19:08:43 +00005976}
Douglas Gregor322328b2009-11-18 22:32:06 +00005977
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005978void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregor218937c2011-02-01 19:23:04 +00005979 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00005980 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00005981 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00005982
5983 // Figure out where this @synthesize lives.
5984 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00005985 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00005986 if (!Container ||
5987 (!isa<ObjCImplementationDecl>(Container) &&
5988 !isa<ObjCCategoryImplDecl>(Container)))
5989 return;
5990
5991 // Ignore any properties that have already been implemented.
Douglas Gregorb92a4082012-06-12 13:44:08 +00005992 Container = getContainerDef(Container);
5993 for (DeclContext::decl_iterator D = Container->decls_begin(),
Douglas Gregor322328b2009-11-18 22:32:06 +00005994 DEnd = Container->decls_end();
5995 D != DEnd; ++D)
5996 if (ObjCPropertyImplDecl *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(*D))
5997 Results.Ignore(PropertyImpl->getPropertyDecl());
5998
5999 // Add any properties that we find.
Douglas Gregor73449212010-12-09 23:01:55 +00006000 AddedPropertiesSet AddedProperties;
Douglas Gregor322328b2009-11-18 22:32:06 +00006001 Results.EnterNewScope();
6002 if (ObjCImplementationDecl *ClassImpl
6003 = dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor4b81cde2011-05-05 15:50:42 +00006004 AddObjCProperties(ClassImpl->getClassInterface(), false,
6005 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor73449212010-12-09 23:01:55 +00006006 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00006007 else
6008 AddObjCProperties(cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Douglas Gregor4b81cde2011-05-05 15:50:42 +00006009 false, /*AllowNullaryMethods=*/false, CurContext,
6010 AddedProperties, Results);
Douglas Gregor322328b2009-11-18 22:32:06 +00006011 Results.ExitScope();
6012
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006013 HandleCodeCompleteResults(this, CodeCompleter,
6014 CodeCompletionContext::CCC_Other,
6015 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00006016}
6017
6018void Sema::CodeCompleteObjCPropertySynthesizeIvar(Scope *S,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006019 IdentifierInfo *PropertyName) {
John McCall0a2c5e22010-08-25 06:19:51 +00006020 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006021 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006022 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006023 CodeCompletionContext::CCC_Other);
Douglas Gregor322328b2009-11-18 22:32:06 +00006024
6025 // Figure out where this @synthesize lives.
6026 ObjCContainerDecl *Container
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006027 = dyn_cast_or_null<ObjCContainerDecl>(CurContext);
Douglas Gregor322328b2009-11-18 22:32:06 +00006028 if (!Container ||
6029 (!isa<ObjCImplementationDecl>(Container) &&
6030 !isa<ObjCCategoryImplDecl>(Container)))
6031 return;
6032
6033 // Figure out which interface we're looking into.
6034 ObjCInterfaceDecl *Class = 0;
6035 if (ObjCImplementationDecl *ClassImpl
6036 = dyn_cast<ObjCImplementationDecl>(Container))
6037 Class = ClassImpl->getClassInterface();
6038 else
6039 Class = cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl()
6040 ->getClassInterface();
6041
Douglas Gregore8426052011-04-18 14:40:46 +00006042 // Determine the type of the property we're synthesizing.
6043 QualType PropertyType = Context.getObjCIdType();
6044 if (Class) {
6045 if (ObjCPropertyDecl *Property
6046 = Class->FindPropertyDeclaration(PropertyName)) {
6047 PropertyType
6048 = Property->getType().getNonReferenceType().getUnqualifiedType();
6049
6050 // Give preference to ivars
6051 Results.setPreferredType(PropertyType);
6052 }
6053 }
6054
Douglas Gregor322328b2009-11-18 22:32:06 +00006055 // Add all of the instance variables in this class and its superclasses.
6056 Results.EnterNewScope();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006057 bool SawSimilarlyNamedIvar = false;
6058 std::string NameWithPrefix;
6059 NameWithPrefix += '_';
Benjamin Kramera0651c52011-07-26 16:59:25 +00006060 NameWithPrefix += PropertyName->getName();
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006061 std::string NameWithSuffix = PropertyName->getName().str();
6062 NameWithSuffix += '_';
Douglas Gregor322328b2009-11-18 22:32:06 +00006063 for(; Class; Class = Class->getSuperClass()) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006064 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
6065 Ivar = Ivar->getNextIvar()) {
Douglas Gregord1f09b42013-01-31 04:52:16 +00006066 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), 0),
6067 CurContext, 0, false);
Douglas Gregore8426052011-04-18 14:40:46 +00006068
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006069 // Determine whether we've seen an ivar with a name similar to the
6070 // property.
Douglas Gregore8426052011-04-18 14:40:46 +00006071 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006072 NameWithPrefix == Ivar->getName() ||
Douglas Gregore8426052011-04-18 14:40:46 +00006073 NameWithSuffix == Ivar->getName())) {
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006074 SawSimilarlyNamedIvar = true;
Douglas Gregore8426052011-04-18 14:40:46 +00006075
6076 // Reduce the priority of this result by one, to give it a slight
6077 // advantage over other results whose names don't match so closely.
6078 if (Results.size() &&
6079 Results.data()[Results.size() - 1].Kind
6080 == CodeCompletionResult::RK_Declaration &&
6081 Results.data()[Results.size() - 1].Declaration == Ivar)
6082 Results.data()[Results.size() - 1].Priority--;
6083 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006084 }
Douglas Gregor322328b2009-11-18 22:32:06 +00006085 }
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006086
6087 if (!SawSimilarlyNamedIvar) {
6088 // Create ivar result _propName, that the user can use to synthesize
Douglas Gregore8426052011-04-18 14:40:46 +00006089 // an ivar of the appropriate type.
6090 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006091 typedef CodeCompletionResult Result;
6092 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006093 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
6094 Priority,CXAvailability_Available);
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006095
Douglas Gregor8987b232011-09-27 23:30:47 +00006096 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8426052011-04-18 14:40:46 +00006097 Builder.AddResultTypeChunk(GetCompletionTypeString(PropertyType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006098 Policy, Allocator));
Douglas Gregoraa490cb2011-04-18 14:13:53 +00006099 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
6100 Results.AddResult(Result(Builder.TakeString(), Priority,
6101 CXCursor_ObjCIvarDecl));
6102 }
6103
Douglas Gregor322328b2009-11-18 22:32:06 +00006104 Results.ExitScope();
6105
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006106 HandleCodeCompleteResults(this, CodeCompleter,
6107 CodeCompletionContext::CCC_Other,
6108 Results.data(),Results.size());
Douglas Gregor322328b2009-11-18 22:32:06 +00006109}
Douglas Gregore8f5a172010-04-07 00:21:17 +00006110
Douglas Gregor408be5a2010-08-25 01:08:01 +00006111// Mapping from selectors to the methods that implement that selector, along
6112// with the "in original class" flag.
Benjamin Kramere1039792013-06-29 17:52:13 +00006113typedef llvm::DenseMap<
6114 Selector, llvm::PointerIntPair<ObjCMethodDecl *, 1, bool> > KnownMethodsMap;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006115
6116/// \brief Find all of the methods that reside in the given container
6117/// (and its superclasses, protocols, etc.) that meet the given
6118/// criteria. Insert those methods into the map of known methods,
6119/// indexed by selector so they can be easily found.
6120static void FindImplementableMethods(ASTContext &Context,
6121 ObjCContainerDecl *Container,
6122 bool WantInstanceMethods,
6123 QualType ReturnType,
Douglas Gregor408be5a2010-08-25 01:08:01 +00006124 KnownMethodsMap &KnownMethods,
6125 bool InOriginalClass = true) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006126 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006127 // Make sure we have a definition; that's what we'll walk.
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006128 if (!IFace->hasDefinition())
6129 return;
Douglas Gregorb92a4082012-06-12 13:44:08 +00006130
6131 IFace = IFace->getDefinition();
6132 Container = IFace;
Douglas Gregor2e5c15b2011-12-15 05:27:12 +00006133
Douglas Gregore8f5a172010-04-07 00:21:17 +00006134 const ObjCList<ObjCProtocolDecl> &Protocols
6135 = IFace->getReferencedProtocols();
6136 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006137 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006138 I != E; ++I)
6139 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006140 KnownMethods, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006141
Douglas Gregorea766182010-10-18 18:21:28 +00006142 // Add methods from any class extensions and categories.
Douglas Gregord3297242013-01-16 23:00:23 +00006143 for (ObjCInterfaceDecl::visible_categories_iterator
6144 Cat = IFace->visible_categories_begin(),
6145 CatEnd = IFace->visible_categories_end();
6146 Cat != CatEnd; ++Cat) {
6147 FindImplementableMethods(Context, *Cat, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006148 KnownMethods, false);
Douglas Gregord3297242013-01-16 23:00:23 +00006149 }
6150
Douglas Gregorea766182010-10-18 18:21:28 +00006151 // Visit the superclass.
6152 if (IFace->getSuperClass())
6153 FindImplementableMethods(Context, IFace->getSuperClass(),
6154 WantInstanceMethods, ReturnType,
6155 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006156 }
6157
6158 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6159 // Recurse into protocols.
6160 const ObjCList<ObjCProtocolDecl> &Protocols
6161 = Category->getReferencedProtocols();
6162 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Douglas Gregorea766182010-10-18 18:21:28 +00006163 E = Protocols.end();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006164 I != E; ++I)
6165 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregorea766182010-10-18 18:21:28 +00006166 KnownMethods, InOriginalClass);
6167
6168 // If this category is the original class, jump to the interface.
6169 if (InOriginalClass && Category->getClassInterface())
6170 FindImplementableMethods(Context, Category->getClassInterface(),
6171 WantInstanceMethods, ReturnType, KnownMethods,
6172 false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006173 }
6174
6175 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregorb92a4082012-06-12 13:44:08 +00006176 // Make sure we have a definition; that's what we'll walk.
6177 if (!Protocol->hasDefinition())
6178 return;
6179 Protocol = Protocol->getDefinition();
6180 Container = Protocol;
6181
6182 // Recurse into protocols.
6183 const ObjCList<ObjCProtocolDecl> &Protocols
6184 = Protocol->getReferencedProtocols();
6185 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
6186 E = Protocols.end();
6187 I != E; ++I)
6188 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
6189 KnownMethods, false);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006190 }
6191
6192 // Add methods in this container. This operation occurs last because
6193 // we want the methods from this container to override any methods
6194 // we've previously seen with the same selector.
6195 for (ObjCContainerDecl::method_iterator M = Container->meth_begin(),
6196 MEnd = Container->meth_end();
6197 M != MEnd; ++M) {
David Blaikie262bc182012-04-30 02:36:29 +00006198 if (M->isInstanceMethod() == WantInstanceMethods) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006199 if (!ReturnType.isNull() &&
David Blaikie262bc182012-04-30 02:36:29 +00006200 !Context.hasSameUnqualifiedType(ReturnType, M->getResultType()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006201 continue;
6202
Benjamin Kramere1039792013-06-29 17:52:13 +00006203 KnownMethods[M->getSelector()] =
6204 KnownMethodsMap::mapped_type(*M, InOriginalClass);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006205 }
6206 }
6207}
6208
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006209/// \brief Add the parenthesized return or parameter type chunk to a code
6210/// completion string.
6211static void AddObjCPassingTypeChunk(QualType Type,
Douglas Gregor90f5f472012-04-10 18:35:07 +00006212 unsigned ObjCDeclQuals,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006213 ASTContext &Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006214 const PrintingPolicy &Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006215 CodeCompletionBuilder &Builder) {
6216 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor90f5f472012-04-10 18:35:07 +00006217 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals);
6218 if (!Quals.empty())
6219 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Douglas Gregor8987b232011-09-27 23:30:47 +00006220 Builder.AddTextChunk(GetCompletionTypeString(Type, Context, Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006221 Builder.getAllocator()));
6222 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6223}
6224
6225/// \brief Determine whether the given class is or inherits from a class by
6226/// the given name.
6227static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class,
Chris Lattner5f9e2722011-07-23 10:55:15 +00006228 StringRef Name) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006229 if (!Class)
6230 return false;
6231
6232 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
6233 return true;
6234
6235 return InheritsFromClassNamed(Class->getSuperClass(), Name);
6236}
6237
6238/// \brief Add code completions for Objective-C Key-Value Coding (KVC) and
6239/// Key-Value Observing (KVO).
6240static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
6241 bool IsInstanceMethod,
6242 QualType ReturnType,
6243 ASTContext &Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00006244 VisitedSelectorSet &KnownSelectors,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006245 ResultBuilder &Results) {
6246 IdentifierInfo *PropName = Property->getIdentifier();
6247 if (!PropName || PropName->getLength() == 0)
6248 return;
6249
Douglas Gregor8987b232011-09-27 23:30:47 +00006250 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
6251
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006252 // Builder that will create each code completion.
6253 typedef CodeCompletionResult Result;
6254 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006255 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006256
6257 // The selector table.
6258 SelectorTable &Selectors = Context.Selectors;
6259
6260 // The property name, copied into the code completion allocation region
6261 // on demand.
6262 struct KeyHolder {
6263 CodeCompletionAllocator &Allocator;
Chris Lattner5f9e2722011-07-23 10:55:15 +00006264 StringRef Key;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006265 const char *CopiedKey;
6266
Chris Lattner5f9e2722011-07-23 10:55:15 +00006267 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006268 : Allocator(Allocator), Key(Key), CopiedKey(0) { }
6269
6270 operator const char *() {
6271 if (CopiedKey)
6272 return CopiedKey;
6273
6274 return CopiedKey = Allocator.CopyString(Key);
6275 }
6276 } Key(Allocator, PropName->getName());
6277
6278 // The uppercased name of the property name.
6279 std::string UpperKey = PropName->getName();
6280 if (!UpperKey.empty())
Jordan Rose223f0ff2013-02-09 10:09:43 +00006281 UpperKey[0] = toUppercase(UpperKey[0]);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006282
6283 bool ReturnTypeMatchesProperty = ReturnType.isNull() ||
6284 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
6285 Property->getType());
6286 bool ReturnTypeMatchesVoid
6287 = ReturnType.isNull() || ReturnType->isVoidType();
6288
6289 // Add the normal accessor -(type)key.
6290 if (IsInstanceMethod &&
Douglas Gregore74c25c2011-05-04 23:50:46 +00006291 KnownSelectors.insert(Selectors.getNullarySelector(PropName)) &&
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006292 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
6293 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006294 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6295 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006296
6297 Builder.AddTypedTextChunk(Key);
6298 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6299 CXCursor_ObjCInstanceMethodDecl));
6300 }
6301
6302 // If we have an integral or boolean property (or the user has provided
6303 // an integral or boolean return type), add the accessor -(type)isKey.
6304 if (IsInstanceMethod &&
6305 ((!ReturnType.isNull() &&
6306 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
6307 (ReturnType.isNull() &&
6308 (Property->getType()->isIntegerType() ||
6309 Property->getType()->isBooleanType())))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006310 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006311 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006312 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006313 if (ReturnType.isNull()) {
6314 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6315 Builder.AddTextChunk("BOOL");
6316 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6317 }
6318
6319 Builder.AddTypedTextChunk(
6320 Allocator.CopyString(SelectorId->getName()));
6321 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6322 CXCursor_ObjCInstanceMethodDecl));
6323 }
6324 }
6325
6326 // Add the normal mutator.
6327 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
6328 !Property->getSetterMethodDecl()) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006329 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006330 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006331 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006332 if (ReturnType.isNull()) {
6333 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6334 Builder.AddTextChunk("void");
6335 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6336 }
6337
6338 Builder.AddTypedTextChunk(
6339 Allocator.CopyString(SelectorId->getName()));
6340 Builder.AddTypedTextChunk(":");
Douglas Gregor90f5f472012-04-10 18:35:07 +00006341 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0,
6342 Context, Policy, Builder);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006343 Builder.AddTextChunk(Key);
6344 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6345 CXCursor_ObjCInstanceMethodDecl));
6346 }
6347 }
6348
6349 // Indexed and unordered accessors
6350 unsigned IndexedGetterPriority = CCP_CodePattern;
6351 unsigned IndexedSetterPriority = CCP_CodePattern;
6352 unsigned UnorderedGetterPriority = CCP_CodePattern;
6353 unsigned UnorderedSetterPriority = CCP_CodePattern;
6354 if (const ObjCObjectPointerType *ObjCPointer
6355 = Property->getType()->getAs<ObjCObjectPointerType>()) {
6356 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
6357 // If this interface type is not provably derived from a known
6358 // collection, penalize the corresponding completions.
6359 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
6360 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6361 if (!InheritsFromClassNamed(IFace, "NSArray"))
6362 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6363 }
6364
6365 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
6366 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6367 if (!InheritsFromClassNamed(IFace, "NSSet"))
6368 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6369 }
6370 }
6371 } else {
6372 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
6373 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
6374 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
6375 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
6376 }
6377
6378 // Add -(NSUInteger)countOf<key>
6379 if (IsInstanceMethod &&
6380 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006381 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006382 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006383 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006384 if (ReturnType.isNull()) {
6385 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6386 Builder.AddTextChunk("NSUInteger");
6387 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6388 }
6389
6390 Builder.AddTypedTextChunk(
6391 Allocator.CopyString(SelectorId->getName()));
6392 Results.AddResult(Result(Builder.TakeString(),
6393 std::min(IndexedGetterPriority,
6394 UnorderedGetterPriority),
6395 CXCursor_ObjCInstanceMethodDecl));
6396 }
6397 }
6398
6399 // Indexed getters
6400 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
6401 if (IsInstanceMethod &&
6402 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Douglas Gregor62041592011-02-17 03:19:26 +00006403 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006404 = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006405 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006406 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006407 if (ReturnType.isNull()) {
6408 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6409 Builder.AddTextChunk("id");
6410 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6411 }
6412
6413 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6414 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6415 Builder.AddTextChunk("NSUInteger");
6416 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6417 Builder.AddTextChunk("index");
6418 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6419 CXCursor_ObjCInstanceMethodDecl));
6420 }
6421 }
6422
6423 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
6424 if (IsInstanceMethod &&
6425 (ReturnType.isNull() ||
6426 (ReturnType->isObjCObjectPointerType() &&
6427 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6428 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6429 ->getName() == "NSArray"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006430 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006431 = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006432 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006433 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006434 if (ReturnType.isNull()) {
6435 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6436 Builder.AddTextChunk("NSArray *");
6437 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6438 }
6439
6440 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6441 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6442 Builder.AddTextChunk("NSIndexSet *");
6443 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6444 Builder.AddTextChunk("indexes");
6445 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6446 CXCursor_ObjCInstanceMethodDecl));
6447 }
6448 }
6449
6450 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
6451 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006452 std::string SelectorName = (Twine("get") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006453 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006454 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006455 &Context.Idents.get("range")
6456 };
6457
Douglas Gregore74c25c2011-05-04 23:50:46 +00006458 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006459 if (ReturnType.isNull()) {
6460 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6461 Builder.AddTextChunk("void");
6462 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6463 }
6464
6465 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6466 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6467 Builder.AddPlaceholderChunk("object-type");
6468 Builder.AddTextChunk(" **");
6469 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6470 Builder.AddTextChunk("buffer");
6471 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6472 Builder.AddTypedTextChunk("range:");
6473 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6474 Builder.AddTextChunk("NSRange");
6475 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6476 Builder.AddTextChunk("inRange");
6477 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
6478 CXCursor_ObjCInstanceMethodDecl));
6479 }
6480 }
6481
6482 // Mutable indexed accessors
6483
6484 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
6485 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006486 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006487 IdentifierInfo *SelectorIds[2] = {
6488 &Context.Idents.get("insertObject"),
Douglas Gregor62041592011-02-17 03:19:26 +00006489 &Context.Idents.get(SelectorName)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006490 };
6491
Douglas Gregore74c25c2011-05-04 23:50:46 +00006492 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006493 if (ReturnType.isNull()) {
6494 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6495 Builder.AddTextChunk("void");
6496 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6497 }
6498
6499 Builder.AddTypedTextChunk("insertObject:");
6500 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6501 Builder.AddPlaceholderChunk("object-type");
6502 Builder.AddTextChunk(" *");
6503 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6504 Builder.AddTextChunk("object");
6505 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6506 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6507 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6508 Builder.AddPlaceholderChunk("NSUInteger");
6509 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6510 Builder.AddTextChunk("index");
6511 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6512 CXCursor_ObjCInstanceMethodDecl));
6513 }
6514 }
6515
6516 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
6517 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006518 std::string SelectorName = (Twine("insert") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006519 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006520 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006521 &Context.Idents.get("atIndexes")
6522 };
6523
Douglas Gregore74c25c2011-05-04 23:50:46 +00006524 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006525 if (ReturnType.isNull()) {
6526 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6527 Builder.AddTextChunk("void");
6528 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6529 }
6530
6531 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6532 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6533 Builder.AddTextChunk("NSArray *");
6534 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6535 Builder.AddTextChunk("array");
6536 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6537 Builder.AddTypedTextChunk("atIndexes:");
6538 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6539 Builder.AddPlaceholderChunk("NSIndexSet *");
6540 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6541 Builder.AddTextChunk("indexes");
6542 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6543 CXCursor_ObjCInstanceMethodDecl));
6544 }
6545 }
6546
6547 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
6548 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006549 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006550 = (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006551 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006552 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006553 if (ReturnType.isNull()) {
6554 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6555 Builder.AddTextChunk("void");
6556 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6557 }
6558
6559 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6560 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6561 Builder.AddTextChunk("NSUInteger");
6562 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6563 Builder.AddTextChunk("index");
6564 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6565 CXCursor_ObjCInstanceMethodDecl));
6566 }
6567 }
6568
6569 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
6570 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006571 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006572 = (Twine("remove") + UpperKey + "AtIndexes").str();
Douglas Gregor62041592011-02-17 03:19:26 +00006573 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006574 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006575 if (ReturnType.isNull()) {
6576 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6577 Builder.AddTextChunk("void");
6578 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6579 }
6580
6581 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6582 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6583 Builder.AddTextChunk("NSIndexSet *");
6584 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6585 Builder.AddTextChunk("indexes");
6586 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6587 CXCursor_ObjCInstanceMethodDecl));
6588 }
6589 }
6590
6591 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
6592 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006593 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006594 = (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006595 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006596 &Context.Idents.get(SelectorName),
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006597 &Context.Idents.get("withObject")
6598 };
6599
Douglas Gregore74c25c2011-05-04 23:50:46 +00006600 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006601 if (ReturnType.isNull()) {
6602 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6603 Builder.AddTextChunk("void");
6604 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6605 }
6606
6607 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6608 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6609 Builder.AddPlaceholderChunk("NSUInteger");
6610 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6611 Builder.AddTextChunk("index");
6612 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6613 Builder.AddTypedTextChunk("withObject:");
6614 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6615 Builder.AddTextChunk("id");
6616 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6617 Builder.AddTextChunk("object");
6618 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6619 CXCursor_ObjCInstanceMethodDecl));
6620 }
6621 }
6622
6623 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
6624 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006625 std::string SelectorName1
Chris Lattner5f9e2722011-07-23 10:55:15 +00006626 = (Twine("replace") + UpperKey + "AtIndexes").str();
6627 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006628 IdentifierInfo *SelectorIds[2] = {
Douglas Gregor62041592011-02-17 03:19:26 +00006629 &Context.Idents.get(SelectorName1),
6630 &Context.Idents.get(SelectorName2)
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006631 };
6632
Douglas Gregore74c25c2011-05-04 23:50:46 +00006633 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006634 if (ReturnType.isNull()) {
6635 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6636 Builder.AddTextChunk("void");
6637 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6638 }
6639
6640 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
6641 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6642 Builder.AddPlaceholderChunk("NSIndexSet *");
6643 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6644 Builder.AddTextChunk("indexes");
6645 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6646 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
6647 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6648 Builder.AddTextChunk("NSArray *");
6649 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6650 Builder.AddTextChunk("array");
6651 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
6652 CXCursor_ObjCInstanceMethodDecl));
6653 }
6654 }
6655
6656 // Unordered getters
6657 // - (NSEnumerator *)enumeratorOfKey
6658 if (IsInstanceMethod &&
6659 (ReturnType.isNull() ||
6660 (ReturnType->isObjCObjectPointerType() &&
6661 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6662 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6663 ->getName() == "NSEnumerator"))) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006664 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006665 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006666 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006667 if (ReturnType.isNull()) {
6668 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6669 Builder.AddTextChunk("NSEnumerator *");
6670 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6671 }
6672
6673 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6674 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6675 CXCursor_ObjCInstanceMethodDecl));
6676 }
6677 }
6678
6679 // - (type *)memberOfKey:(type *)object
6680 if (IsInstanceMethod &&
6681 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006682 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006683 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006684 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006685 if (ReturnType.isNull()) {
6686 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6687 Builder.AddPlaceholderChunk("object-type");
6688 Builder.AddTextChunk(" *");
6689 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6690 }
6691
6692 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6693 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6694 if (ReturnType.isNull()) {
6695 Builder.AddPlaceholderChunk("object-type");
6696 Builder.AddTextChunk(" *");
6697 } else {
6698 Builder.AddTextChunk(GetCompletionTypeString(ReturnType, Context,
Douglas Gregor8987b232011-09-27 23:30:47 +00006699 Policy,
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006700 Builder.getAllocator()));
6701 }
6702 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6703 Builder.AddTextChunk("object");
6704 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
6705 CXCursor_ObjCInstanceMethodDecl));
6706 }
6707 }
6708
6709 // Mutable unordered accessors
6710 // - (void)addKeyObject:(type *)object
6711 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006712 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006713 = (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006714 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006715 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006716 if (ReturnType.isNull()) {
6717 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6718 Builder.AddTextChunk("void");
6719 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6720 }
6721
6722 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6723 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6724 Builder.AddPlaceholderChunk("object-type");
6725 Builder.AddTextChunk(" *");
6726 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6727 Builder.AddTextChunk("object");
6728 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6729 CXCursor_ObjCInstanceMethodDecl));
6730 }
6731 }
6732
6733 // - (void)addKey:(NSSet *)objects
6734 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006735 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006736 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006737 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006738 if (ReturnType.isNull()) {
6739 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6740 Builder.AddTextChunk("void");
6741 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6742 }
6743
6744 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6745 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6746 Builder.AddTextChunk("NSSet *");
6747 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6748 Builder.AddTextChunk("objects");
6749 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6750 CXCursor_ObjCInstanceMethodDecl));
6751 }
6752 }
6753
6754 // - (void)removeKeyObject:(type *)object
6755 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Douglas Gregor62041592011-02-17 03:19:26 +00006756 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006757 = (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006758 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006759 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006760 if (ReturnType.isNull()) {
6761 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6762 Builder.AddTextChunk("void");
6763 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6764 }
6765
6766 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6767 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6768 Builder.AddPlaceholderChunk("object-type");
6769 Builder.AddTextChunk(" *");
6770 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6771 Builder.AddTextChunk("object");
6772 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6773 CXCursor_ObjCInstanceMethodDecl));
6774 }
6775 }
6776
6777 // - (void)removeKey:(NSSet *)objects
6778 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006779 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006780 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006781 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006782 if (ReturnType.isNull()) {
6783 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6784 Builder.AddTextChunk("void");
6785 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6786 }
6787
6788 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6789 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6790 Builder.AddTextChunk("NSSet *");
6791 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6792 Builder.AddTextChunk("objects");
6793 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6794 CXCursor_ObjCInstanceMethodDecl));
6795 }
6796 }
6797
6798 // - (void)intersectKey:(NSSet *)objects
6799 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006800 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006801 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006802 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006803 if (ReturnType.isNull()) {
6804 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6805 Builder.AddTextChunk("void");
6806 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6807 }
6808
6809 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
6810 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6811 Builder.AddTextChunk("NSSet *");
6812 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6813 Builder.AddTextChunk("objects");
6814 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
6815 CXCursor_ObjCInstanceMethodDecl));
6816 }
6817 }
6818
6819 // Key-Value Observing
6820 // + (NSSet *)keyPathsForValuesAffectingKey
6821 if (!IsInstanceMethod &&
6822 (ReturnType.isNull() ||
6823 (ReturnType->isObjCObjectPointerType() &&
6824 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
6825 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl()
6826 ->getName() == "NSSet"))) {
Douglas Gregor62041592011-02-17 03:19:26 +00006827 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006828 = (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor62041592011-02-17 03:19:26 +00006829 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
Douglas Gregore74c25c2011-05-04 23:50:46 +00006830 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006831 if (ReturnType.isNull()) {
6832 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6833 Builder.AddTextChunk("NSSet *");
6834 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6835 }
6836
6837 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6838 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor3f828d12011-06-02 04:02:27 +00006839 CXCursor_ObjCClassMethodDecl));
6840 }
6841 }
6842
6843 // + (BOOL)automaticallyNotifiesObserversForKey
6844 if (!IsInstanceMethod &&
6845 (ReturnType.isNull() ||
6846 ReturnType->isIntegerType() ||
6847 ReturnType->isBooleanType())) {
6848 std::string SelectorName
Chris Lattner5f9e2722011-07-23 10:55:15 +00006849 = (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor3f828d12011-06-02 04:02:27 +00006850 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
6851 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))) {
6852 if (ReturnType.isNull()) {
6853 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
6854 Builder.AddTextChunk("BOOL");
6855 Builder.AddChunk(CodeCompletionString::CK_RightParen);
6856 }
6857
6858 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
6859 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
6860 CXCursor_ObjCClassMethodDecl));
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006861 }
6862 }
6863}
6864
Douglas Gregore8f5a172010-04-07 00:21:17 +00006865void Sema::CodeCompleteObjCMethodDecl(Scope *S,
6866 bool IsInstanceMethod,
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006867 ParsedType ReturnTy) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006868 // Determine the return type of the method we're declaring, if
6869 // provided.
6870 QualType ReturnType = GetTypeFromParser(ReturnTy);
Fariborz Jahaniana28948f2011-08-22 15:54:49 +00006871 Decl *IDecl = 0;
6872 if (CurContext->isObjCContainer()) {
6873 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
6874 IDecl = cast<Decl>(OCD);
6875 }
Douglas Gregorea766182010-10-18 18:21:28 +00006876 // Determine where we should start searching for methods.
6877 ObjCContainerDecl *SearchDecl = 0;
Douglas Gregore8f5a172010-04-07 00:21:17 +00006878 bool IsInImplementation = false;
John McCalld226f652010-08-21 09:40:31 +00006879 if (Decl *D = IDecl) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006880 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
6881 SearchDecl = Impl->getClassInterface();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006882 IsInImplementation = true;
6883 } else if (ObjCCategoryImplDecl *CatImpl
Douglas Gregorea766182010-10-18 18:21:28 +00006884 = dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006885 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregore8f5a172010-04-07 00:21:17 +00006886 IsInImplementation = true;
Douglas Gregorea766182010-10-18 18:21:28 +00006887 } else
Douglas Gregore8f5a172010-04-07 00:21:17 +00006888 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006889 }
6890
6891 if (!SearchDecl && S) {
Douglas Gregorea766182010-10-18 18:21:28 +00006892 if (DeclContext *DC = static_cast<DeclContext *>(S->getEntity()))
Douglas Gregore8f5a172010-04-07 00:21:17 +00006893 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006894 }
6895
Douglas Gregorea766182010-10-18 18:21:28 +00006896 if (!SearchDecl) {
Douglas Gregore6b1bb62010-08-11 21:23:17 +00006897 HandleCodeCompleteResults(this, CodeCompleter,
6898 CodeCompletionContext::CCC_Other,
6899 0, 0);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006900 return;
6901 }
6902
6903 // Find all of the methods that we could declare/implement here.
6904 KnownMethodsMap KnownMethods;
6905 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod,
Douglas Gregorea766182010-10-18 18:21:28 +00006906 ReturnType, KnownMethods);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006907
Douglas Gregore8f5a172010-04-07 00:21:17 +00006908 // Add declarations or definitions for each of the known methods.
John McCall0a2c5e22010-08-25 06:19:51 +00006909 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00006910 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006911 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00006912 CodeCompletionContext::CCC_Other);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006913 Results.EnterNewScope();
Douglas Gregor8987b232011-09-27 23:30:47 +00006914 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006915 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
6916 MEnd = KnownMethods.end();
6917 M != MEnd; ++M) {
Benjamin Kramere1039792013-06-29 17:52:13 +00006918 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00006919 CodeCompletionBuilder Builder(Results.getAllocator(),
6920 Results.getCodeCompletionTUInfo());
Douglas Gregore8f5a172010-04-07 00:21:17 +00006921
6922 // If the result type was not already provided, add it to the
6923 // pattern as (type).
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006924 if (ReturnType.isNull())
Douglas Gregor90f5f472012-04-10 18:35:07 +00006925 AddObjCPassingTypeChunk(Method->getResultType(),
6926 Method->getObjCDeclQualifier(),
6927 Context, Policy,
6928 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006929
6930 Selector Sel = Method->getSelector();
6931
6932 // Add the first part of the selector to the pattern.
Douglas Gregordae68752011-02-01 22:57:45 +00006933 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor813d8342011-02-18 22:29:55 +00006934 Sel.getNameForSlot(0)));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006935
6936 // Add parameters to the pattern.
6937 unsigned I = 0;
6938 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
6939 PEnd = Method->param_end();
6940 P != PEnd; (void)++P, ++I) {
6941 // Add the part of the selector name.
6942 if (I == 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006943 Builder.AddTypedTextChunk(":");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006944 else if (I < Sel.getNumArgs()) {
Douglas Gregor218937c2011-02-01 19:23:04 +00006945 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6946 Builder.AddTypedTextChunk(
Douglas Gregor813d8342011-02-18 22:29:55 +00006947 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006948 } else
6949 break;
6950
6951 // Add the parameter type.
Douglas Gregor90f5f472012-04-10 18:35:07 +00006952 AddObjCPassingTypeChunk((*P)->getOriginalType(),
6953 (*P)->getObjCDeclQualifier(),
6954 Context, Policy,
Douglas Gregor8987b232011-09-27 23:30:47 +00006955 Builder);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006956
6957 if (IdentifierInfo *Id = (*P)->getIdentifier())
Douglas Gregordae68752011-02-01 22:57:45 +00006958 Builder.AddTextChunk(Builder.getAllocator().CopyString( Id->getName()));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006959 }
6960
6961 if (Method->isVariadic()) {
6962 if (Method->param_size() > 0)
Douglas Gregor218937c2011-02-01 19:23:04 +00006963 Builder.AddChunk(CodeCompletionString::CK_Comma);
6964 Builder.AddTextChunk("...");
Douglas Gregore17794f2010-08-31 05:13:43 +00006965 }
Douglas Gregore8f5a172010-04-07 00:21:17 +00006966
Douglas Gregor447107d2010-05-28 00:57:46 +00006967 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregore8f5a172010-04-07 00:21:17 +00006968 // We will be defining the method here, so add a compound statement.
Douglas Gregor218937c2011-02-01 19:23:04 +00006969 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6970 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
6971 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006972 if (!Method->getResultType()->isVoidType()) {
6973 // If the result type is not void, add a return clause.
Douglas Gregor218937c2011-02-01 19:23:04 +00006974 Builder.AddTextChunk("return");
6975 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
6976 Builder.AddPlaceholderChunk("expression");
6977 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006978 } else
Douglas Gregor218937c2011-02-01 19:23:04 +00006979 Builder.AddPlaceholderChunk("statements");
Douglas Gregore8f5a172010-04-07 00:21:17 +00006980
Douglas Gregor218937c2011-02-01 19:23:04 +00006981 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
6982 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregore8f5a172010-04-07 00:21:17 +00006983 }
6984
Douglas Gregor408be5a2010-08-25 01:08:01 +00006985 unsigned Priority = CCP_CodePattern;
Benjamin Kramere1039792013-06-29 17:52:13 +00006986 if (!M->second.getInt())
Douglas Gregor408be5a2010-08-25 01:08:01 +00006987 Priority += CCD_InBaseClass;
6988
Douglas Gregorba103062012-03-27 23:34:16 +00006989 Results.AddResult(Result(Builder.TakeString(), Method, Priority));
Douglas Gregore8f5a172010-04-07 00:21:17 +00006990 }
6991
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006992 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
6993 // the properties in this class and its categories.
David Blaikie4e4d0842012-03-11 07:00:24 +00006994 if (Context.getLangOpts().ObjC2) {
Chris Lattner5f9e2722011-07-23 10:55:15 +00006995 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor577cdfd2011-02-17 00:22:45 +00006996 Containers.push_back(SearchDecl);
6997
Douglas Gregore74c25c2011-05-04 23:50:46 +00006998 VisitedSelectorSet KnownSelectors;
6999 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
7000 MEnd = KnownMethods.end();
7001 M != MEnd; ++M)
7002 KnownSelectors.insert(M->first);
7003
7004
Douglas Gregor577cdfd2011-02-17 00:22:45 +00007005 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7006 if (!IFace)
7007 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7008 IFace = Category->getClassInterface();
7009
7010 if (IFace) {
Douglas Gregord3297242013-01-16 23:00:23 +00007011 for (ObjCInterfaceDecl::visible_categories_iterator
7012 Cat = IFace->visible_categories_begin(),
7013 CatEnd = IFace->visible_categories_end();
7014 Cat != CatEnd; ++Cat) {
7015 Containers.push_back(*Cat);
7016 }
Douglas Gregor577cdfd2011-02-17 00:22:45 +00007017 }
7018
7019 for (unsigned I = 0, N = Containers.size(); I != N; ++I) {
7020 for (ObjCContainerDecl::prop_iterator P = Containers[I]->prop_begin(),
7021 PEnd = Containers[I]->prop_end();
7022 P != PEnd; ++P) {
David Blaikie581deb32012-06-06 20:45:41 +00007023 AddObjCKeyValueCompletions(*P, IsInstanceMethod, ReturnType, Context,
Douglas Gregore74c25c2011-05-04 23:50:46 +00007024 KnownSelectors, Results);
Douglas Gregor577cdfd2011-02-17 00:22:45 +00007025 }
7026 }
7027 }
7028
Douglas Gregore8f5a172010-04-07 00:21:17 +00007029 Results.ExitScope();
7030
Douglas Gregore6b1bb62010-08-11 21:23:17 +00007031 HandleCodeCompleteResults(this, CodeCompleter,
7032 CodeCompletionContext::CCC_Other,
7033 Results.data(),Results.size());
Douglas Gregore8f5a172010-04-07 00:21:17 +00007034}
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007035
7036void Sema::CodeCompleteObjCMethodDeclSelector(Scope *S,
7037 bool IsInstanceMethod,
Douglas Gregor40ed9a12010-07-08 23:37:41 +00007038 bool AtParameterName,
John McCallb3d87482010-08-24 05:47:05 +00007039 ParsedType ReturnTy,
Dmitri Gribenko050315b2013-06-16 03:47:57 +00007040 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007041 // If we have an external source, load the entire class method
Sebastian Redl3c7f4132010-08-18 23:57:06 +00007042 // pool from the AST file.
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007043 if (ExternalSource) {
7044 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
7045 I != N; ++I) {
7046 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redldb9d2142010-08-02 23:18:59 +00007047 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007048 continue;
Sebastian Redldb9d2142010-08-02 23:18:59 +00007049
7050 ReadMethodPool(Sel);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007051 }
7052 }
7053
7054 // Build the set of methods we can see.
John McCall0a2c5e22010-08-25 06:19:51 +00007055 typedef CodeCompletionResult Result;
Douglas Gregor218937c2011-02-01 19:23:04 +00007056 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007057 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor218937c2011-02-01 19:23:04 +00007058 CodeCompletionContext::CCC_Other);
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007059
7060 if (ReturnTy)
7061 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redldb9d2142010-08-02 23:18:59 +00007062
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007063 Results.EnterNewScope();
Sebastian Redldb9d2142010-08-02 23:18:59 +00007064 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7065 MEnd = MethodPool.end();
7066 M != MEnd; ++M) {
7067 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first :
7068 &M->second.second;
7069 MethList && MethList->Method;
Argyrios Kyrtzidis2e3d8c02013-04-17 00:08:58 +00007070 MethList = MethList->getNext()) {
Dmitri Gribenko050315b2013-06-16 03:47:57 +00007071 if (!isAcceptableObjCMethod(MethList->Method, MK_Any, SelIdents))
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007072 continue;
7073
Douglas Gregor40ed9a12010-07-08 23:37:41 +00007074 if (AtParameterName) {
7075 // Suggest parameter names we've seen before.
Dmitri Gribenko050315b2013-06-16 03:47:57 +00007076 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor40ed9a12010-07-08 23:37:41 +00007077 if (NumSelIdents && NumSelIdents <= MethList->Method->param_size()) {
7078 ParmVarDecl *Param = MethList->Method->param_begin()[NumSelIdents-1];
7079 if (Param->getIdentifier()) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007080 CodeCompletionBuilder Builder(Results.getAllocator(),
7081 Results.getCodeCompletionTUInfo());
Douglas Gregordae68752011-02-01 22:57:45 +00007082 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007083 Param->getIdentifier()->getName()));
7084 Results.AddResult(Builder.TakeString());
Douglas Gregor40ed9a12010-07-08 23:37:41 +00007085 }
7086 }
7087
7088 continue;
7089 }
7090
Douglas Gregord1f09b42013-01-31 04:52:16 +00007091 Result R(MethList->Method, Results.getBasePriority(MethList->Method), 0);
Dmitri Gribenko050315b2013-06-16 03:47:57 +00007092 R.StartParameter = SelIdents.size();
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007093 R.AllParametersAreInformative = false;
7094 R.DeclaringEntity = true;
7095 Results.MaybeAddResult(R, CurContext);
7096 }
7097 }
7098
7099 Results.ExitScope();
Douglas Gregore6b1bb62010-08-11 21:23:17 +00007100 HandleCodeCompleteResults(this, CodeCompleter,
7101 CodeCompletionContext::CCC_Other,
7102 Results.data(),Results.size());
Douglas Gregor1f5537a2010-07-08 23:20:03 +00007103}
Douglas Gregor87c08a52010-08-13 22:48:40 +00007104
Douglas Gregorf29c5232010-08-24 22:20:20 +00007105void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007106 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007107 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007108 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007109 Results.EnterNewScope();
7110
7111 // #if <condition>
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007112 CodeCompletionBuilder Builder(Results.getAllocator(),
7113 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007114 Builder.AddTypedTextChunk("if");
7115 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7116 Builder.AddPlaceholderChunk("condition");
7117 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007118
7119 // #ifdef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007120 Builder.AddTypedTextChunk("ifdef");
7121 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7122 Builder.AddPlaceholderChunk("macro");
7123 Results.AddResult(Builder.TakeString());
7124
Douglas Gregorf44e8542010-08-24 19:08:16 +00007125 // #ifndef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007126 Builder.AddTypedTextChunk("ifndef");
7127 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7128 Builder.AddPlaceholderChunk("macro");
7129 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007130
7131 if (InConditional) {
7132 // #elif <condition>
Douglas Gregor218937c2011-02-01 19:23:04 +00007133 Builder.AddTypedTextChunk("elif");
7134 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7135 Builder.AddPlaceholderChunk("condition");
7136 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007137
7138 // #else
Douglas Gregor218937c2011-02-01 19:23:04 +00007139 Builder.AddTypedTextChunk("else");
7140 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007141
7142 // #endif
Douglas Gregor218937c2011-02-01 19:23:04 +00007143 Builder.AddTypedTextChunk("endif");
7144 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007145 }
7146
7147 // #include "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007148 Builder.AddTypedTextChunk("include");
7149 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7150 Builder.AddTextChunk("\"");
7151 Builder.AddPlaceholderChunk("header");
7152 Builder.AddTextChunk("\"");
7153 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007154
7155 // #include <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007156 Builder.AddTypedTextChunk("include");
7157 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7158 Builder.AddTextChunk("<");
7159 Builder.AddPlaceholderChunk("header");
7160 Builder.AddTextChunk(">");
7161 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007162
7163 // #define <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007164 Builder.AddTypedTextChunk("define");
7165 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7166 Builder.AddPlaceholderChunk("macro");
7167 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007168
7169 // #define <macro>(<args>)
Douglas Gregor218937c2011-02-01 19:23:04 +00007170 Builder.AddTypedTextChunk("define");
7171 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7172 Builder.AddPlaceholderChunk("macro");
7173 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7174 Builder.AddPlaceholderChunk("args");
7175 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7176 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007177
7178 // #undef <macro>
Douglas Gregor218937c2011-02-01 19:23:04 +00007179 Builder.AddTypedTextChunk("undef");
7180 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7181 Builder.AddPlaceholderChunk("macro");
7182 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007183
7184 // #line <number>
Douglas Gregor218937c2011-02-01 19:23:04 +00007185 Builder.AddTypedTextChunk("line");
7186 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7187 Builder.AddPlaceholderChunk("number");
7188 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007189
7190 // #line <number> "filename"
Douglas Gregor218937c2011-02-01 19:23:04 +00007191 Builder.AddTypedTextChunk("line");
7192 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7193 Builder.AddPlaceholderChunk("number");
7194 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7195 Builder.AddTextChunk("\"");
7196 Builder.AddPlaceholderChunk("filename");
7197 Builder.AddTextChunk("\"");
7198 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007199
7200 // #error <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007201 Builder.AddTypedTextChunk("error");
7202 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7203 Builder.AddPlaceholderChunk("message");
7204 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007205
7206 // #pragma <arguments>
Douglas Gregor218937c2011-02-01 19:23:04 +00007207 Builder.AddTypedTextChunk("pragma");
7208 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7209 Builder.AddPlaceholderChunk("arguments");
7210 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007211
David Blaikie4e4d0842012-03-11 07:00:24 +00007212 if (getLangOpts().ObjC1) {
Douglas Gregorf44e8542010-08-24 19:08:16 +00007213 // #import "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007214 Builder.AddTypedTextChunk("import");
7215 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7216 Builder.AddTextChunk("\"");
7217 Builder.AddPlaceholderChunk("header");
7218 Builder.AddTextChunk("\"");
7219 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007220
7221 // #import <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007222 Builder.AddTypedTextChunk("import");
7223 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7224 Builder.AddTextChunk("<");
7225 Builder.AddPlaceholderChunk("header");
7226 Builder.AddTextChunk(">");
7227 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007228 }
7229
7230 // #include_next "header"
Douglas Gregor218937c2011-02-01 19:23:04 +00007231 Builder.AddTypedTextChunk("include_next");
7232 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7233 Builder.AddTextChunk("\"");
7234 Builder.AddPlaceholderChunk("header");
7235 Builder.AddTextChunk("\"");
7236 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007237
7238 // #include_next <header>
Douglas Gregor218937c2011-02-01 19:23:04 +00007239 Builder.AddTypedTextChunk("include_next");
7240 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7241 Builder.AddTextChunk("<");
7242 Builder.AddPlaceholderChunk("header");
7243 Builder.AddTextChunk(">");
7244 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007245
7246 // #warning <message>
Douglas Gregor218937c2011-02-01 19:23:04 +00007247 Builder.AddTypedTextChunk("warning");
7248 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7249 Builder.AddPlaceholderChunk("message");
7250 Results.AddResult(Builder.TakeString());
Douglas Gregorf44e8542010-08-24 19:08:16 +00007251
7252 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
7253 // completions for them. And __include_macros is a Clang-internal extension
7254 // that we don't want to encourage anyone to use.
7255
7256 // FIXME: we don't support #assert or #unassert, so don't suggest them.
7257 Results.ExitScope();
7258
Douglas Gregorf44e8542010-08-24 19:08:16 +00007259 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregor721f3592010-08-25 18:41:16 +00007260 CodeCompletionContext::CCC_PreprocessorDirective,
Douglas Gregorf44e8542010-08-24 19:08:16 +00007261 Results.data(), Results.size());
7262}
7263
7264void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Douglas Gregorf29c5232010-08-24 22:20:20 +00007265 CodeCompleteOrdinaryName(S,
John McCallf312b1e2010-08-26 23:41:50 +00007266 S->getFnParent()? Sema::PCC_RecoveryInFunction
7267 : Sema::PCC_Namespace);
Douglas Gregorf44e8542010-08-24 19:08:16 +00007268}
7269
Douglas Gregorf29c5232010-08-24 22:20:20 +00007270void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregor218937c2011-02-01 19:23:04 +00007271 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007272 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007273 IsDefinition? CodeCompletionContext::CCC_MacroName
7274 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007275 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
7276 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007277 CodeCompletionBuilder Builder(Results.getAllocator(),
7278 Results.getCodeCompletionTUInfo());
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007279 Results.EnterNewScope();
7280 for (Preprocessor::macro_iterator M = PP.macro_begin(),
7281 MEnd = PP.macro_end();
7282 M != MEnd; ++M) {
Douglas Gregordae68752011-02-01 22:57:45 +00007283 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Douglas Gregor218937c2011-02-01 19:23:04 +00007284 M->first->getName()));
Argyrios Kyrtzidisc04bb922012-09-27 00:24:09 +00007285 Results.AddResult(CodeCompletionResult(Builder.TakeString(),
7286 CCP_CodePattern,
7287 CXCursor_MacroDefinition));
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007288 }
7289 Results.ExitScope();
7290 } else if (IsDefinition) {
7291 // FIXME: Can we detect when the user just wrote an include guard above?
7292 }
7293
Douglas Gregor52779fb2010-09-23 23:01:17 +00007294 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor1fbb4472010-08-24 20:21:13 +00007295 Results.data(), Results.size());
7296}
7297
Douglas Gregorf29c5232010-08-24 22:20:20 +00007298void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregor218937c2011-02-01 19:23:04 +00007299 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007300 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor52779fb2010-09-23 23:01:17 +00007301 CodeCompletionContext::CCC_PreprocessorExpression);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007302
7303 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007304 AddMacroResults(PP, Results, true);
Douglas Gregorf29c5232010-08-24 22:20:20 +00007305
7306 // defined (<macro>)
7307 Results.EnterNewScope();
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007308 CodeCompletionBuilder Builder(Results.getAllocator(),
7309 Results.getCodeCompletionTUInfo());
Douglas Gregor218937c2011-02-01 19:23:04 +00007310 Builder.AddTypedTextChunk("defined");
7311 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7312 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7313 Builder.AddPlaceholderChunk("macro");
7314 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7315 Results.AddResult(Builder.TakeString());
Douglas Gregorf29c5232010-08-24 22:20:20 +00007316 Results.ExitScope();
7317
7318 HandleCodeCompleteResults(this, CodeCompleter,
7319 CodeCompletionContext::CCC_PreprocessorExpression,
7320 Results.data(), Results.size());
7321}
7322
7323void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
7324 IdentifierInfo *Macro,
7325 MacroInfo *MacroInfo,
7326 unsigned Argument) {
7327 // FIXME: In the future, we could provide "overload" results, much like we
7328 // do for function calls.
7329
Argyrios Kyrtzidis5c5f03e2011-08-18 19:41:28 +00007330 // Now just ignore this. There will be another code-completion callback
7331 // for the expanded tokens.
Douglas Gregorf29c5232010-08-24 22:20:20 +00007332}
7333
Douglas Gregor55817af2010-08-25 17:04:25 +00007334void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor55817af2010-08-25 17:04:25 +00007335 HandleCodeCompleteResults(this, CodeCompleter,
Douglas Gregoraf1c6b52010-08-25 17:10:00 +00007336 CodeCompletionContext::CCC_NaturalLanguage,
Douglas Gregor55817af2010-08-25 17:04:25 +00007337 0, 0);
7338}
7339
Douglas Gregordae68752011-02-01 22:57:45 +00007340void Sema::GatherGlobalCodeCompletions(CodeCompletionAllocator &Allocator,
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007341 CodeCompletionTUInfo &CCTUInfo,
Chris Lattner5f9e2722011-07-23 10:55:15 +00007342 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis28a83f52012-04-10 17:23:48 +00007343 ResultBuilder Builder(*this, Allocator, CCTUInfo,
7344 CodeCompletionContext::CCC_Recovery);
Douglas Gregor8071e422010-08-15 06:18:01 +00007345 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
7346 CodeCompletionDeclConsumer Consumer(Builder,
7347 Context.getTranslationUnitDecl());
7348 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
7349 Consumer);
7350 }
Douglas Gregor87c08a52010-08-13 22:48:40 +00007351
7352 if (!CodeCompleter || CodeCompleter->includeMacros())
Douglas Gregor3644d972012-10-09 16:01:50 +00007353 AddMacroResults(PP, Builder, true);
Douglas Gregor87c08a52010-08-13 22:48:40 +00007354
7355 Results.clear();
7356 Results.insert(Results.end(),
7357 Builder.data(), Builder.data() + Builder.size());
7358}