blob: 11c5e6369bdf5bb254481231dde79359d2608f51 [file] [log] [blame]
Douglas Gregor2436e712009-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//===----------------------------------------------------------------------===//
Eric Liub91e0812018-10-02 10:29:00 +000013#include "clang/AST/Decl.h"
Ilya Biryukov98397552018-12-05 17:38:39 +000014#include "clang/AST/DeclBase.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000015#include "clang/AST/DeclCXX.h"
John McCallde6836a2010-08-24 07:21:54 +000016#include "clang/AST/DeclObjC.h"
Douglas Gregorf2510672009-09-21 19:57:38 +000017#include "clang/AST/ExprCXX.h"
Douglas Gregor8ce33212009-11-17 17:59:40 +000018#include "clang/AST/ExprObjC.h"
Ilya Biryukovb5da91c2017-11-08 10:39:09 +000019#include "clang/AST/QualTypeNames.h"
Jordan Rose4938f272013-02-09 10:09:43 +000020#include "clang/Basic/CharInfo.h"
Douglas Gregor07f43572012-01-29 18:15:03 +000021#include "clang/Lex/HeaderSearch.h"
Douglas Gregorf329c7c2009-10-30 16:50:04 +000022#include "clang/Lex/MacroInfo.h"
23#include "clang/Lex/Preprocessor.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000024#include "clang/Sema/CodeCompleteConsumer.h"
Chandler Carruth3a022472012-12-04 09:13:33 +000025#include "clang/Sema/Lookup.h"
26#include "clang/Sema/Overload.h"
27#include "clang/Sema/Scope.h"
28#include "clang/Sema/ScopeInfo.h"
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +000029#include "clang/Sema/SemaInternal.h"
Douglas Gregor1154e272010-09-16 16:06:31 +000030#include "llvm/ADT/DenseSet.h"
Benjamin Kramere0513cb2012-01-30 16:17:39 +000031#include "llvm/ADT/SmallBitVector.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000032#include "llvm/ADT/SmallPtrSet.h"
Benjamin Kramer49038022012-02-04 13:45:25 +000033#include "llvm/ADT/SmallString.h"
Douglas Gregore6688e62009-09-28 03:51:44 +000034#include "llvm/ADT/StringExtras.h"
Douglas Gregor9d2ddb22010-04-06 19:22:33 +000035#include "llvm/ADT/StringSwitch.h"
Douglas Gregor67c692c2010-08-26 15:07:07 +000036#include "llvm/ADT/Twine.h"
Sam McCall3d8051a2018-09-18 08:40:41 +000037#include "llvm/ADT/iterator_range.h"
38#include "llvm/Support/Path.h"
Douglas Gregor3545ff42009-09-21 16:56:56 +000039#include <list>
40#include <map>
41#include <vector>
Douglas Gregor2436e712009-09-17 21:32:03 +000042
43using namespace clang;
John McCallaab3e412010-08-25 08:40:02 +000044using namespace sema;
Douglas Gregor2436e712009-09-17 21:32:03 +000045
Douglas Gregor3545ff42009-09-21 16:56:56 +000046namespace {
Fangrui Song050229d2018-11-24 00:14:31 +000047/// A container of code-completion results.
48class ResultBuilder {
49public:
50 /// The type of a name-lookup filter, which can be provided to the
51 /// name-lookup routines to specify which declarations should be included in
52 /// the result set (when it returns true) and which declarations should be
53 /// filtered out (returns false).
54 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const;
Ivan Donchevskii13d90542017-10-27 11:05:40 +000055
Fangrui Song050229d2018-11-24 00:14:31 +000056 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000057
Fangrui Song050229d2018-11-24 00:14:31 +000058private:
59 /// The actual results we have found.
60 std::vector<Result> Results;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000061
Fangrui Song050229d2018-11-24 00:14:31 +000062 /// A record of all of the declarations we have found and placed
63 /// into the result set, used to ensure that no declaration ever gets into
64 /// the result set twice.
65 llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000066
Fangrui Song050229d2018-11-24 00:14:31 +000067 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000068
Fangrui Song050229d2018-11-24 00:14:31 +000069 /// An entry in the shadow map, which is optimized to store
70 /// a single (declaration, index) mapping (the common case) but
71 /// can also store a list of (declaration, index) mappings.
72 class ShadowMapEntry {
73 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000074
Fangrui Song050229d2018-11-24 00:14:31 +000075 /// Contains either the solitary NamedDecl * or a vector
76 /// of (declaration, index) pairs.
77 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector;
Douglas Gregor05e7ca32009-12-06 20:23:50 +000078
Fangrui Song050229d2018-11-24 00:14:31 +000079 /// When the entry contains a single declaration, this is
80 /// the index associated with that entry.
81 unsigned SingleDeclIndex;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000082
Douglas Gregor3545ff42009-09-21 16:56:56 +000083 public:
Fangrui Song050229d2018-11-24 00:14:31 +000084 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +000085
Fangrui Song050229d2018-11-24 00:14:31 +000086 void Add(const NamedDecl *ND, unsigned Index) {
87 if (DeclOrVector.isNull()) {
88 // 0 - > 1 elements: just set the single element information.
89 DeclOrVector = ND;
90 SingleDeclIndex = Index;
91 return;
92 }
93
94 if (const NamedDecl *PrevND =
95 DeclOrVector.dyn_cast<const NamedDecl *>()) {
96 // 1 -> 2 elements: create the vector of results and push in the
97 // existing declaration.
98 DeclIndexPairVector *Vec = new DeclIndexPairVector;
99 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex));
100 DeclOrVector = Vec;
101 }
102
103 // Add the new element to the end of the vector.
104 DeclOrVector.get<DeclIndexPairVector *>()->push_back(
105 DeclIndexPair(ND, Index));
106 }
107
108 void Destroy() {
109 if (DeclIndexPairVector *Vec =
110 DeclOrVector.dyn_cast<DeclIndexPairVector *>()) {
111 delete Vec;
112 DeclOrVector = ((NamedDecl *)nullptr);
Douglas Gregor05fcf842010-11-02 20:36:02 +0000113 }
114 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000115
Fangrui Song050229d2018-11-24 00:14:31 +0000116 // Iteration.
117 class iterator;
118 iterator begin() const;
119 iterator end() const;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000120 };
Fangrui Song050229d2018-11-24 00:14:31 +0000121
122 /// A mapping from declaration names to the declarations that have
123 /// this name within a particular scope and their index within the list of
124 /// results.
125 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap;
126
127 /// The semantic analysis object for which results are being
128 /// produced.
129 Sema &SemaRef;
130
131 /// The allocator used to allocate new code-completion strings.
132 CodeCompletionAllocator &Allocator;
133
134 CodeCompletionTUInfo &CCTUInfo;
135
136 /// If non-NULL, a filter function used to remove any code-completion
137 /// results that are not desirable.
138 LookupFilter Filter;
139
140 /// Whether we should allow declarations as
141 /// nested-name-specifiers that would otherwise be filtered out.
142 bool AllowNestedNameSpecifiers;
143
144 /// If set, the type that we would prefer our resulting value
145 /// declarations to have.
146 ///
147 /// Closely matching the preferred type gives a boost to a result's
148 /// priority.
149 CanQualType PreferredType;
150
151 /// A list of shadow maps, which is used to model name hiding at
152 /// different levels of, e.g., the inheritance hierarchy.
153 std::list<ShadowMap> ShadowMaps;
154
155 /// If we're potentially referring to a C++ member function, the set
156 /// of qualifiers applied to the object type.
157 Qualifiers ObjectTypeQualifiers;
158
159 /// Whether the \p ObjectTypeQualifiers field is active.
160 bool HasObjectTypeQualifiers;
161
162 /// The selector that we prefer.
163 Selector PreferredSelector;
164
165 /// The completion context in which we are gathering results.
166 CodeCompletionContext CompletionContext;
167
168 /// If we are in an instance method definition, the \@implementation
169 /// object.
170 ObjCImplementationDecl *ObjCImplementation;
171
172 void AdjustResultPriorityForDecl(Result &R);
173
174 void MaybeAddConstructorResults(Result R);
175
176public:
177 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator,
178 CodeCompletionTUInfo &CCTUInfo,
179 const CodeCompletionContext &CompletionContext,
180 LookupFilter Filter = nullptr)
181 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo),
182 Filter(Filter), AllowNestedNameSpecifiers(false),
183 HasObjectTypeQualifiers(false), CompletionContext(CompletionContext),
184 ObjCImplementation(nullptr) {
185 // If this is an Objective-C instance method definition, dig out the
186 // corresponding implementation.
187 switch (CompletionContext.getKind()) {
188 case CodeCompletionContext::CCC_Expression:
189 case CodeCompletionContext::CCC_ObjCMessageReceiver:
190 case CodeCompletionContext::CCC_ParenthesizedExpression:
191 case CodeCompletionContext::CCC_Statement:
192 case CodeCompletionContext::CCC_Recovery:
193 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())
194 if (Method->isInstanceMethod())
195 if (ObjCInterfaceDecl *Interface = Method->getClassInterface())
196 ObjCImplementation = Interface->getImplementation();
197 break;
198
199 default:
200 break;
201 }
202 }
203
204 /// Determine the priority for a reference to the given declaration.
205 unsigned getBasePriority(const NamedDecl *D);
206
207 /// Whether we should include code patterns in the completion
208 /// results.
209 bool includeCodePatterns() const {
210 return SemaRef.CodeCompleter &&
211 SemaRef.CodeCompleter->includeCodePatterns();
212 }
213
214 /// Set the filter used for code-completion results.
215 void setFilter(LookupFilter Filter) { this->Filter = Filter; }
216
217 Result *data() { return Results.empty() ? nullptr : &Results.front(); }
218 unsigned size() const { return Results.size(); }
219 bool empty() const { return Results.empty(); }
220
221 /// Specify the preferred type.
222 void setPreferredType(QualType T) {
223 PreferredType = SemaRef.Context.getCanonicalType(T);
224 }
225
226 /// Set the cv-qualifiers on the object type, for us in filtering
227 /// calls to member functions.
228 ///
229 /// When there are qualifiers in this set, they will be used to filter
230 /// out member functions that aren't available (because there will be a
231 /// cv-qualifier mismatch) or prefer functions with an exact qualifier
232 /// match.
233 void setObjectTypeQualifiers(Qualifiers Quals) {
234 ObjectTypeQualifiers = Quals;
235 HasObjectTypeQualifiers = true;
236 }
237
238 /// Set the preferred selector.
239 ///
240 /// When an Objective-C method declaration result is added, and that
241 /// method's selector matches this preferred selector, we give that method
242 /// a slight priority boost.
243 void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; }
244
245 /// Retrieve the code-completion context for which results are
246 /// being collected.
247 const CodeCompletionContext &getCompletionContext() const {
248 return CompletionContext;
249 }
250
251 /// Specify whether nested-name-specifiers are allowed.
252 void allowNestedNameSpecifiers(bool Allow = true) {
253 AllowNestedNameSpecifiers = Allow;
254 }
255
256 /// Return the semantic analysis object for which we are collecting
257 /// code completion results.
258 Sema &getSema() const { return SemaRef; }
259
260 /// Retrieve the allocator used to allocate code completion strings.
261 CodeCompletionAllocator &getAllocator() const { return Allocator; }
262
263 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; }
264
265 /// Determine whether the given declaration is at all interesting
266 /// as a code-completion result.
267 ///
268 /// \param ND the declaration that we are inspecting.
269 ///
270 /// \param AsNestedNameSpecifier will be set true if this declaration is
271 /// only interesting when it is a nested-name-specifier.
272 bool isInterestingDecl(const NamedDecl *ND,
273 bool &AsNestedNameSpecifier) const;
274
275 /// Check whether the result is hidden by the Hiding declaration.
276 ///
277 /// \returns true if the result is hidden and cannot be found, false if
278 /// the hidden result could still be found. When false, \p R may be
279 /// modified to describe how the result can be found (e.g., via extra
280 /// qualification).
281 bool CheckHiddenResult(Result &R, DeclContext *CurContext,
282 const NamedDecl *Hiding);
283
284 /// Add a new result to this result set (if it isn't already in one
285 /// of the shadow maps), or replace an existing result (for, e.g., a
286 /// redeclaration).
287 ///
288 /// \param R the result to add (if it is unique).
289 ///
290 /// \param CurContext the context in which this result will be named.
291 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr);
292
293 /// Add a new result to this result set, where we already know
294 /// the hiding declaration (if any).
295 ///
296 /// \param R the result to add (if it is unique).
297 ///
298 /// \param CurContext the context in which this result will be named.
299 ///
300 /// \param Hiding the declaration that hides the result.
301 ///
302 /// \param InBaseClass whether the result was found in a base
303 /// class of the searched context.
304 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding,
305 bool InBaseClass);
306
307 /// Add a new non-declaration result to this result set.
308 void AddResult(Result R);
309
310 /// Enter into a new scope.
311 void EnterNewScope();
312
313 /// Exit from the current scope.
314 void ExitScope();
315
316 /// Ignore this declaration, if it is seen again.
317 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); }
318
319 /// Add a visited context.
320 void addVisitedContext(DeclContext *Ctx) {
321 CompletionContext.addVisitedContext(Ctx);
322 }
323
324 /// \name Name lookup predicates
325 ///
326 /// These predicates can be passed to the name lookup functions to filter the
327 /// results of name lookup. All of the predicates have the same type, so that
328 ///
329 //@{
330 bool IsOrdinaryName(const NamedDecl *ND) const;
331 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const;
332 bool IsIntegralConstantValue(const NamedDecl *ND) const;
333 bool IsOrdinaryNonValueName(const NamedDecl *ND) const;
334 bool IsNestedNameSpecifier(const NamedDecl *ND) const;
335 bool IsEnum(const NamedDecl *ND) const;
336 bool IsClassOrStruct(const NamedDecl *ND) const;
337 bool IsUnion(const NamedDecl *ND) const;
338 bool IsNamespace(const NamedDecl *ND) const;
339 bool IsNamespaceOrAlias(const NamedDecl *ND) const;
340 bool IsType(const NamedDecl *ND) const;
341 bool IsMember(const NamedDecl *ND) const;
342 bool IsObjCIvar(const NamedDecl *ND) const;
343 bool IsObjCMessageReceiver(const NamedDecl *ND) const;
344 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const;
345 bool IsObjCCollection(const NamedDecl *ND) const;
346 bool IsImpossibleToSatisfy(const NamedDecl *ND) const;
347 //@}
348};
349} // namespace
Douglas Gregor3545ff42009-09-21 16:56:56 +0000350
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000351class ResultBuilder::ShadowMapEntry::iterator {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000352 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000353 unsigned SingleDeclIndex;
354
355public:
356 typedef DeclIndexPair value_type;
357 typedef value_type reference;
358 typedef std::ptrdiff_t difference_type;
359 typedef std::input_iterator_tag iterator_category;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000360
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000361 class pointer {
362 DeclIndexPair Value;
363
364 public:
Fangrui Song050229d2018-11-24 00:14:31 +0000365 pointer(const DeclIndexPair &Value) : Value(Value) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000366
Fangrui Song050229d2018-11-24 00:14:31 +0000367 const DeclIndexPair *operator->() const { return &Value; }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000368 };
Craig Topperc3ec1492014-05-26 06:22:03 +0000369
370 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000371
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000372 iterator(const NamedDecl *SingleDecl, unsigned Index)
Fangrui Song050229d2018-11-24 00:14:31 +0000373 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000374
375 iterator(const DeclIndexPair *Iterator)
Fangrui Song050229d2018-11-24 00:14:31 +0000376 : DeclOrIterator(Iterator), SingleDeclIndex(0) {}
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000377
378 iterator &operator++() {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000379 if (DeclOrIterator.is<const NamedDecl *>()) {
Craig Topperc3ec1492014-05-26 06:22:03 +0000380 DeclOrIterator = (NamedDecl *)nullptr;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000381 SingleDeclIndex = 0;
382 return *this;
383 }
384
Fangrui Song050229d2018-11-24 00:14:31 +0000385 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000386 ++I;
387 DeclOrIterator = I;
388 return *this;
389 }
390
Chris Lattner9795b392010-09-04 18:12:20 +0000391 /*iterator operator++(int) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000392 iterator tmp(*this);
393 ++(*this);
394 return tmp;
Chris Lattner9795b392010-09-04 18:12:20 +0000395 }*/
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000396
397 reference operator*() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000398 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000399 return reference(ND, SingleDeclIndex);
400
Fangrui Song050229d2018-11-24 00:14:31 +0000401 return *DeclOrIterator.get<const DeclIndexPair *>();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000402 }
403
Fangrui Song050229d2018-11-24 00:14:31 +0000404 pointer operator->() const { return pointer(**this); }
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000405
406 friend bool operator==(const iterator &X, const iterator &Y) {
Fangrui Song050229d2018-11-24 00:14:31 +0000407 return X.DeclOrIterator.getOpaqueValue() ==
408 Y.DeclOrIterator.getOpaqueValue() &&
409 X.SingleDeclIndex == Y.SingleDeclIndex;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000410 }
411
412 friend bool operator!=(const iterator &X, const iterator &Y) {
Douglas Gregor94bb5e82009-12-06 21:27:58 +0000413 return !(X == Y);
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000414 }
415};
416
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000417ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000418ResultBuilder::ShadowMapEntry::begin() const {
419 if (DeclOrVector.isNull())
420 return iterator();
421
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000422 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000423 return iterator(ND, SingleDeclIndex);
424
425 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin());
426}
427
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000428ResultBuilder::ShadowMapEntry::iterator
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000429ResultBuilder::ShadowMapEntry::end() const {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000430 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull())
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000431 return iterator();
432
433 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end());
434}
435
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000436/// Compute the qualification required to get from the current context
Douglas Gregor2af2f672009-09-21 20:12:40 +0000437/// (\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///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000444/// \param TargetContext the context in which the named entity actually
Douglas Gregor2af2f672009-09-21 20:12:40 +0000445/// resides.
446///
447/// \returns a nested name specifier that refers into the target context, or
448/// NULL if no qualification is needed.
449static NestedNameSpecifier *
Fangrui Song050229d2018-11-24 00:14:31 +0000450getRequiredQualification(ASTContext &Context, const DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000451 const DeclContext *TargetContext) {
452 SmallVector<const DeclContext *, 4> TargetParents;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000453
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000454 for (const DeclContext *CommonAncestor = TargetContext;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000455 CommonAncestor && !CommonAncestor->Encloses(CurContext);
456 CommonAncestor = CommonAncestor->getLookupParent()) {
457 if (CommonAncestor->isTransparentContext() ||
458 CommonAncestor->isFunctionOrMethod())
459 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000460
Douglas Gregor2af2f672009-09-21 20:12:40 +0000461 TargetParents.push_back(CommonAncestor);
462 }
Craig Topperc3ec1492014-05-26 06:22:03 +0000463
464 NestedNameSpecifier *Result = nullptr;
Douglas Gregor2af2f672009-09-21 20:12:40 +0000465 while (!TargetParents.empty()) {
Robert Wilhelm25284cc2013-08-23 16:11:15 +0000466 const DeclContext *Parent = TargetParents.pop_back_val();
467
Fangrui Song050229d2018-11-24 00:14:31 +0000468 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) {
Douglas Gregor68762e72010-08-23 21:17:50 +0000469 if (!Namespace->getIdentifier())
470 continue;
471
Douglas Gregor2af2f672009-09-21 20:12:40 +0000472 Result = NestedNameSpecifier::Create(Context, Result, Namespace);
Fangrui Song050229d2018-11-24 00:14:31 +0000473 } else if (const auto *TD = dyn_cast<TagDecl>(Parent))
474 Result = NestedNameSpecifier::Create(
475 Context, Result, false, Context.getTypeDeclType(TD).getTypePtr());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000476 }
Douglas Gregor2af2f672009-09-21 20:12:40 +0000477 return Result;
478}
479
Alp Toker034bbd52014-06-30 01:33:53 +0000480/// Determine whether \p Id is a name reserved for the implementation (C99
481/// 7.1.3, C++ [lib.global.names]).
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000482static bool isReservedName(const IdentifierInfo *Id,
483 bool doubleUnderscoreOnly = false) {
Alp Toker034bbd52014-06-30 01:33:53 +0000484 if (Id->getLength() < 2)
485 return false;
486 const char *Name = Id->getNameStart();
487 return Name[0] == '_' &&
Fangrui Song050229d2018-11-24 00:14:31 +0000488 (Name[1] == '_' ||
489 (Name[1] >= 'A' && Name[1] <= 'Z' && !doubleUnderscoreOnly));
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000490}
491
492// Some declarations have reserved names that we don't want to ever show.
493// Filter out names reserved for the implementation if they come from a
494// system header.
495static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) {
496 const IdentifierInfo *Id = ND->getIdentifier();
497 if (!Id)
498 return false;
499
500 // Ignore reserved names for compiler provided decls.
501 if (isReservedName(Id) && ND->getLocation().isInvalid())
502 return true;
503
504 // For system headers ignore only double-underscore names.
505 // This allows for system headers providing private symbols with a single
506 // underscore.
507 if (isReservedName(Id, /*doubleUnderscoreOnly=*/true) &&
Fangrui Song050229d2018-11-24 00:14:31 +0000508 SemaRef.SourceMgr.isInSystemHeader(
509 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation())))
510 return true;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000511
512 return false;
Alp Toker034bbd52014-06-30 01:33:53 +0000513}
514
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000515bool ResultBuilder::isInterestingDecl(const NamedDecl *ND,
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000516 bool &AsNestedNameSpecifier) const {
517 AsNestedNameSpecifier = false;
518
Richard Smithf2005d32015-12-29 23:34:32 +0000519 auto *Named = ND;
Douglas Gregor7c208612010-01-14 00:20:49 +0000520 ND = ND->getUnderlyingDecl();
Douglas Gregor58acf322009-10-09 22:16:47 +0000521
522 // Skip unnamed entities.
Douglas Gregor7c208612010-01-14 00:20:49 +0000523 if (!ND->getDeclName())
524 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000525
Douglas Gregor3545ff42009-09-21 16:56:56 +0000526 // Friend declarations and declarations introduced due to friends are never
527 // added as results.
Richard Smith6eece292015-01-15 02:27:20 +0000528 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared)
Douglas Gregor7c208612010-01-14 00:20:49 +0000529 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000530
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000531 // Class template (partial) specializations are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000532 if (isa<ClassTemplateSpecializationDecl>(ND) ||
533 isa<ClassTemplatePartialSpecializationDecl>(ND))
534 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000535
Douglas Gregor99fe2ad2009-12-11 17:31:05 +0000536 // Using declarations themselves are never added as results.
Douglas Gregor7c208612010-01-14 00:20:49 +0000537 if (isa<UsingDecl>(ND))
538 return false;
Argyrios Kyrtzidis5d8006d2016-07-01 01:17:02 +0000539
540 if (shouldIgnoreDueToReservedName(ND, SemaRef))
541 return false;
Douglas Gregor2927c0c2010-11-09 03:59:40 +0000542
Douglas Gregor59cab552010-08-16 23:05:20 +0000543 if (Filter == &ResultBuilder::IsNestedNameSpecifier ||
Fangrui Song050229d2018-11-24 00:14:31 +0000544 (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace &&
545 Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr))
Douglas Gregor59cab552010-08-16 23:05:20 +0000546 AsNestedNameSpecifier = true;
547
Douglas Gregor3545ff42009-09-21 16:56:56 +0000548 // Filter out any unwanted results.
Richard Smithf2005d32015-12-29 23:34:32 +0000549 if (Filter && !(this->*Filter)(Named)) {
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000550 // Check whether it is interesting as a nested-name-specifier.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000551 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000552 IsNestedNameSpecifier(ND) &&
553 (Filter != &ResultBuilder::IsMember ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000554 (isa<CXXRecordDecl>(ND) &&
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000555 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) {
556 AsNestedNameSpecifier = true;
557 return true;
558 }
559
Douglas Gregor7c208612010-01-14 00:20:49 +0000560 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000561 }
Douglas Gregor7c208612010-01-14 00:20:49 +0000562 // ... then it must be interesting!
563 return true;
564}
565
Douglas Gregore0717ab2010-01-14 00:41:07 +0000566bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000567 const NamedDecl *Hiding) {
Douglas Gregore0717ab2010-01-14 00:41:07 +0000568 // In C, there is no way to refer to a hidden name.
569 // FIXME: This isn't true; we can find a tag name hidden by an ordinary
570 // name if we introduce the tag type.
David Blaikiebbafb8a2012-03-11 07:00:24 +0000571 if (!SemaRef.getLangOpts().CPlusPlus)
Douglas Gregore0717ab2010-01-14 00:41:07 +0000572 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000573
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000574 const DeclContext *HiddenCtx =
575 R.Declaration->getDeclContext()->getRedeclContext();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000576
Douglas Gregore0717ab2010-01-14 00:41:07 +0000577 // There is no way to qualify a name declared in a function or method.
578 if (HiddenCtx->isFunctionOrMethod())
579 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000580
Sebastian Redl50c68252010-08-31 00:36:30 +0000581 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext())
Douglas Gregore0717ab2010-01-14 00:41:07 +0000582 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000583
Douglas Gregore0717ab2010-01-14 00:41:07 +0000584 // We can refer to the result with the appropriate qualification. Do it.
585 R.Hidden = true;
586 R.QualifierIsInformative = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000587
Douglas Gregore0717ab2010-01-14 00:41:07 +0000588 if (!R.Qualifier)
Fangrui Song050229d2018-11-24 00:14:31 +0000589 R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext,
Douglas Gregore0717ab2010-01-14 00:41:07 +0000590 R.Declaration->getDeclContext());
591 return false;
592}
593
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000594/// A simplified classification of types used to determine whether two
Douglas Gregor95887f92010-07-08 23:20:03 +0000595/// types are "similar enough" when adjusting priorities.
Douglas Gregor6e240332010-08-16 16:18:59 +0000596SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) {
Douglas Gregor95887f92010-07-08 23:20:03 +0000597 switch (T->getTypeClass()) {
598 case Type::Builtin:
599 switch (cast<BuiltinType>(T)->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +0000600 case BuiltinType::Void:
601 return STC_Void;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000602
Fangrui Song050229d2018-11-24 00:14:31 +0000603 case BuiltinType::NullPtr:
604 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000605
Fangrui Song050229d2018-11-24 00:14:31 +0000606 case BuiltinType::Overload:
607 case BuiltinType::Dependent:
608 return STC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000609
Fangrui Song050229d2018-11-24 00:14:31 +0000610 case BuiltinType::ObjCId:
611 case BuiltinType::ObjCClass:
612 case BuiltinType::ObjCSel:
613 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000614
Fangrui Song050229d2018-11-24 00:14:31 +0000615 default:
616 return STC_Arithmetic;
Douglas Gregor95887f92010-07-08 23:20:03 +0000617 }
David Blaikie8a40f702012-01-17 06:56:22 +0000618
Douglas Gregor95887f92010-07-08 23:20:03 +0000619 case Type::Complex:
620 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000621
Douglas Gregor95887f92010-07-08 23:20:03 +0000622 case Type::Pointer:
623 return STC_Pointer;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000624
Douglas Gregor95887f92010-07-08 23:20:03 +0000625 case Type::BlockPointer:
626 return STC_Block;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000627
Douglas Gregor95887f92010-07-08 23:20:03 +0000628 case Type::LValueReference:
629 case Type::RValueReference:
630 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000631
Douglas Gregor95887f92010-07-08 23:20:03 +0000632 case Type::ConstantArray:
633 case Type::IncompleteArray:
634 case Type::VariableArray:
635 case Type::DependentSizedArray:
636 return STC_Array;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000637
Douglas Gregor95887f92010-07-08 23:20:03 +0000638 case Type::DependentSizedExtVector:
639 case Type::Vector:
640 case Type::ExtVector:
641 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000642
Douglas Gregor95887f92010-07-08 23:20:03 +0000643 case Type::FunctionProto:
644 case Type::FunctionNoProto:
645 return STC_Function;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000646
Douglas Gregor95887f92010-07-08 23:20:03 +0000647 case Type::Record:
648 return STC_Record;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000649
Douglas Gregor95887f92010-07-08 23:20:03 +0000650 case Type::Enum:
651 return STC_Arithmetic;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000652
Douglas Gregor95887f92010-07-08 23:20:03 +0000653 case Type::ObjCObject:
654 case Type::ObjCInterface:
655 case Type::ObjCObjectPointer:
656 return STC_ObjectiveC;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000657
Douglas Gregor95887f92010-07-08 23:20:03 +0000658 default:
659 return STC_Other;
660 }
661}
662
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000663/// Get the type that a given expression will have if this declaration
Douglas Gregor95887f92010-07-08 23:20:03 +0000664/// is used as an expression in its "typical" code-completion form.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000665QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) {
George Burgess IV00f70bd2018-03-01 05:43:23 +0000666 ND = ND->getUnderlyingDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000667
Fangrui Song050229d2018-11-24 00:14:31 +0000668 if (const auto *Type = dyn_cast<TypeDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000669 return C.getTypeDeclType(Type);
Fangrui Song050229d2018-11-24 00:14:31 +0000670 if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000671 return C.getObjCInterfaceType(Iface);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000672
Douglas Gregor95887f92010-07-08 23:20:03 +0000673 QualType T;
Alp Tokera2794f92014-01-22 07:29:52 +0000674 if (const FunctionDecl *Function = ND->getAsFunction())
Douglas Gregor603d81b2010-07-13 08:18:22 +0000675 T = Function->getCallResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000676 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND))
Douglas Gregor603d81b2010-07-13 08:18:22 +0000677 T = Method->getSendResultType();
Fangrui Song050229d2018-11-24 00:14:31 +0000678 else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000679 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext()));
Fangrui Song050229d2018-11-24 00:14:31 +0000680 else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000681 T = Property->getType();
Fangrui Song050229d2018-11-24 00:14:31 +0000682 else if (const auto *Value = dyn_cast<ValueDecl>(ND))
Douglas Gregor95887f92010-07-08 23:20:03 +0000683 T = Value->getType();
684 else
685 return QualType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000686
687 // Dig through references, function pointers, and block pointers to
688 // get down to the likely type of an expression when the entity is
689 // used.
690 do {
Fangrui Song050229d2018-11-24 00:14:31 +0000691 if (const auto *Ref = T->getAs<ReferenceType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000692 T = Ref->getPointeeType();
693 continue;
694 }
695
Fangrui Song050229d2018-11-24 00:14:31 +0000696 if (const auto *Pointer = T->getAs<PointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000697 if (Pointer->getPointeeType()->isFunctionType()) {
698 T = Pointer->getPointeeType();
699 continue;
700 }
701
702 break;
703 }
704
Fangrui Song050229d2018-11-24 00:14:31 +0000705 if (const auto *Block = T->getAs<BlockPointerType>()) {
Douglas Gregoraf670a82011-04-14 20:33:34 +0000706 T = Block->getPointeeType();
707 continue;
708 }
709
Fangrui Song050229d2018-11-24 00:14:31 +0000710 if (const auto *Function = T->getAs<FunctionType>()) {
Alp Toker314cc812014-01-25 16:55:45 +0000711 T = Function->getReturnType();
Douglas Gregoraf670a82011-04-14 20:33:34 +0000712 continue;
713 }
714
715 break;
716 } while (true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000717
Douglas Gregoraf670a82011-04-14 20:33:34 +0000718 return T;
Douglas Gregor95887f92010-07-08 23:20:03 +0000719}
720
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000721unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) {
722 if (!ND)
723 return CCP_Unlikely;
724
725 // Context-based decisions.
Richard Smith541b38b2013-09-20 01:15:31 +0000726 const DeclContext *LexicalDC = ND->getLexicalDeclContext();
727 if (LexicalDC->isFunctionOrMethod()) {
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000728 // _cmd is relatively rare
Fangrui Song050229d2018-11-24 00:14:31 +0000729 if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000730 if (ImplicitParam->getIdentifier() &&
731 ImplicitParam->getIdentifier()->isStr("_cmd"))
732 return CCP_ObjC_cmd;
733
734 return CCP_LocalDeclaration;
735 }
Richard Smith541b38b2013-09-20 01:15:31 +0000736
737 const DeclContext *DC = ND->getDeclContext()->getRedeclContext();
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000738 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) {
739 // Explicit destructor calls are very rare.
740 if (isa<CXXDestructorDecl>(ND))
741 return CCP_Unlikely;
742 // Explicit operator and conversion function calls are also very rare.
743 auto DeclNameKind = ND->getDeclName().getNameKind();
744 if (DeclNameKind == DeclarationName::CXXOperatorName ||
745 DeclNameKind == DeclarationName::CXXLiteralOperatorName ||
746 DeclNameKind == DeclarationName::CXXConversionFunctionName)
747 return CCP_Unlikely;
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000748 return CCP_MemberDeclaration;
Ilya Biryukov4e7a6fe2017-09-22 19:07:37 +0000749 }
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000750
751 // Content-based decisions.
752 if (isa<EnumConstantDecl>(ND))
753 return CCP_Constant;
754
Douglas Gregor52e0de42013-01-31 05:03:46 +0000755 // Use CCP_Type for type declarations unless we're in a statement, Objective-C
756 // message receiver, or parenthesized expression context. There, it's as
757 // likely that the user will want to write a type as other declarations.
758 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) &&
759 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement ||
Fangrui Song050229d2018-11-24 00:14:31 +0000760 CompletionContext.getKind() ==
761 CodeCompletionContext::CCC_ObjCMessageReceiver ||
762 CompletionContext.getKind() ==
763 CodeCompletionContext::CCC_ParenthesizedExpression))
Douglas Gregor0a0e2b32013-01-31 04:52:16 +0000764 return CCP_Type;
765
766 return CCP_Declaration;
767}
768
Douglas Gregor50832e02010-09-20 22:39:41 +0000769void ResultBuilder::AdjustResultPriorityForDecl(Result &R) {
770 // If this is an Objective-C method declaration whose selector matches our
771 // preferred selector, give it a priority boost.
772 if (!PreferredSelector.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +0000773 if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration))
Douglas Gregor50832e02010-09-20 22:39:41 +0000774 if (PreferredSelector == Method->getSelector())
775 R.Priority += CCD_SelectorMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000776
Douglas Gregor50832e02010-09-20 22:39:41 +0000777 // If we have a preferred type, adjust the priority for results with exactly-
778 // matching or nearly-matching types.
779 if (!PreferredType.isNull()) {
780 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration);
781 if (!T.isNull()) {
782 CanQualType TC = SemaRef.Context.getCanonicalType(T);
783 // Check for exactly-matching types (modulo qualifiers).
784 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC))
785 R.Priority /= CCF_ExactTypeMatch;
786 // Check for nearly-matching types, based on classification of each.
Fangrui Song050229d2018-11-24 00:14:31 +0000787 else if ((getSimplifiedTypeClass(PreferredType) ==
788 getSimplifiedTypeClass(TC)) &&
Douglas Gregor50832e02010-09-20 22:39:41 +0000789 !(PreferredType->isEnumeralType() && TC->isEnumeralType()))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000790 R.Priority /= CCF_SimilarTypeMatch;
Douglas Gregor50832e02010-09-20 22:39:41 +0000791 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000792 }
Douglas Gregor95887f92010-07-08 23:20:03 +0000793}
794
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +0000795DeclContext::lookup_result getConstructors(ASTContext &Context,
796 const CXXRecordDecl *Record) {
797 QualType RecordTy = Context.getTypeDeclType(Record);
798 DeclarationName ConstructorName =
799 Context.DeclarationNames.getCXXConstructorName(
800 Context.getCanonicalType(RecordTy));
801 return Record->lookup(ConstructorName);
802}
803
Douglas Gregor0212fd72010-09-21 16:06:22 +0000804void ResultBuilder::MaybeAddConstructorResults(Result R) {
David Blaikiebbafb8a2012-03-11 07:00:24 +0000805 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration ||
Douglas Gregor0212fd72010-09-21 16:06:22 +0000806 !CompletionContext.wantConstructorResults())
807 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000808
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000809 const NamedDecl *D = R.Declaration;
Craig Topperc3ec1492014-05-26 06:22:03 +0000810 const CXXRecordDecl *Record = nullptr;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000811 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000812 Record = ClassTemplate->getTemplatedDecl();
813 else if ((Record = dyn_cast<CXXRecordDecl>(D))) {
814 // Skip specializations and partial specializations.
815 if (isa<ClassTemplateSpecializationDecl>(Record))
816 return;
817 } else {
818 // There are no constructors here.
819 return;
820 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000821
Douglas Gregor0212fd72010-09-21 16:06:22 +0000822 Record = Record->getDefinition();
823 if (!Record)
824 return;
825
Fangrui Song050229d2018-11-24 00:14:31 +0000826 for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +0000827 R.Declaration = Ctor;
Douglas Gregor0212fd72010-09-21 16:06:22 +0000828 R.CursorKind = getCursorKindForDecl(R.Declaration);
829 Results.push_back(R);
830 }
831}
832
Sam McCall63c59722018-01-22 20:44:47 +0000833static bool isConstructor(const Decl *ND) {
834 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND))
835 ND = Tmpl->getTemplatedDecl();
836 return isa<CXXConstructorDecl>(ND);
837}
838
Douglas Gregor7c208612010-01-14 00:20:49 +0000839void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) {
840 assert(!ShadowMaps.empty() && "Must enter into a results scope");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000841
Douglas Gregor7c208612010-01-14 00:20:49 +0000842 if (R.Kind != Result::RK_Declaration) {
843 // For non-declaration results, just add the result.
844 Results.push_back(R);
845 return;
846 }
847
848 // Look through using declarations.
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000849 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
850 CodeCompletionResult Result(Using->getTargetDecl(),
851 getBasePriority(Using->getTargetDecl()),
852 R.Qualifier);
853 Result.ShadowDecl = Using;
854 MaybeAddResult(Result, CurContext);
Douglas Gregor7c208612010-01-14 00:20:49 +0000855 return;
856 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000857
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000858 const Decl *CanonDecl = R.Declaration->getCanonicalDecl();
Douglas Gregor7c208612010-01-14 00:20:49 +0000859 unsigned IDNS = CanonDecl->getIdentifierNamespace();
860
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000861 bool AsNestedNameSpecifier = false;
862 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregor7c208612010-01-14 00:20:49 +0000863 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000864
Douglas Gregor0212fd72010-09-21 16:06:22 +0000865 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000866 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000867 return;
868
Douglas Gregor3545ff42009-09-21 16:56:56 +0000869 ShadowMap &SMap = ShadowMaps.back();
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000870 ShadowMapEntry::iterator I, IEnd;
871 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName());
872 if (NamePos != SMap.end()) {
873 I = NamePos->second.begin();
874 IEnd = NamePos->second.end();
875 }
876
877 for (; I != IEnd; ++I) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000878 const NamedDecl *ND = I->first;
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000879 unsigned Index = I->second;
Douglas Gregor3545ff42009-09-21 16:56:56 +0000880 if (ND->getCanonicalDecl() == CanonDecl) {
881 // This is a redeclaration. Always pick the newer declaration.
Douglas Gregor3545ff42009-09-21 16:56:56 +0000882 Results[Index].Declaration = R.Declaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000883
Douglas Gregor3545ff42009-09-21 16:56:56 +0000884 // We're done.
885 return;
886 }
887 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000888
Douglas Gregor3545ff42009-09-21 16:56:56 +0000889 // This is a new declaration in this scope. However, check whether this
890 // declaration name is hidden by a similarly-named declaration in an outer
891 // scope.
892 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end();
893 --SMEnd;
894 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) {
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000895 ShadowMapEntry::iterator I, IEnd;
896 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName());
897 if (NamePos != SM->end()) {
898 I = NamePos->second.begin();
899 IEnd = NamePos->second.end();
900 }
901 for (; I != IEnd; ++I) {
Douglas Gregor3545ff42009-09-21 16:56:56 +0000902 // A tag declaration does not hide a non-tag declaration.
John McCalle87beb22010-04-23 18:46:30 +0000903 if (I->first->hasTagIdentifierNamespace() &&
Richard Smith541b38b2013-09-20 01:15:31 +0000904 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary |
905 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol)))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000906 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000907
Douglas Gregor3545ff42009-09-21 16:56:56 +0000908 // Protocols are in distinct namespaces from everything else.
Fangrui Song050229d2018-11-24 00:14:31 +0000909 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) ||
910 (IDNS & Decl::IDNS_ObjCProtocol)) &&
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000911 I->first->getIdentifierNamespace() != IDNS)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000912 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000913
Douglas Gregor3545ff42009-09-21 16:56:56 +0000914 // The newly-added result is hidden by an entry in the shadow map.
Douglas Gregore0717ab2010-01-14 00:41:07 +0000915 if (CheckHiddenResult(R, CurContext, I->first))
Douglas Gregor3545ff42009-09-21 16:56:56 +0000916 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000917
Douglas Gregor3545ff42009-09-21 16:56:56 +0000918 break;
919 }
920 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000921
Douglas Gregor3545ff42009-09-21 16:56:56 +0000922 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000923 if (!AllDeclsFound.insert(CanonDecl).second)
Douglas Gregor3545ff42009-09-21 16:56:56 +0000924 return;
Douglas Gregorc2cb2e22010-08-27 15:29:55 +0000925
Douglas Gregore412a5a2009-09-23 22:26:46 +0000926 // If the filter is for nested-name-specifiers, then this result starts a
927 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000928 if (AsNestedNameSpecifier) {
Douglas Gregore412a5a2009-09-23 22:26:46 +0000929 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +0000930 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000931 } else
Fangrui Song050229d2018-11-24 00:14:31 +0000932 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000933
Douglas Gregor5bf52692009-09-22 23:15:58 +0000934 // If this result is supposed to have an informative qualifier, add one.
Douglas Gregore412a5a2009-09-23 22:26:46 +0000935 if (R.QualifierIsInformative && !R.Qualifier &&
936 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000937 const DeclContext *Ctx = R.Declaration->getDeclContext();
938 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +0000939 R.Qualifier =
940 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +0000941 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx))
Fangrui Song050229d2018-11-24 00:14:31 +0000942 R.Qualifier = NestedNameSpecifier::Create(
943 SemaRef.Context, nullptr, false,
944 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregor5bf52692009-09-22 23:15:58 +0000945 else
946 R.QualifierIsInformative = false;
947 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000948
Douglas Gregor3545ff42009-09-21 16:56:56 +0000949 // Insert this result into the set of results and into the current shadow
950 // map.
Douglas Gregor05e7ca32009-12-06 20:23:50 +0000951 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size());
Douglas Gregor3545ff42009-09-21 16:56:56 +0000952 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000953
Douglas Gregor0212fd72010-09-21 16:06:22 +0000954 if (!AsNestedNameSpecifier)
955 MaybeAddConstructorResults(R);
Douglas Gregor3545ff42009-09-21 16:56:56 +0000956}
957
Eric Liu4a7cd632018-10-24 12:57:27 +0000958static void setInBaseClass(ResultBuilder::Result &R) {
959 R.Priority += CCD_InBaseClass;
960 R.InBaseClass = true;
961}
962
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000963void ResultBuilder::AddResult(Result R, DeclContext *CurContext,
Douglas Gregor09bbc652010-01-14 15:47:35 +0000964 NamedDecl *Hiding, bool InBaseClass = false) {
Douglas Gregor78a21012010-01-14 16:01:26 +0000965 if (R.Kind != Result::RK_Declaration) {
966 // For non-declaration results, just add the result.
967 Results.push_back(R);
968 return;
969 }
970
Douglas Gregorc580c522010-01-14 01:09:38 +0000971 // Look through using declarations.
Fangrui Song050229d2018-11-24 00:14:31 +0000972 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) {
Kirill Bobyrev47d7f522018-07-11 14:49:49 +0000973 CodeCompletionResult Result(Using->getTargetDecl(),
974 getBasePriority(Using->getTargetDecl()),
975 R.Qualifier);
976 Result.ShadowDecl = Using;
977 AddResult(Result, CurContext, Hiding);
Douglas Gregorc580c522010-01-14 01:09:38 +0000978 return;
979 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000980
Douglas Gregor6ae4c522010-01-14 03:21:49 +0000981 bool AsNestedNameSpecifier = false;
982 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier))
Douglas Gregorc580c522010-01-14 01:09:38 +0000983 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000984
Douglas Gregor0212fd72010-09-21 16:06:22 +0000985 // C++ constructors are never found by name lookup.
Sam McCall63c59722018-01-22 20:44:47 +0000986 if (isConstructor(R.Declaration))
Douglas Gregor0212fd72010-09-21 16:06:22 +0000987 return;
988
Douglas Gregorc580c522010-01-14 01:09:38 +0000989 if (Hiding && CheckHiddenResult(R, CurContext, Hiding))
990 return;
Nick Lewyckyc3921482012-04-03 21:44:08 +0000991
Douglas Gregorc580c522010-01-14 01:09:38 +0000992 // Make sure that any given declaration only shows up in the result set once.
David Blaikie82e95a32014-11-19 07:49:47 +0000993 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second)
Douglas Gregorc580c522010-01-14 01:09:38 +0000994 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +0000995
Douglas Gregorc580c522010-01-14 01:09:38 +0000996 // If the filter is for nested-name-specifiers, then this result starts a
997 // nested-name-specifier.
Douglas Gregora2db7932010-05-26 22:00:08 +0000998 if (AsNestedNameSpecifier) {
Douglas Gregorc580c522010-01-14 01:09:38 +0000999 R.StartsNestedNameSpecifier = true;
Douglas Gregora2db7932010-05-26 22:00:08 +00001000 R.Priority = CCP_NestedNameSpecifier;
Kirill Bobyrev47d7f522018-07-11 14:49:49 +00001001 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier &&
1002 InBaseClass &&
1003 isa<CXXRecordDecl>(
1004 R.Declaration->getDeclContext()->getRedeclContext()))
Douglas Gregor09bbc652010-01-14 15:47:35 +00001005 R.QualifierIsInformative = true;
1006
Douglas Gregorc580c522010-01-14 01:09:38 +00001007 // If this result is supposed to have an informative qualifier, add one.
1008 if (R.QualifierIsInformative && !R.Qualifier &&
1009 !R.StartsNestedNameSpecifier) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001010 const DeclContext *Ctx = R.Declaration->getDeclContext();
Fangrui Song050229d2018-11-24 00:14:31 +00001011 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx))
1012 R.Qualifier =
1013 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace);
1014 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx))
1015 R.Qualifier = NestedNameSpecifier::Create(
1016 SemaRef.Context, nullptr, false,
1017 SemaRef.Context.getTypeDeclType(Tag).getTypePtr());
Douglas Gregorc580c522010-01-14 01:09:38 +00001018 else
1019 R.QualifierIsInformative = false;
1020 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001021
Douglas Gregora2db7932010-05-26 22:00:08 +00001022 // Adjust the priority if this result comes from a base class.
1023 if (InBaseClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00001024 setInBaseClass(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001025
Douglas Gregor50832e02010-09-20 22:39:41 +00001026 AdjustResultPriorityForDecl(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001027
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001028 if (HasObjectTypeQualifiers)
Fangrui Song050229d2018-11-24 00:14:31 +00001029 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration))
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001030 if (Method->isInstance()) {
Mikael Nilsson9d2872d2018-12-13 10:15:27 +00001031 Qualifiers MethodQuals = Method->getTypeQualifiers();
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001032 if (ObjectTypeQualifiers == MethodQuals)
1033 R.Priority += CCD_ObjectQualifierMatch;
1034 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001035 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001036 // qualifiers.
1037 return;
1038 }
1039 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001040
Douglas Gregorc580c522010-01-14 01:09:38 +00001041 // Insert this result into the set of results.
1042 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001043
Douglas Gregor0212fd72010-09-21 16:06:22 +00001044 if (!AsNestedNameSpecifier)
1045 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001046}
1047
Douglas Gregor78a21012010-01-14 16:01:26 +00001048void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001049 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001050 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001051 Results.push_back(R);
1052}
1053
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001054/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001055void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001056
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001057/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001058void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001059 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00001060 EEnd = ShadowMaps.back().end();
1061 E != EEnd; ++E)
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001062 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001063
Douglas Gregor3545ff42009-09-21 16:56:56 +00001064 ShadowMaps.pop_back();
1065}
1066
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001067/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001068/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001069bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001070 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001071
Richard Smith541b38b2013-09-20 01:15:31 +00001072 // If name lookup finds a local extern declaration, then we are in a
1073 // context where it behaves like an ordinary name.
1074 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001075 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001076 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001077 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001078 if (isa<ObjCIvarDecl>(ND))
1079 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001080 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001081
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001082 return ND->getIdentifierNamespace() & IDNS;
1083}
1084
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001085/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001086/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001087bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001088 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001089 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001090 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001091 // Objective-C interfaces names are not filtered by this method because they
1092 // can be used in a class property expression. We can still filter out
1093 // @class declarations though.
1094 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1095 if (!ID->getDefinition())
1096 return false;
1097 }
1098
Richard Smith541b38b2013-09-20 01:15:31 +00001099 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001100 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001101 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001102 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001103 if (isa<ObjCIvarDecl>(ND))
1104 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001105 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001106
Douglas Gregor70febae2010-05-28 00:49:12 +00001107 return ND->getIdentifierNamespace() & IDNS;
1108}
1109
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001110bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001111 if (!IsOrdinaryNonTypeName(ND))
1112 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001113
Fangrui Song050229d2018-11-24 00:14:31 +00001114 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001115 if (VD->getType()->isIntegralOrEnumerationType())
1116 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001117
Douglas Gregor85b50632010-07-28 21:50:18 +00001118 return false;
1119}
1120
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001121/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001122/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001123bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001124 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001125
Richard Smith541b38b2013-09-20 01:15:31 +00001126 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001127 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001128 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001129
Fangrui Song050229d2018-11-24 00:14:31 +00001130 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1131 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001132}
1133
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001134/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001135/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001136bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001137 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001138 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001139 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001140
Douglas Gregor3545ff42009-09-21 16:56:56 +00001141 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1142}
1143
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001144/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001145bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001146 return isa<EnumDecl>(ND);
1147}
1148
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001149/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001150bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001151 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001152 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001153 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001154
1155 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001156 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1157 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1158 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001159
Douglas Gregor3545ff42009-09-21 16:56:56 +00001160 return false;
1161}
1162
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001163/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001164bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001165 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001166 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001167 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001168
Fangrui Song050229d2018-11-24 00:14:31 +00001169 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001170 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001171
Douglas Gregor3545ff42009-09-21 16:56:56 +00001172 return false;
1173}
1174
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001175/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001176bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001177 return isa<NamespaceDecl>(ND);
1178}
1179
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001180/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001181/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001182bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001183 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001184}
1185
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001186/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001187bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001188 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001189 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001190}
1191
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001192/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001193/// "." or "->". Only value declarations, nested name specifiers, and
1194/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001195bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001196 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001197 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001198 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001199}
1200
Douglas Gregora817a192010-05-27 23:06:34 +00001201static bool isObjCReceiverType(ASTContext &C, QualType T) {
1202 T = C.getCanonicalType(T);
1203 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001204 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001205 case Type::ObjCInterface:
1206 case Type::ObjCObjectPointer:
1207 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001208
Douglas Gregora817a192010-05-27 23:06:34 +00001209 case Type::Builtin:
1210 switch (cast<BuiltinType>(T)->getKind()) {
1211 case BuiltinType::ObjCId:
1212 case BuiltinType::ObjCClass:
1213 case BuiltinType::ObjCSel:
1214 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001215
Douglas Gregora817a192010-05-27 23:06:34 +00001216 default:
1217 break;
1218 }
1219 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001220
Douglas Gregora817a192010-05-27 23:06:34 +00001221 default:
1222 break;
1223 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001224
David Blaikiebbafb8a2012-03-11 07:00:24 +00001225 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001226 return false;
1227
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001228 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001229 // particular class type has any conversions to Objective-C types. For now,
1230 // just accept all class types.
1231 return T->isDependentType() || T->isRecordType();
1232}
1233
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001234bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001235 QualType T = getDeclUsageType(SemaRef.Context, ND);
1236 if (T.isNull())
1237 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001238
Douglas Gregora817a192010-05-27 23:06:34 +00001239 T = SemaRef.Context.getBaseElementType(T);
1240 return isObjCReceiverType(SemaRef.Context, T);
1241}
1242
Fangrui Song050229d2018-11-24 00:14:31 +00001243bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1244 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001245 if (IsObjCMessageReceiver(ND))
1246 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001247
Fangrui Song050229d2018-11-24 00:14:31 +00001248 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001249 if (!Var)
1250 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001251
Douglas Gregord8c61782012-02-15 15:34:24 +00001252 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1253}
1254
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001255bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001256 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1257 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001258 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001259
Douglas Gregor68762e72010-08-23 21:17:50 +00001260 QualType T = getDeclUsageType(SemaRef.Context, ND);
1261 if (T.isNull())
1262 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001263
Douglas Gregor68762e72010-08-23 21:17:50 +00001264 T = SemaRef.Context.getBaseElementType(T);
1265 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001266 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001267 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001268}
Douglas Gregora817a192010-05-27 23:06:34 +00001269
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001270bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001271 return false;
1272}
1273
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001274/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001275/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001276bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001277 return isa<ObjCIvarDecl>(ND);
1278}
1279
Douglas Gregorc580c522010-01-14 01:09:38 +00001280namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001281
Fangrui Song050229d2018-11-24 00:14:31 +00001282/// Visible declaration consumer that adds a code-completion result
1283/// for each visible declaration.
1284class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1285 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001286 DeclContext *InitialLookupCtx;
1287 // NamingClass and BaseType are used for access-checking. See
1288 // Sema::IsSimplyAccessible for details.
1289 CXXRecordDecl *NamingClass;
1290 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001291 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001292
Fangrui Song050229d2018-11-24 00:14:31 +00001293public:
1294 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001295 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1296 QualType BaseType = QualType(),
1297 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1298 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1299 FixIts(std::move(FixIts)) {
1300 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1301 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1302 if (BaseType.isNull()) {
1303 auto ThisType = Results.getSema().getCurrentThisType();
1304 if (!ThisType.isNull()) {
1305 assert(ThisType->isPointerType());
1306 BaseType = ThisType->getPointeeType();
1307 if (!NamingClass)
1308 NamingClass = BaseType->getAsCXXRecordDecl();
1309 }
1310 }
1311 this->BaseType = BaseType;
1312 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001313
Fangrui Song050229d2018-11-24 00:14:31 +00001314 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1315 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001316 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001317 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001318 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001319 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001320
Fangrui Song050229d2018-11-24 00:14:31 +00001321 void EnteredContext(DeclContext *Ctx) override {
1322 Results.addVisitedContext(Ctx);
1323 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001324
1325private:
1326 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1327 // Naming class to use for access check. In most cases it was provided
1328 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1329 // for unqualified lookup we fallback to the \p Ctx in which we found the
1330 // member.
1331 auto *NamingClass = this->NamingClass;
1332 QualType BaseType = this->BaseType;
1333 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1334 if (!NamingClass)
1335 NamingClass = Cls;
1336 // When we emulate implicit 'this->' in an unqualified lookup, we might
1337 // end up with an invalid naming class. In that case, we avoid emulating
1338 // 'this->' qualifier to satisfy preconditions of the access checking.
1339 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1340 !NamingClass->isDerivedFrom(Cls)) {
1341 NamingClass = Cls;
1342 BaseType = QualType();
1343 }
1344 } else {
1345 // The decl was found outside the C++ class, so only ObjC access checks
1346 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1347 // out.
1348 NamingClass = nullptr;
1349 BaseType = QualType();
1350 }
1351 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1352 }
Fangrui Song050229d2018-11-24 00:14:31 +00001353};
1354} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001355
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001356/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001357static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001358 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001359 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001360 Results.AddResult(Result("short", CCP_Type));
1361 Results.AddResult(Result("long", CCP_Type));
1362 Results.AddResult(Result("signed", CCP_Type));
1363 Results.AddResult(Result("unsigned", CCP_Type));
1364 Results.AddResult(Result("void", CCP_Type));
1365 Results.AddResult(Result("char", CCP_Type));
1366 Results.AddResult(Result("int", CCP_Type));
1367 Results.AddResult(Result("float", CCP_Type));
1368 Results.AddResult(Result("double", CCP_Type));
1369 Results.AddResult(Result("enum", CCP_Type));
1370 Results.AddResult(Result("struct", CCP_Type));
1371 Results.AddResult(Result("union", CCP_Type));
1372 Results.AddResult(Result("const", CCP_Type));
1373 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001374
Douglas Gregor3545ff42009-09-21 16:56:56 +00001375 if (LangOpts.C99) {
1376 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001377 Results.AddResult(Result("_Complex", CCP_Type));
1378 Results.AddResult(Result("_Imaginary", CCP_Type));
1379 Results.AddResult(Result("_Bool", CCP_Type));
1380 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001381 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001382
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001383 CodeCompletionBuilder Builder(Results.getAllocator(),
1384 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001385 if (LangOpts.CPlusPlus) {
1386 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001387 Results.AddResult(
1388 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001389 Results.AddResult(Result("class", CCP_Type));
1390 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001391
Douglas Gregorf4c33342010-05-28 00:22:41 +00001392 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001393 Builder.AddTypedTextChunk("typename");
1394 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1395 Builder.AddPlaceholderChunk("qualifier");
1396 Builder.AddTextChunk("::");
1397 Builder.AddPlaceholderChunk("name");
1398 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001399
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001400 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001401 Results.AddResult(Result("auto", CCP_Type));
1402 Results.AddResult(Result("char16_t", CCP_Type));
1403 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001404
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001405 Builder.AddTypedTextChunk("decltype");
1406 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1407 Builder.AddPlaceholderChunk("expression");
1408 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1409 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001410 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001411 } else
1412 Results.AddResult(Result("__auto_type", CCP_Type));
1413
Richard Smith7b301e22018-05-24 21:51:52 +00001414 // GNU keywords
1415 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001416 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001417 // Results.AddResult(Result("_Decimal32"));
1418 // Results.AddResult(Result("_Decimal64"));
1419 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001420
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001421 Builder.AddTypedTextChunk("typeof");
1422 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1423 Builder.AddPlaceholderChunk("expression");
1424 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001425
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001426 Builder.AddTypedTextChunk("typeof");
1427 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1428 Builder.AddPlaceholderChunk("type");
1429 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1430 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001431 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001432
1433 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001434 Results.AddResult(Result("_Nonnull", CCP_Type));
1435 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1436 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001437}
1438
John McCallfaf5fb42010-08-26 23:41:50 +00001439static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001440 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001441 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001442 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001443 // Note: we don't suggest either "auto" or "register", because both
1444 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1445 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001446 Results.AddResult(Result("extern"));
1447 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001448
1449 if (LangOpts.CPlusPlus11) {
1450 CodeCompletionAllocator &Allocator = Results.getAllocator();
1451 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1452
1453 // alignas
1454 Builder.AddTypedTextChunk("alignas");
1455 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1456 Builder.AddPlaceholderChunk("expression");
1457 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1458 Results.AddResult(Result(Builder.TakeString()));
1459
1460 Results.AddResult(Result("constexpr"));
1461 Results.AddResult(Result("thread_local"));
1462 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001463}
1464
John McCallfaf5fb42010-08-26 23:41:50 +00001465static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001466 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001467 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001468 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001469 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001470 case Sema::PCC_Class:
1471 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001472 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001473 Results.AddResult(Result("explicit"));
1474 Results.AddResult(Result("friend"));
1475 Results.AddResult(Result("mutable"));
1476 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001477 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001478 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001479
John McCallfaf5fb42010-08-26 23:41:50 +00001480 case Sema::PCC_ObjCInterface:
1481 case Sema::PCC_ObjCImplementation:
1482 case Sema::PCC_Namespace:
1483 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001484 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001485 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001486 break;
1487
John McCallfaf5fb42010-08-26 23:41:50 +00001488 case Sema::PCC_ObjCInstanceVariableList:
1489 case Sema::PCC_Expression:
1490 case Sema::PCC_Statement:
1491 case Sema::PCC_ForInit:
1492 case Sema::PCC_Condition:
1493 case Sema::PCC_RecoveryInFunction:
1494 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001495 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001496 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001497 break;
1498 }
1499}
1500
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001501static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1502static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1503static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001504 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001505static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001506 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001507static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001508 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001509static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001510
Douglas Gregorf4c33342010-05-28 00:22:41 +00001511static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001512 CodeCompletionBuilder Builder(Results.getAllocator(),
1513 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001514 Builder.AddTypedTextChunk("typedef");
1515 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1516 Builder.AddPlaceholderChunk("type");
1517 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1518 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001519 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001520}
1521
John McCallfaf5fb42010-08-26 23:41:50 +00001522static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001523 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001524 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001525 case Sema::PCC_Namespace:
1526 case Sema::PCC_Class:
1527 case Sema::PCC_ObjCInstanceVariableList:
1528 case Sema::PCC_Template:
1529 case Sema::PCC_MemberTemplate:
1530 case Sema::PCC_Statement:
1531 case Sema::PCC_RecoveryInFunction:
1532 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001533 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001534 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001535 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001536
John McCallfaf5fb42010-08-26 23:41:50 +00001537 case Sema::PCC_Expression:
1538 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001539 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001540
Douglas Gregor5e35d592010-09-14 23:59:36 +00001541 case Sema::PCC_ObjCInterface:
1542 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001543 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001544
John McCallfaf5fb42010-08-26 23:41:50 +00001545 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001546 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001547 }
David Blaikie8a40f702012-01-17 06:56:22 +00001548
1549 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001550}
1551
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001552static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1553 const Preprocessor &PP) {
1554 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001555 Policy.AnonymousTagLocations = false;
1556 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001557 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001558 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001559 return Policy;
1560}
1561
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001562/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001563static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1564 return getCompletionPrintingPolicy(S.Context, S.PP);
1565}
1566
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001567/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001568/// that has the appropriate lifetime for code completion.
1569///
1570/// This routine provides a fast path where we provide constant strings for
1571/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001572static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001573 const PrintingPolicy &Policy,
1574 CodeCompletionAllocator &Allocator) {
1575 if (!T.getLocalQualifiers()) {
1576 // Built-in type names are constant strings.
1577 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001578 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001579
Douglas Gregore5c79d52011-10-18 21:20:17 +00001580 // Anonymous tag types are constant strings.
1581 if (const TagType *TagT = dyn_cast<TagType>(T))
1582 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001583 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001584 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001585 case TTK_Struct:
1586 return "struct <anonymous>";
1587 case TTK_Interface:
1588 return "__interface <anonymous>";
1589 case TTK_Class:
1590 return "class <anonymous>";
1591 case TTK_Union:
1592 return "union <anonymous>";
1593 case TTK_Enum:
1594 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001595 }
1596 }
1597 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001598
Douglas Gregore5c79d52011-10-18 21:20:17 +00001599 // Slow path: format the type as a string.
1600 std::string Result;
1601 T.getAsStringInternal(Result, Policy);
1602 return Allocator.CopyString(Result);
1603}
1604
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001605/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001606static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1607 QualType ThisTy = S.getCurrentThisType();
1608 if (ThisTy.isNull())
1609 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001610
Douglas Gregord8c61782012-02-15 15:34:24 +00001611 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001612 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001613 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001614 Builder.AddResultTypeChunk(
1615 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001616 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001617 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001618}
1619
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001620static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1621 ResultBuilder &Results,
1622 const LangOptions &LangOpts) {
1623 if (!LangOpts.CPlusPlus11)
1624 return;
1625
1626 Builder.AddTypedTextChunk("static_assert");
1627 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1628 Builder.AddPlaceholderChunk("expression");
1629 Builder.AddChunk(CodeCompletionString::CK_Comma);
1630 Builder.AddPlaceholderChunk("message");
1631 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1632 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1633}
1634
Fangrui Song050229d2018-11-24 00:14:31 +00001635static void printOverrideString(llvm::raw_ostream &OS,
1636 CodeCompletionString *CCS) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001637 for (const auto &C : *CCS) {
1638 if (C.Kind == CodeCompletionString::CK_Optional)
1639 printOverrideString(OS, C.Optional);
1640 else
1641 OS << C.Text;
1642 // Add a space after return type.
1643 if (C.Kind == CodeCompletionString::CK_ResultType)
1644 OS << ' ';
1645 }
1646}
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001647
1648static void AddOverrideResults(ResultBuilder &Results,
1649 const CodeCompletionContext &CCContext,
1650 CodeCompletionBuilder &Builder) {
1651 Sema &S = Results.getSema();
1652 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1653 // If not inside a class/struct/union return empty.
1654 if (!CR)
1655 return;
1656 // First store overrides within current class.
1657 // These are stored by name to make querying fast in the later step.
1658 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1659 for (auto *Method : CR->methods()) {
1660 if (!Method->isVirtual() || !Method->getIdentifier())
1661 continue;
1662 Overrides[Method->getName()].push_back(Method);
1663 }
1664
1665 for (const auto &Base : CR->bases()) {
1666 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1667 if (!BR)
1668 continue;
1669 for (auto *Method : BR->methods()) {
1670 if (!Method->isVirtual() || !Method->getIdentifier())
1671 continue;
1672 const auto it = Overrides.find(Method->getName());
1673 bool IsOverriden = false;
1674 if (it != Overrides.end()) {
1675 for (auto *MD : it->second) {
1676 // If the method in current body is not an overload of this virtual
1677 // function, then it overrides this one.
1678 if (!S.IsOverload(MD, Method, false)) {
1679 IsOverriden = true;
1680 break;
1681 }
1682 }
1683 }
1684 if (!IsOverriden) {
1685 // Generates a new CodeCompletionResult by taking this function and
1686 // converting it into an override declaration with only one chunk in the
1687 // final CodeCompletionString as a TypedTextChunk.
1688 std::string OverrideSignature;
1689 llvm::raw_string_ostream OS(OverrideSignature);
1690 CodeCompletionResult CCR(Method, 0);
1691 PrintingPolicy Policy =
1692 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1693 auto *CCS = CCR.createCodeCompletionStringForOverride(
1694 S.getPreprocessor(), S.getASTContext(), Builder,
1695 /*IncludeBriefComments=*/false, CCContext, Policy);
1696 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1697 }
1698 }
1699 }
1700}
1701
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001702/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001703static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1704 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001705 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001706 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001707
John McCall276321a2010-08-25 06:19:51 +00001708 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001709 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001710 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001711 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001712 if (Results.includeCodePatterns()) {
1713 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001714 Builder.AddTypedTextChunk("namespace");
1715 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1716 Builder.AddPlaceholderChunk("identifier");
1717 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1718 Builder.AddPlaceholderChunk("declarations");
1719 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1720 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1721 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001722 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001723
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001724 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001725 Builder.AddTypedTextChunk("namespace");
1726 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1727 Builder.AddPlaceholderChunk("name");
1728 Builder.AddChunk(CodeCompletionString::CK_Equal);
1729 Builder.AddPlaceholderChunk("namespace");
1730 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001731
1732 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001733 Builder.AddTypedTextChunk("using");
1734 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1735 Builder.AddTextChunk("namespace");
1736 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1737 Builder.AddPlaceholderChunk("identifier");
1738 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001739
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001740 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001741 Builder.AddTypedTextChunk("asm");
1742 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1743 Builder.AddPlaceholderChunk("string-literal");
1744 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1745 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001746
Douglas Gregorf4c33342010-05-28 00:22:41 +00001747 if (Results.includeCodePatterns()) {
1748 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001749 Builder.AddTypedTextChunk("template");
1750 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1751 Builder.AddPlaceholderChunk("declaration");
1752 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001753 } else {
1754 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001755 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001756 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001757
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001758 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001759 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001760
Douglas Gregorf4c33342010-05-28 00:22:41 +00001761 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001762 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001763
John McCallfaf5fb42010-08-26 23:41:50 +00001764 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001765 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001766 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001767 Builder.AddTypedTextChunk("using");
1768 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1769 Builder.AddPlaceholderChunk("qualifier");
1770 Builder.AddTextChunk("::");
1771 Builder.AddPlaceholderChunk("name");
1772 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001773
Douglas Gregorf4c33342010-05-28 00:22:41 +00001774 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001775 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001776 Builder.AddTypedTextChunk("using");
1777 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1778 Builder.AddTextChunk("typename");
1779 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1780 Builder.AddPlaceholderChunk("qualifier");
1781 Builder.AddTextChunk("::");
1782 Builder.AddPlaceholderChunk("name");
1783 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001784 }
1785
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001786 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1787
John McCallfaf5fb42010-08-26 23:41:50 +00001788 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001789 AddTypedefResult(Results);
1790
Erik Verbruggen6524c052017-10-24 13:46:58 +00001791 bool IsNotInheritanceScope =
1792 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001793 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001794 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001795 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001796 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001797 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001798
1799 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001800 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001801 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001802 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001803 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001804
1805 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001806 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001807 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001808 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001809 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001810
1811 // FIXME: This adds override results only if we are at the first word of
1812 // the declaration/definition. Also call this from other sides to have
1813 // more use-cases.
1814 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
1815 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001816 }
1817 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001818 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001819
John McCallfaf5fb42010-08-26 23:41:50 +00001820 case Sema::PCC_Template:
1821 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001822 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001823 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001824 Builder.AddTypedTextChunk("template");
1825 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1826 Builder.AddPlaceholderChunk("parameters");
1827 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1828 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001829 } else {
1830 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001831 }
1832
David Blaikiebbafb8a2012-03-11 07:00:24 +00001833 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1834 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001835 break;
1836
John McCallfaf5fb42010-08-26 23:41:50 +00001837 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001838 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1839 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1840 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001841 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001842
John McCallfaf5fb42010-08-26 23:41:50 +00001843 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001844 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1845 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1846 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001847 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001848
John McCallfaf5fb42010-08-26 23:41:50 +00001849 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001850 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001851 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001852
John McCallfaf5fb42010-08-26 23:41:50 +00001853 case Sema::PCC_RecoveryInFunction:
1854 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001855 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001856
David Blaikiebbafb8a2012-03-11 07:00:24 +00001857 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1858 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001859 Builder.AddTypedTextChunk("try");
1860 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1861 Builder.AddPlaceholderChunk("statements");
1862 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1863 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1864 Builder.AddTextChunk("catch");
1865 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1866 Builder.AddPlaceholderChunk("declaration");
1867 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1868 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1869 Builder.AddPlaceholderChunk("statements");
1870 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1871 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1872 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001873 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001874 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001875 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001876
Douglas Gregorf64acca2010-05-25 21:41:55 +00001877 if (Results.includeCodePatterns()) {
1878 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001879 Builder.AddTypedTextChunk("if");
1880 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001881 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001882 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001883 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001884 Builder.AddPlaceholderChunk("expression");
1885 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1886 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1887 Builder.AddPlaceholderChunk("statements");
1888 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1889 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1890 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001891
Douglas Gregorf64acca2010-05-25 21:41:55 +00001892 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001893 Builder.AddTypedTextChunk("switch");
1894 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001895 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001896 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001897 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001898 Builder.AddPlaceholderChunk("expression");
1899 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1900 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1901 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1902 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1903 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001904 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001905
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001906 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00001907 if (SemaRef.getCurFunction() &&
1908 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001909 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001910 Builder.AddTypedTextChunk("case");
1911 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1912 Builder.AddPlaceholderChunk("expression");
1913 Builder.AddChunk(CodeCompletionString::CK_Colon);
1914 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001915
1916 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001917 Builder.AddTypedTextChunk("default");
1918 Builder.AddChunk(CodeCompletionString::CK_Colon);
1919 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001920 }
1921
Douglas Gregorf64acca2010-05-25 21:41:55 +00001922 if (Results.includeCodePatterns()) {
1923 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001924 Builder.AddTypedTextChunk("while");
1925 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001926 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001927 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001928 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001929 Builder.AddPlaceholderChunk("expression");
1930 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1931 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1932 Builder.AddPlaceholderChunk("statements");
1933 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1934 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1935 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001936
1937 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001938 Builder.AddTypedTextChunk("do");
1939 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1940 Builder.AddPlaceholderChunk("statements");
1941 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1942 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1943 Builder.AddTextChunk("while");
1944 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1945 Builder.AddPlaceholderChunk("expression");
1946 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1947 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001948
Douglas Gregorf64acca2010-05-25 21:41:55 +00001949 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001950 Builder.AddTypedTextChunk("for");
1951 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001952 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001953 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001954 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001955 Builder.AddPlaceholderChunk("init-expression");
1956 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1957 Builder.AddPlaceholderChunk("condition");
1958 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1959 Builder.AddPlaceholderChunk("inc-expression");
1960 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1961 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1962 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1963 Builder.AddPlaceholderChunk("statements");
1964 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1965 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1966 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001967 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001968
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001969 if (S->getContinueParent()) {
1970 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001971 Builder.AddTypedTextChunk("continue");
1972 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001973 }
1974
1975 if (S->getBreakParent()) {
1976 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001977 Builder.AddTypedTextChunk("break");
1978 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001979 }
1980
1981 // "return expression ;" or "return ;", depending on whether we
1982 // know the function is void or not.
1983 bool isVoid = false;
Fangrui Song050229d2018-11-24 00:14:31 +00001984 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001985 isVoid = Function->getReturnType()->isVoidType();
Fangrui Song050229d2018-11-24 00:14:31 +00001986 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001987 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001988 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00001989 !SemaRef.getCurBlock()->ReturnType.isNull())
1990 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001991 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001992 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001993 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1994 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001995 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001996 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001997
Douglas Gregorf4c33342010-05-28 00:22:41 +00001998 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001999 Builder.AddTypedTextChunk("goto");
2000 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2001 Builder.AddPlaceholderChunk("label");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002002 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002003
Douglas Gregorf4c33342010-05-28 00:22:41 +00002004 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002005 Builder.AddTypedTextChunk("using");
2006 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2007 Builder.AddTextChunk("namespace");
2008 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2009 Builder.AddPlaceholderChunk("identifier");
2010 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002011
2012 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002013 }
Fangrui Song050229d2018-11-24 00:14:31 +00002014 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002015
2016 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002017 case Sema::PCC_ForInit:
2018 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002019 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002020 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002021 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002022
Douglas Gregor5e35d592010-09-14 23:59:36 +00002023 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002024 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002025 CCC == Sema::PCC_ParenthesizedExpression) {
2026 // (__bridge <type>)<expression>
2027 Builder.AddTypedTextChunk("__bridge");
2028 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2029 Builder.AddPlaceholderChunk("type");
2030 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2031 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002032 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002033
2034 // (__bridge_transfer <Objective-C type>)<expression>
2035 Builder.AddTypedTextChunk("__bridge_transfer");
2036 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2037 Builder.AddPlaceholderChunk("Objective-C type");
2038 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2039 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002040 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002041
2042 // (__bridge_retained <CF type>)<expression>
2043 Builder.AddTypedTextChunk("__bridge_retained");
2044 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2045 Builder.AddPlaceholderChunk("CF type");
2046 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2047 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002048 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002049 }
2050 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002051 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002052
John McCallfaf5fb42010-08-26 23:41:50 +00002053 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002054 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002055 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002056 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002057
Douglas Gregore5c79d52011-10-18 21:20:17 +00002058 // true
2059 Builder.AddResultTypeChunk("bool");
2060 Builder.AddTypedTextChunk("true");
2061 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002062
Douglas Gregore5c79d52011-10-18 21:20:17 +00002063 // false
2064 Builder.AddResultTypeChunk("bool");
2065 Builder.AddTypedTextChunk("false");
2066 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002067
David Blaikiebbafb8a2012-03-11 07:00:24 +00002068 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002069 // dynamic_cast < type-id > ( expression )
2070 Builder.AddTypedTextChunk("dynamic_cast");
2071 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2072 Builder.AddPlaceholderChunk("type");
2073 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2074 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2075 Builder.AddPlaceholderChunk("expression");
2076 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002077 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002078 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002079
Douglas Gregorf4c33342010-05-28 00:22:41 +00002080 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002081 Builder.AddTypedTextChunk("static_cast");
2082 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2083 Builder.AddPlaceholderChunk("type");
2084 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2085 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2086 Builder.AddPlaceholderChunk("expression");
2087 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002088 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002089
Douglas Gregorf4c33342010-05-28 00:22:41 +00002090 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002091 Builder.AddTypedTextChunk("reinterpret_cast");
2092 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2093 Builder.AddPlaceholderChunk("type");
2094 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2095 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2096 Builder.AddPlaceholderChunk("expression");
2097 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002098 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002099
Douglas Gregorf4c33342010-05-28 00:22:41 +00002100 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002101 Builder.AddTypedTextChunk("const_cast");
2102 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2103 Builder.AddPlaceholderChunk("type");
2104 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2105 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2106 Builder.AddPlaceholderChunk("expression");
2107 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002108 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002109
David Blaikiebbafb8a2012-03-11 07:00:24 +00002110 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002111 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002112 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002113 Builder.AddTypedTextChunk("typeid");
2114 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2115 Builder.AddPlaceholderChunk("expression-or-type");
2116 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002117 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002118 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002119
Douglas Gregorf4c33342010-05-28 00:22:41 +00002120 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002121 Builder.AddTypedTextChunk("new");
2122 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2123 Builder.AddPlaceholderChunk("type");
2124 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2125 Builder.AddPlaceholderChunk("expressions");
2126 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002127 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002128
Douglas Gregorf4c33342010-05-28 00:22:41 +00002129 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002130 Builder.AddTypedTextChunk("new");
2131 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2132 Builder.AddPlaceholderChunk("type");
2133 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2134 Builder.AddPlaceholderChunk("size");
2135 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2136 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2137 Builder.AddPlaceholderChunk("expressions");
2138 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002139 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002140
Douglas Gregorf4c33342010-05-28 00:22:41 +00002141 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002142 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002143 Builder.AddTypedTextChunk("delete");
2144 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2145 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002146 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002147
Douglas Gregorf4c33342010-05-28 00:22:41 +00002148 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002149 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002150 Builder.AddTypedTextChunk("delete");
2151 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2152 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2153 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2154 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2155 Builder.AddPlaceholderChunk("expression");
2156 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002157
David Blaikiebbafb8a2012-03-11 07:00:24 +00002158 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002159 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002160 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002161 Builder.AddTypedTextChunk("throw");
2162 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2163 Builder.AddPlaceholderChunk("expression");
2164 Results.AddResult(Result(Builder.TakeString()));
2165 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002166
Douglas Gregora2db7932010-05-26 22:00:08 +00002167 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002168
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002169 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002170 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002171 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002172 Builder.AddTypedTextChunk("nullptr");
2173 Results.AddResult(Result(Builder.TakeString()));
2174
2175 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002176 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002177 Builder.AddTypedTextChunk("alignof");
2178 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2179 Builder.AddPlaceholderChunk("type");
2180 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2181 Results.AddResult(Result(Builder.TakeString()));
2182
2183 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002184 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002185 Builder.AddTypedTextChunk("noexcept");
2186 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2187 Builder.AddPlaceholderChunk("expression");
2188 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2189 Results.AddResult(Result(Builder.TakeString()));
2190
2191 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002192 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002193 Builder.AddTypedTextChunk("sizeof...");
2194 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2195 Builder.AddPlaceholderChunk("parameter-pack");
2196 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2197 Results.AddResult(Result(Builder.TakeString()));
2198 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002199 }
2200
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002201 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002202 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002203 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2204 // The interface can be NULL.
2205 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002206 if (ID->getSuperClass()) {
2207 std::string SuperType;
2208 SuperType = ID->getSuperClass()->getNameAsString();
2209 if (Method->isInstanceMethod())
2210 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002211
Douglas Gregore5c79d52011-10-18 21:20:17 +00002212 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2213 Builder.AddTypedTextChunk("super");
2214 Results.AddResult(Result(Builder.TakeString()));
2215 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002216 }
2217
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002218 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002219 }
2220
Jordan Rose58d54722012-06-30 21:33:57 +00002221 if (SemaRef.getLangOpts().C11) {
2222 // _Alignof
2223 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002224 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002225 Builder.AddTypedTextChunk("alignof");
2226 else
2227 Builder.AddTypedTextChunk("_Alignof");
2228 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2229 Builder.AddPlaceholderChunk("type");
2230 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2231 Results.AddResult(Result(Builder.TakeString()));
2232 }
2233
Douglas Gregorf4c33342010-05-28 00:22:41 +00002234 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002235 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002236 Builder.AddTypedTextChunk("sizeof");
2237 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2238 Builder.AddPlaceholderChunk("expression-or-type");
2239 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2240 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002241 break;
2242 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002243
John McCallfaf5fb42010-08-26 23:41:50 +00002244 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002245 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002246 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002247 }
2248
David Blaikiebbafb8a2012-03-11 07:00:24 +00002249 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2250 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002251
David Blaikiebbafb8a2012-03-11 07:00:24 +00002252 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002253 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002254}
2255
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002256/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002257/// type chunk.
2258static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002259 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002260 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002261 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002262 if (!ND)
2263 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002264
2265 // Skip constructors and conversion functions, which have their return types
2266 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002267 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002268 return;
2269
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002270 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002271 QualType T;
2272 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002273 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002274 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002275 if (!BaseType.isNull())
2276 T = Method->getSendResultType(BaseType);
2277 else
2278 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002279 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002280 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002281 T = clang::TypeName::getFullyQualifiedType(T, Context);
2282 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002283 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002284 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002285 if (!BaseType.isNull())
2286 T = Ivar->getUsageType(BaseType);
2287 else
2288 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002289 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002290 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002291 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002292 if (!BaseType.isNull())
2293 T = Property->getUsageType(BaseType);
2294 else
2295 T = Property->getType();
2296 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002297
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002298 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2299 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002300
Fangrui Song050229d2018-11-24 00:14:31 +00002301 Result.AddResultTypeChunk(
2302 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002303}
2304
Richard Smith20e883e2015-04-29 23:20:19 +00002305static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002306 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002307 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002308 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2309 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002310 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002311 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002312 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002313 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002314 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002315 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002316 }
2317}
2318
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002319static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002320 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002321 std::string Result;
2322 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002323 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002324 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002325 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002326 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002327 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002328 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002329 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002330 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002331 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002332 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002333 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002334 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2335 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2336 switch (*nullability) {
2337 case NullabilityKind::NonNull:
2338 Result += "nonnull ";
2339 break;
2340
2341 case NullabilityKind::Nullable:
2342 Result += "nullable ";
2343 break;
2344
2345 case NullabilityKind::Unspecified:
2346 Result += "null_unspecified ";
2347 break;
2348 }
2349 }
2350 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002351 return Result;
2352}
2353
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002354/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002355/// block placeholder.
2356///
2357/// This function ignores things like typedefs and qualifiers in order to
2358/// present the most relevant and accurate block placeholders in code completion
2359/// results.
2360static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2361 FunctionTypeLoc &Block,
2362 FunctionProtoTypeLoc &BlockProto,
2363 bool SuppressBlock = false) {
2364 if (!TSInfo)
2365 return;
2366 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2367 while (true) {
2368 // Look through typedefs.
2369 if (!SuppressBlock) {
2370 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2371 if (TypeSourceInfo *InnerTSInfo =
2372 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2373 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2374 continue;
2375 }
2376 }
2377
2378 // Look through qualified types
2379 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2380 TL = QualifiedTL.getUnqualifiedLoc();
2381 continue;
2382 }
2383
2384 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2385 TL = AttrTL.getModifiedLoc();
2386 continue;
2387 }
2388 }
2389
2390 // Try to get the function prototype behind the block pointer type,
2391 // then we're done.
2392 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2393 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2394 Block = TL.getAs<FunctionTypeLoc>();
2395 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2396 }
2397 break;
2398 }
2399}
2400
Alex Lorenz920ae142016-10-18 10:38:58 +00002401static std::string
2402formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2403 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002404 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002405 bool SuppressBlock = false,
2406 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2407
Fangrui Song050229d2018-11-24 00:14:31 +00002408static std::string
2409FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2410 bool SuppressName = false, bool SuppressBlock = false,
2411 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002412 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2413 if (Param->getType()->isDependentType() ||
2414 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002415 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002416 // containing that parameter's type.
2417 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002418
Douglas Gregor981a0c42010-08-29 19:47:46 +00002419 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002420 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002421
Douglas Gregor86b42682015-06-19 18:27:52 +00002422 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002423 if (ObjCSubsts)
2424 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2425 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002426 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002427 Result =
2428 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002429 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002430 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002431 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002432 } else {
2433 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002434 }
2435 return Result;
2436 }
Alex Lorenza1951202016-10-18 10:35:27 +00002437
Douglas Gregore90dd002010-08-24 16:15:59 +00002438 // The argument for a block pointer parameter is a block literal with
2439 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002440 FunctionTypeLoc Block;
2441 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002442 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2443 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002444 // Try to retrieve the block type information from the property if this is a
2445 // parameter in a setter.
2446 if (!Block && ObjCMethodParam &&
2447 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2448 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2449 ->findPropertyDecl(/*CheckOverrides=*/false))
2450 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2451 SuppressBlock);
2452 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002453
2454 if (!Block) {
2455 // We were unable to find a FunctionProtoTypeLoc with parameter names
2456 // for the block; just use the parameter type as a placeholder.
2457 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002458 if (!ObjCMethodParam && Param->getIdentifier())
2459 Result = Param->getIdentifier()->getName();
2460
Douglas Gregor86b42682015-06-19 18:27:52 +00002461 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002462
Douglas Gregore90dd002010-08-24 16:15:59 +00002463 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002464 Result = Type.getAsString(Policy);
2465 std::string Quals =
2466 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2467 if (!Quals.empty())
2468 Result = "(" + Quals + " " + Result + ")";
2469 if (Result.back() != ')')
2470 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002471 if (Param->getIdentifier())
2472 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002473 } else {
2474 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002475 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002476
Douglas Gregore90dd002010-08-24 16:15:59 +00002477 return Result;
2478 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002479
Douglas Gregore90dd002010-08-24 16:15:59 +00002480 // We have the function prototype behind the block pointer type, as it was
2481 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002482 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2483 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002484 ObjCSubsts);
2485}
2486
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002487/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002488/// declaration.
2489///
2490/// \param BlockDecl A declaration with an Objective-C block type.
2491///
2492/// \param Block The most relevant type location for that block type.
2493///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002494/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002495/// declaration is included in the resulting string.
2496static std::string
2497formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2498 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002499 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002500 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002501 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002502 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002503 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002504 ResultType =
2505 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2506 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002507 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002508 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002509
2510 // Format the parameter list.
2511 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002512 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002513 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002514 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002515 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002516 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002517 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002518 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002519 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002520 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002521 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002522 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002523 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002524 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002525
David Blaikie6adc78e2013-02-18 22:06:02 +00002526 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002527 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002528 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002529 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002530 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002531
Douglas Gregord793e7c2011-10-18 04:23:19 +00002532 if (SuppressBlock) {
2533 // Format as a parameter.
2534 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002535 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002536 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002537 Result += ")";
2538 Result += Params;
2539 } else {
2540 // Format as a block literal argument.
2541 Result = '^' + Result;
2542 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002543
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002544 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002545 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002546 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002547
Douglas Gregore90dd002010-08-24 16:15:59 +00002548 return Result;
2549}
2550
Erik Verbruggen11338c52017-07-19 10:45:40 +00002551static std::string GetDefaultValueString(const ParmVarDecl *Param,
2552 const SourceManager &SM,
2553 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002554 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002555 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2556 bool Invalid = CharSrcRange.isInvalid();
2557 if (Invalid)
2558 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002559 StringRef srcText =
2560 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002561 if (Invalid)
2562 return "";
2563
2564 if (srcText.empty() || srcText == "=") {
2565 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002566 // This happens if the code is incorrect (for example class is forward
2567 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002568 return "";
2569 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002570 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002571 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2572 // this value always has (or always does not have) '=' in front of it
2573 if (DefValue.at(0) != '=') {
2574 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002575 // Lexer returns built-in types values without '=' and user-defined types
2576 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002577 return " = " + DefValue;
2578 }
2579 return " " + DefValue;
2580}
2581
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002582/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002583static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002584 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002585 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002586 CodeCompletionBuilder &Result,
2587 unsigned Start = 0,
2588 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002589 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002590
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002591 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002592 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002593
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002594 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002595 // When we see an optional default argument, put that argument and
2596 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002597 CodeCompletionBuilder Opt(Result.getAllocator(),
2598 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002599 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002600 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002601 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002602 Result.AddOptionalChunk(Opt.TakeString());
2603 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002604 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002605
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002606 if (FirstParameter)
2607 FirstParameter = false;
2608 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002609 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002610
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002611 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002612
Douglas Gregor3545ff42009-09-21 16:56:56 +00002613 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002614 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002615 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002616 PlaceholderStr +=
2617 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002618
Douglas Gregor400f5972010-08-31 05:13:43 +00002619 if (Function->isVariadic() && P == N - 1)
2620 PlaceholderStr += ", ...";
2621
Douglas Gregor3545ff42009-09-21 16:56:56 +00002622 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002623 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002624 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002625 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002626
Fangrui Song050229d2018-11-24 00:14:31 +00002627 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002628 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002629 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002630 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002631
Richard Smith20e883e2015-04-29 23:20:19 +00002632 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002633 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002634}
2635
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002636/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002637static void AddTemplateParameterChunks(
2638 ASTContext &Context, const PrintingPolicy &Policy,
2639 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2640 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002641 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002642
2643 // Prefer to take the template parameter names from the first declaration of
2644 // the template.
2645 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2646
Douglas Gregor3545ff42009-09-21 16:56:56 +00002647 TemplateParameterList *Params = Template->getTemplateParameters();
2648 TemplateParameterList::iterator PEnd = Params->end();
2649 if (MaxParameters)
2650 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002651 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2652 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002653 bool HasDefaultArg = false;
2654 std::string PlaceholderStr;
2655 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2656 if (TTP->wasDeclaredWithTypename())
2657 PlaceholderStr = "typename";
2658 else
2659 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002660
Douglas Gregor3545ff42009-09-21 16:56:56 +00002661 if (TTP->getIdentifier()) {
2662 PlaceholderStr += ' ';
2663 PlaceholderStr += TTP->getIdentifier()->getName();
2664 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002665
Douglas Gregor3545ff42009-09-21 16:56:56 +00002666 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00002667 } else if (NonTypeTemplateParmDecl *NTTP =
2668 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002669 if (NTTP->getIdentifier())
2670 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002671 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002672 HasDefaultArg = NTTP->hasDefaultArgument();
2673 } else {
2674 assert(isa<TemplateTemplateParmDecl>(*P));
2675 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002676
Douglas Gregor3545ff42009-09-21 16:56:56 +00002677 // Since putting the template argument list into the placeholder would
2678 // be very, very long, we just use an abbreviation.
2679 PlaceholderStr = "template<...> class";
2680 if (TTP->getIdentifier()) {
2681 PlaceholderStr += ' ';
2682 PlaceholderStr += TTP->getIdentifier()->getName();
2683 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002684
Douglas Gregor3545ff42009-09-21 16:56:56 +00002685 HasDefaultArg = TTP->hasDefaultArgument();
2686 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002687
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002688 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002689 // When we see an optional default argument, put that argument and
2690 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002691 CodeCompletionBuilder Opt(Result.getAllocator(),
2692 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002693 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002694 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002695 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002696 P - Params->begin(), true);
2697 Result.AddOptionalChunk(Opt.TakeString());
2698 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002699 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002700
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002701 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002702
Douglas Gregor3545ff42009-09-21 16:56:56 +00002703 if (FirstParameter)
2704 FirstParameter = false;
2705 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002706 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002707
Douglas Gregor3545ff42009-09-21 16:56:56 +00002708 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002709 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002710 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002711 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002712}
2713
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002714/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002715/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00002716static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2717 NestedNameSpecifier *Qualifier,
2718 bool QualifierIsInformative,
2719 ASTContext &Context,
2720 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002721 if (!Qualifier)
2722 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002723
Douglas Gregorf2510672009-09-21 19:57:38 +00002724 std::string PrintedNNS;
2725 {
2726 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002727 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002728 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002729 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002730 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002731 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002732 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002733}
2734
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002735static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002736AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002737 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00002738 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Douglas Gregor0f622362009-12-11 18:44:16 +00002739 if (!Proto || !Proto->getTypeQuals())
2740 return;
2741
Douglas Gregor304f9b02011-02-01 21:15:40 +00002742 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002743
Douglas Gregor304f9b02011-02-01 21:15:40 +00002744 // Handle single qualifiers without copying
Mikael Nilsson9d2872d2018-12-13 10:15:27 +00002745 if (Proto->getTypeQuals().hasOnlyConst()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002746 Result.AddInformativeChunk(" const");
2747 return;
2748 }
2749
Mikael Nilsson9d2872d2018-12-13 10:15:27 +00002750 if (Proto->getTypeQuals().hasOnlyVolatile()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002751 Result.AddInformativeChunk(" volatile");
2752 return;
2753 }
2754
Mikael Nilsson9d2872d2018-12-13 10:15:27 +00002755 if (Proto->getTypeQuals().hasOnlyRestrict()) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002756 Result.AddInformativeChunk(" restrict");
2757 return;
2758 }
2759
2760 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002761 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002762 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002763 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002764 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002765 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002766 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002767 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002768 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002769}
2770
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002771/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002772static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002773 const NamedDecl *ND,
2774 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002775 DeclarationName Name = ND->getDeclName();
2776 if (!Name)
2777 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002778
Douglas Gregor0212fd72010-09-21 16:06:22 +00002779 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00002780 case DeclarationName::CXXOperatorName: {
2781 const char *OperatorName = nullptr;
2782 switch (Name.getCXXOverloadedOperator()) {
2783 case OO_None:
2784 case OO_Conditional:
2785 case NUM_OVERLOADED_OPERATORS:
2786 OperatorName = "operator";
2787 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002788
Fangrui Song050229d2018-11-24 00:14:31 +00002789#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
2790 case OO_##Name: \
2791 OperatorName = "operator" Spelling; \
2792 break;
2793#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00002794#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002795
Fangrui Song050229d2018-11-24 00:14:31 +00002796 case OO_New:
2797 OperatorName = "operator new";
2798 break;
2799 case OO_Delete:
2800 OperatorName = "operator delete";
2801 break;
2802 case OO_Array_New:
2803 OperatorName = "operator new[]";
2804 break;
2805 case OO_Array_Delete:
2806 OperatorName = "operator delete[]";
2807 break;
2808 case OO_Call:
2809 OperatorName = "operator()";
2810 break;
2811 case OO_Subscript:
2812 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00002813 break;
2814 }
Fangrui Song050229d2018-11-24 00:14:31 +00002815 Result.AddTypedTextChunk(OperatorName);
2816 break;
2817 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002818
Douglas Gregor0212fd72010-09-21 16:06:22 +00002819 case DeclarationName::Identifier:
2820 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002821 case DeclarationName::CXXDestructorName:
2822 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002823 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002824 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002825 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002826
Richard Smith35845152017-02-07 01:37:30 +00002827 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002828 case DeclarationName::CXXUsingDirective:
2829 case DeclarationName::ObjCZeroArgSelector:
2830 case DeclarationName::ObjCOneArgSelector:
2831 case DeclarationName::ObjCMultiArgSelector:
2832 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002833
Douglas Gregor0212fd72010-09-21 16:06:22 +00002834 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002835 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002836 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00002837 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00002838 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00002839 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00002840 Record = InjectedTy->getDecl();
2841 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002842 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002843 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002844 break;
2845 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002846
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002847 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002848 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002849 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002850 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002851 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002852 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002853 }
2854 break;
2855 }
2856 }
2857}
2858
Fangrui Song050229d2018-11-24 00:14:31 +00002859CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
2860 Sema &S, const CodeCompletionContext &CCContext,
2861 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
2862 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002863 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2864 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002865}
2866
Eric Liu00f43c92018-07-06 09:43:57 +00002867CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
2868 Preprocessor &PP, CodeCompletionAllocator &Allocator,
2869 CodeCompletionTUInfo &CCTUInfo) {
2870 assert(Kind == RK_Macro);
2871 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
2872 const MacroInfo *MI = PP.getMacroInfo(Macro);
2873 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
2874
2875 if (!MI || !MI->isFunctionLike())
2876 return Result.TakeString();
2877
2878 // Format a function-like macro with placeholders for the arguments.
2879 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2880 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
2881
2882 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2883 if (MI->isC99Varargs()) {
2884 --AEnd;
2885
2886 if (A == AEnd) {
2887 Result.AddPlaceholderChunk("...");
2888 }
2889 }
2890
2891 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2892 if (A != MI->param_begin())
2893 Result.AddChunk(CodeCompletionString::CK_Comma);
2894
2895 if (MI->isVariadic() && (A + 1) == AEnd) {
2896 SmallString<32> Arg = (*A)->getName();
2897 if (MI->isC99Varargs())
2898 Arg += ", ...";
2899 else
2900 Arg += "...";
2901 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
2902 break;
2903 }
2904
2905 // Non-variadic macros are simple.
2906 Result.AddPlaceholderChunk(
2907 Result.getAllocator().CopyString((*A)->getName()));
2908 }
2909 Result.AddChunk(CodeCompletionString::CK_RightParen);
2910 return Result.TakeString();
2911}
2912
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002913/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002914/// result.
2915///
2916/// \returns Either a new, heap-allocated code completion string describing
2917/// how to use this result, or NULL to indicate that the string or name of the
2918/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00002919CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
2920 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
2921 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
2922 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00002923 if (Kind == RK_Macro)
2924 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
2925
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002926 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002927
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002928 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002929 if (Kind == RK_Pattern) {
2930 Pattern->Priority = Priority;
2931 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002932
Douglas Gregor78254c82012-03-27 23:34:16 +00002933 if (Declaration) {
2934 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002935 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002936 if (const RawComment *RC =
2937 getPatternCompletionComment(Ctx, Declaration)) {
2938 Result.addBriefComment(RC->getBriefText(Ctx));
2939 Pattern->BriefComment = Result.getBriefComment();
2940 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002941 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002942
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002943 return Pattern;
2944 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002945
Douglas Gregorf09935f2009-12-01 05:55:20 +00002946 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002947 Result.AddTypedTextChunk(Keyword);
2948 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002949 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00002950 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00002951 return createCodeCompletionStringForDecl(
2952 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002953}
2954
2955CodeCompletionString *
2956CodeCompletionResult::createCodeCompletionStringForOverride(
2957 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2958 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2959 PrintingPolicy &Policy) {
2960 std::string OverrideSignature;
2961 llvm::raw_string_ostream OS(OverrideSignature);
2962 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
2963 /*IncludeBriefComments=*/false,
2964 CCContext, Policy);
2965 printOverrideString(OS, CCS);
2966 OS << " override";
2967 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
2968 return Result.TakeString();
2969}
2970
2971CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
2972 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2973 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2974 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002975 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002976 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002977
2978 if (IncludeBriefComments) {
2979 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002980 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002981 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002982 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002983 }
2984
Douglas Gregor9eb77012009-11-07 00:00:49 +00002985 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002986 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002987 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002988 Result.AddTextChunk("::");
2989 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002990 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002991
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002992 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2993 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002994
Douglas Gregorc3425b12015-07-07 06:20:19 +00002995 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002996
Fangrui Song050229d2018-11-24 00:14:31 +00002997 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002998 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002999 Ctx, Policy);
3000 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003001 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003002 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003003 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003004 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003005 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003006 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003007
Fangrui Song050229d2018-11-24 00:14:31 +00003008 if (const FunctionTemplateDecl *FunTmpl =
3009 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003010 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003011 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003012 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003013 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003014
Douglas Gregor3545ff42009-09-21 16:56:56 +00003015 // Figure out which template parameters are deduced (or have default
3016 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003017 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003018 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003019 unsigned LastDeducibleArgument;
3020 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3021 --LastDeducibleArgument) {
3022 if (!Deduced[LastDeducibleArgument - 1]) {
3023 // C++0x: Figure out if the template argument has a default. If so,
3024 // the user doesn't need to type this argument.
3025 // FIXME: We need to abstract template parameters better!
3026 bool HasDefaultArg = false;
3027 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003028 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003029 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3030 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003031 else if (NonTypeTemplateParmDecl *NTTP =
3032 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003033 HasDefaultArg = NTTP->hasDefaultArgument();
3034 else {
3035 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003036 HasDefaultArg =
3037 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003038 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003039
Douglas Gregor3545ff42009-09-21 16:56:56 +00003040 if (!HasDefaultArg)
3041 break;
3042 }
3043 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003044
Douglas Gregor3545ff42009-09-21 16:56:56 +00003045 if (LastDeducibleArgument) {
3046 // Some of the function template arguments cannot be deduced from a
3047 // function call, so we introduce an explicit template argument list
3048 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003049 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003050 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003051 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003052 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003053 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003054
Douglas Gregor3545ff42009-09-21 16:56:56 +00003055 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003056 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003057 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003058 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003059 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003060 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003061 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003062
Fangrui Song050229d2018-11-24 00:14:31 +00003063 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003064 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003065 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003066 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003067 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003068 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003069 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003070 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003071 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003072 }
Fangrui Song050229d2018-11-24 00:14:31 +00003073 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003074 Selector Sel = Method->getSelector();
3075 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003076 Result.AddTypedTextChunk(
3077 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003078 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003079 }
3080
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003081 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003082 SelName += ':';
3083 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003084 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003085 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003086 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003087
Douglas Gregor1b605f72009-11-19 01:08:35 +00003088 // If there is only one parameter, and we're past it, add an empty
3089 // typed-text chunk since there is nothing to type.
3090 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003091 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003092 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003093 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003094 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003095 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003096 P != PEnd; (void)++P, ++Idx) {
3097 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003098 std::string Keyword;
3099 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003100 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003101 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003102 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003103 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003104 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003105 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003106 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003107 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003108 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003109
Douglas Gregor1b605f72009-11-19 01:08:35 +00003110 // If we're before the starting parameter, skip the placeholder.
3111 if (Idx < StartParameter)
3112 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003113
3114 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003115 QualType ParamType = (*P)->getType();
3116 Optional<ArrayRef<QualType>> ObjCSubsts;
3117 if (!CCContext.getBaseType().isNull())
3118 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3119
3120 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3121 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003122 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003123 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003124 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003125 ParamType = ParamType.substObjCTypeArgs(
3126 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003127 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003128 ParamType);
3129 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003130 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003131 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003132 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003133 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003134
Douglas Gregor400f5972010-08-31 05:13:43 +00003135 if (Method->isVariadic() && (P + 1) == PEnd)
3136 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003137
Douglas Gregor95887f92010-07-08 23:20:03 +00003138 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003139 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003140 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003141 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003142 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003143 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003144 }
3145
Douglas Gregor04c5f972009-12-23 00:21:46 +00003146 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003147 if (Method->param_size() == 0) {
3148 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003149 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003150 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003151 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003152 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003153 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003154 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003155
Richard Smith20e883e2015-04-29 23:20:19 +00003156 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003157 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003158
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003159 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003160 }
3161
Douglas Gregorf09935f2009-12-01 05:55:20 +00003162 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003163 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003164 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003165
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003166 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003167 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003168 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003169}
3170
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003171const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3172 const NamedDecl *ND) {
3173 if (!ND)
3174 return nullptr;
3175 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3176 return RC;
3177
3178 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003179 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003180 if (!M)
3181 return nullptr;
3182 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3183 if (!PDecl)
3184 return nullptr;
3185
3186 return Ctx.getRawCommentForAnyRedecl(PDecl);
3187}
3188
3189const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3190 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003191 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003192 if (!M || !M->isPropertyAccessor())
3193 return nullptr;
3194
3195 // Provide code completion comment for self.GetterName where
3196 // GetterName is the getter method for a property with name
3197 // different from the property name (declared via a property
3198 // getter attribute.
3199 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3200 if (!PDecl)
3201 return nullptr;
3202 if (PDecl->getGetterName() == M->getSelector() &&
3203 PDecl->getIdentifier() != M->getIdentifier()) {
3204 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3205 return RC;
3206 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3207 return RC;
3208 }
3209 return nullptr;
3210}
3211
3212const RawComment *clang::getParameterComment(
3213 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003214 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003215 auto FDecl = Result.getFunction();
3216 if (!FDecl)
3217 return nullptr;
3218 if (ArgIndex < FDecl->getNumParams())
3219 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3220 return nullptr;
3221}
3222
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003223/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003224/// string.
3225static void AddOverloadParameterChunks(ASTContext &Context,
3226 const PrintingPolicy &Policy,
3227 const FunctionDecl *Function,
3228 const FunctionProtoType *Prototype,
3229 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003230 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003231 bool InOptional = false) {
3232 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003233 unsigned NumParams =
3234 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003235
3236 for (unsigned P = Start; P != NumParams; ++P) {
3237 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3238 // When we see an optional default argument, put that argument and
3239 // the remaining default arguments into a new, optional string.
3240 CodeCompletionBuilder Opt(Result.getAllocator(),
3241 Result.getCodeCompletionTUInfo());
3242 if (!FirstParameter)
3243 Opt.AddChunk(CodeCompletionString::CK_Comma);
3244 // Optional sections are nested.
3245 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3246 CurrentArg, P, /*InOptional=*/true);
3247 Result.AddOptionalChunk(Opt.TakeString());
3248 return;
3249 }
3250
3251 if (FirstParameter)
3252 FirstParameter = false;
3253 else
3254 Result.AddChunk(CodeCompletionString::CK_Comma);
3255
3256 InOptional = false;
3257
3258 // Format the placeholder string.
3259 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003260 if (Function) {
3261 const ParmVarDecl *Param = Function->getParamDecl(P);
3262 Placeholder = FormatFunctionParameter(Policy, Param);
3263 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003264 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3265 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003266 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003267 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003268 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003269
3270 if (P == CurrentArg)
3271 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003272 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003273 else
3274 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3275 }
3276
3277 if (Prototype && Prototype->isVariadic()) {
3278 CodeCompletionBuilder Opt(Result.getAllocator(),
3279 Result.getCodeCompletionTUInfo());
3280 if (!FirstParameter)
3281 Opt.AddChunk(CodeCompletionString::CK_Comma);
3282
3283 if (CurrentArg < NumParams)
3284 Opt.AddPlaceholderChunk("...");
3285 else
3286 Opt.AddCurrentParameterChunk("...");
3287
3288 Result.AddOptionalChunk(Opt.TakeString());
3289 }
3290}
3291
Douglas Gregorf0f51982009-09-23 00:34:09 +00003292CodeCompletionString *
3293CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003294 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3295 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003296 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003297
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003298 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003299 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3300 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003301 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003302 const FunctionProtoType *Proto =
3303 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003304 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003305 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003306 // highlighted ellipsis.
3307 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003308 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003309 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003310 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3311 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3312 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003313 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003314 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003315
3316 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003317 if (IncludeBriefComments) {
3318 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003319 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003320 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003321 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003322 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003323 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003324 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003325 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003326 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003327 }
Alp Toker314cc812014-01-25 16:55:45 +00003328
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003329 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003330 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3331 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003332 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003333
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003334 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003335}
3336
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003337unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003338 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003339 bool PreferredTypeIsPointer) {
3340 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003341
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003342 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003343 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003344 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003345 Priority = CCP_Constant;
3346 if (PreferredTypeIsPointer)
3347 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003348 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003349 // Treat "YES", "NO", "true", and "false" as constants.
3350 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3351 MacroName.equals("true") || MacroName.equals("false"))
3352 Priority = CCP_Constant;
3353 // Treat "bool" as a type.
3354 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003355 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003356
Douglas Gregor6e240332010-08-16 16:18:59 +00003357 return Priority;
3358}
3359
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003360CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003361 if (!D)
3362 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003363
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003364 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003365 case Decl::Enum:
3366 return CXCursor_EnumDecl;
3367 case Decl::EnumConstant:
3368 return CXCursor_EnumConstantDecl;
3369 case Decl::Field:
3370 return CXCursor_FieldDecl;
3371 case Decl::Function:
3372 return CXCursor_FunctionDecl;
3373 case Decl::ObjCCategory:
3374 return CXCursor_ObjCCategoryDecl;
3375 case Decl::ObjCCategoryImpl:
3376 return CXCursor_ObjCCategoryImplDecl;
3377 case Decl::ObjCImplementation:
3378 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003379
Fangrui Song050229d2018-11-24 00:14:31 +00003380 case Decl::ObjCInterface:
3381 return CXCursor_ObjCInterfaceDecl;
3382 case Decl::ObjCIvar:
3383 return CXCursor_ObjCIvarDecl;
3384 case Decl::ObjCMethod:
3385 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3386 ? CXCursor_ObjCInstanceMethodDecl
3387 : CXCursor_ObjCClassMethodDecl;
3388 case Decl::CXXMethod:
3389 return CXCursor_CXXMethod;
3390 case Decl::CXXConstructor:
3391 return CXCursor_Constructor;
3392 case Decl::CXXDestructor:
3393 return CXCursor_Destructor;
3394 case Decl::CXXConversion:
3395 return CXCursor_ConversionFunction;
3396 case Decl::ObjCProperty:
3397 return CXCursor_ObjCPropertyDecl;
3398 case Decl::ObjCProtocol:
3399 return CXCursor_ObjCProtocolDecl;
3400 case Decl::ParmVar:
3401 return CXCursor_ParmDecl;
3402 case Decl::Typedef:
3403 return CXCursor_TypedefDecl;
3404 case Decl::TypeAlias:
3405 return CXCursor_TypeAliasDecl;
3406 case Decl::TypeAliasTemplate:
3407 return CXCursor_TypeAliasTemplateDecl;
3408 case Decl::Var:
3409 return CXCursor_VarDecl;
3410 case Decl::Namespace:
3411 return CXCursor_Namespace;
3412 case Decl::NamespaceAlias:
3413 return CXCursor_NamespaceAlias;
3414 case Decl::TemplateTypeParm:
3415 return CXCursor_TemplateTypeParameter;
3416 case Decl::NonTypeTemplateParm:
3417 return CXCursor_NonTypeTemplateParameter;
3418 case Decl::TemplateTemplateParm:
3419 return CXCursor_TemplateTemplateParameter;
3420 case Decl::FunctionTemplate:
3421 return CXCursor_FunctionTemplate;
3422 case Decl::ClassTemplate:
3423 return CXCursor_ClassTemplate;
3424 case Decl::AccessSpec:
3425 return CXCursor_CXXAccessSpecifier;
3426 case Decl::ClassTemplatePartialSpecialization:
3427 return CXCursor_ClassTemplatePartialSpecialization;
3428 case Decl::UsingDirective:
3429 return CXCursor_UsingDirective;
3430 case Decl::StaticAssert:
3431 return CXCursor_StaticAssert;
3432 case Decl::Friend:
3433 return CXCursor_FriendDecl;
3434 case Decl::TranslationUnit:
3435 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003436
Fangrui Song050229d2018-11-24 00:14:31 +00003437 case Decl::Using:
3438 case Decl::UnresolvedUsingValue:
3439 case Decl::UnresolvedUsingTypename:
3440 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003441
Fangrui Song050229d2018-11-24 00:14:31 +00003442 case Decl::ObjCPropertyImpl:
3443 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3444 case ObjCPropertyImplDecl::Dynamic:
3445 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003446
Fangrui Song050229d2018-11-24 00:14:31 +00003447 case ObjCPropertyImplDecl::Synthesize:
3448 return CXCursor_ObjCSynthesizeDecl;
3449 }
3450
3451 case Decl::Import:
3452 return CXCursor_ModuleImportDecl;
3453
3454 case Decl::ObjCTypeParam:
3455 return CXCursor_TemplateTypeParameter;
3456
3457 default:
3458 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3459 switch (TD->getTagKind()) {
3460 case TTK_Interface: // fall through
3461 case TTK_Struct:
3462 return CXCursor_StructDecl;
3463 case TTK_Class:
3464 return CXCursor_ClassDecl;
3465 case TTK_Union:
3466 return CXCursor_UnionDecl;
3467 case TTK_Enum:
3468 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003469 }
Fangrui Song050229d2018-11-24 00:14:31 +00003470 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003471 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003472
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003473 return CXCursor_UnexposedDecl;
3474}
3475
Douglas Gregor55b037b2010-07-08 20:55:51 +00003476static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003477 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003478 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003479 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003480
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003481 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003482
Eric Liu88de9f62018-09-19 09:34:55 +00003483 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3484 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003485 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003486 auto MD = PP.getMacroDefinition(M->first);
3487 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003488 MacroInfo *MI = MD.getMacroInfo();
3489 if (MI && MI->isUsedForHeaderGuard())
3490 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003491
Eric Liud485df12018-09-05 14:59:17 +00003492 Results.AddResult(
3493 Result(M->first, MI,
3494 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3495 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003496 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003497 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003498
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003499 Results.ExitScope();
3500}
3501
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003502static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003503 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003504 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003505
Douglas Gregorce0e8562010-08-23 21:54:33 +00003506 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003507
Douglas Gregorce0e8562010-08-23 21:54:33 +00003508 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3509 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003510 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003511 Results.AddResult(Result("__func__", CCP_Constant));
3512 Results.ExitScope();
3513}
3514
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003515static void HandleCodeCompleteResults(Sema *S,
3516 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003517 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003518 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003519 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003520 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003521 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003522}
3523
Ilya Biryukov41109672018-12-13 15:36:32 +00003524static CodeCompletionContext
Fangrui Song050229d2018-11-24 00:14:31 +00003525mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003526 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003527 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003528 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003529
John McCallfaf5fb42010-08-26 23:41:50 +00003530 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003531 return CodeCompletionContext::CCC_ClassStructUnion;
3532
John McCallfaf5fb42010-08-26 23:41:50 +00003533 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003534 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003535
John McCallfaf5fb42010-08-26 23:41:50 +00003536 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003537 return CodeCompletionContext::CCC_ObjCImplementation;
3538
John McCallfaf5fb42010-08-26 23:41:50 +00003539 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003540 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003541
John McCallfaf5fb42010-08-26 23:41:50 +00003542 case Sema::PCC_Template:
3543 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003544 if (S.CurContext->isFileContext())
3545 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003546 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003547 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003548 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003549
John McCallfaf5fb42010-08-26 23:41:50 +00003550 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003551 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003552
John McCallfaf5fb42010-08-26 23:41:50 +00003553 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003554 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003555 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003556 return CodeCompletionContext::CCC_ParenthesizedExpression;
3557 else
3558 return CodeCompletionContext::CCC_Expression;
3559
3560 case Sema::PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003561 return CodeCompletionContext::CCC_Expression;
Ilya Biryukov41109672018-12-13 15:36:32 +00003562 case Sema::PCC_Condition:
3563 return CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3564 S.getASTContext().BoolTy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003565
John McCallfaf5fb42010-08-26 23:41:50 +00003566 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003567 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003568
John McCallfaf5fb42010-08-26 23:41:50 +00003569 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003570 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003571
3572 case Sema::PCC_ParenthesizedExpression:
3573 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003574
Douglas Gregor80039242011-02-15 20:33:25 +00003575 case Sema::PCC_LocalDeclarationSpecifiers:
3576 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003577 }
David Blaikie8a40f702012-01-17 06:56:22 +00003578
3579 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003580}
3581
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003582/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003583/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003584/// overridden function as well as adding new functionality.
3585///
3586/// \param S The semantic analysis object for which we are generating results.
3587///
3588/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003589/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003590static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3591 ResultBuilder &Results) {
3592 // Look through blocks.
3593 DeclContext *CurContext = S.CurContext;
3594 while (isa<BlockDecl>(CurContext))
3595 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003596
Douglas Gregorac322ec2010-08-27 21:18:54 +00003597 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3598 if (!Method || !Method->isVirtual())
3599 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003600
3601 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003602 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003603 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003604 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003605 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003606
Douglas Gregor75acd922011-09-27 23:30:47 +00003607 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003608 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003609 CodeCompletionBuilder Builder(Results.getAllocator(),
3610 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003611 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3612 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003613
Douglas Gregorac322ec2010-08-27 21:18:54 +00003614 // If we need a nested-name-specifier, add one now.
3615 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003616 NestedNameSpecifier *NNS = getRequiredQualification(
3617 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003618 if (NNS) {
3619 std::string Str;
3620 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003621 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003622 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003623 }
3624 } else if (!InContext->Equals(Overridden->getDeclContext()))
3625 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003626
Fangrui Song050229d2018-11-24 00:14:31 +00003627 Builder.AddTypedTextChunk(
3628 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003629 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003630 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003631 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003632 if (FirstParam)
3633 FirstParam = false;
3634 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003635 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003636
Aaron Ballman43b68be2014-03-07 17:50:17 +00003637 Builder.AddPlaceholderChunk(
3638 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003639 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003640 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00003641 Results.AddResult(CodeCompletionResult(
3642 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
3643 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003644 Results.Ignore(Overridden);
3645 }
3646}
3647
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003648void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003649 ModuleIdPath Path) {
3650 typedef CodeCompletionResult Result;
3651 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003652 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003653 CodeCompletionContext::CCC_Other);
3654 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003655
Douglas Gregor07f43572012-01-29 18:15:03 +00003656 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003657 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003658 typedef CodeCompletionResult Result;
3659 if (Path.empty()) {
3660 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003661 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003662 PP.getHeaderSearchInfo().collectAllModules(Modules);
3663 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3664 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003665 Builder.getAllocator().CopyString(Modules[I]->Name));
3666 Results.AddResult(Result(
3667 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3668 Modules[I]->isAvailable() ? CXAvailability_Available
3669 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003670 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003671 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003672 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00003673 Module *Mod =
3674 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
3675 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00003676 // Enumerate submodules.
3677 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003678 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003679 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00003680 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003681
Douglas Gregor07f43572012-01-29 18:15:03 +00003682 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003683 Builder.getAllocator().CopyString((*Sub)->Name));
3684 Results.AddResult(Result(
3685 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3686 (*Sub)->isAvailable() ? CXAvailability_Available
3687 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003688 }
3689 }
3690 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003691 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003692 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003693 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00003694}
3695
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003696void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003697 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003698 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003699 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003700 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003701 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003702
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003703 // Determine how to filter results, e.g., so that the names of
3704 // values (functions, enumerators, function templates, etc.) are
3705 // only allowed where we can have an expression.
3706 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003707 case PCC_Namespace:
3708 case PCC_Class:
3709 case PCC_ObjCInterface:
3710 case PCC_ObjCImplementation:
3711 case PCC_ObjCInstanceVariableList:
3712 case PCC_Template:
3713 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003714 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003715 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003716 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3717 break;
3718
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003719 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003720 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003721 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003722 case PCC_ForInit:
3723 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003724 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003725 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3726 else
3727 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003728
David Blaikiebbafb8a2012-03-11 07:00:24 +00003729 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003730 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003731 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003732
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003733 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003734 // Unfiltered
3735 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003736 }
3737
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003738 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003739 // the member function to filter/prioritize the results list.
Eric Liu2bfd3f52018-10-22 08:47:31 +00003740 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext)) {
3741 if (CurMethod->isInstance()) {
Mikael Nilsson9d2872d2018-12-13 10:15:27 +00003742 Results.setObjectTypeQualifiers(CurMethod->getTypeQualifiers());
Eric Liu2bfd3f52018-10-22 08:47:31 +00003743 }
3744 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003745
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003746 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003747 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003748 CodeCompleter->includeGlobals(),
3749 CodeCompleter->loadExternal());
Douglas Gregor92253692009-12-07 09:54:55 +00003750
Douglas Gregorf98e6a22010-01-13 23:51:12 +00003751 AddOrdinaryNameResults(CompletionContext, S, *this, Results);
Douglas Gregor92253692009-12-07 09:54:55 +00003752 Results.ExitScope();
3753
Douglas Gregorce0e8562010-08-23 21:54:33 +00003754 switch (CompletionContext) {
Douglas Gregor5e35d592010-09-14 23:59:36 +00003755 case PCC_ParenthesizedExpression:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003756 case PCC_Expression:
3757 case PCC_Statement:
3758 case PCC_RecoveryInFunction:
3759 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00003760 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003761 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003762
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003763 case PCC_Namespace:
3764 case PCC_Class:
3765 case PCC_ObjCInterface:
3766 case PCC_ObjCImplementation:
3767 case PCC_ObjCInstanceVariableList:
3768 case PCC_Template:
3769 case PCC_MemberTemplate:
3770 case PCC_ForInit:
3771 case PCC_Condition:
3772 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003773 case PCC_LocalDeclarationSpecifiers:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003774 break;
Douglas Gregorce0e8562010-08-23 21:54:33 +00003775 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003776
Douglas Gregor9eb77012009-11-07 00:00:49 +00003777 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003778 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003779
Douglas Gregor50832e02010-09-20 22:39:41 +00003780 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003781 Results.data(), Results.size());
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00003782}
3783
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003784static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003785 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003786 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00003787 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003788 ResultBuilder &Results);
3789
3790void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS,
3791 bool AllowNonIdentifiers,
3792 bool AllowNestedNameSpecifiers) {
John McCall276321a2010-08-25 06:19:51 +00003793 typedef CodeCompletionResult Result;
Kadir Cetinkayab006e092018-10-24 15:23:49 +00003794 ResultBuilder Results(
3795 *this, CodeCompleter->getAllocator(),
3796 CodeCompleter->getCodeCompletionTUInfo(),
3797 AllowNestedNameSpecifiers
3798 // FIXME: Try to separate codepath leading here to deduce whether we
3799 // need an existing symbol or a new one.
3800 ? CodeCompletionContext::CCC_SymbolOrNewName
3801 : CodeCompletionContext::CCC_NewName);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003802 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003803
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003804 // Type qualifiers can come after names.
3805 Results.AddResult(Result("const"));
3806 Results.AddResult(Result("volatile"));
David Blaikiebbafb8a2012-03-11 07:00:24 +00003807 if (getLangOpts().C99)
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003808 Results.AddResult(Result("restrict"));
3809
David Blaikiebbafb8a2012-03-11 07:00:24 +00003810 if (getLangOpts().CPlusPlus) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00003811 if (getLangOpts().CPlusPlus11 &&
3812 (DS.getTypeSpecType() == DeclSpec::TST_class ||
3813 DS.getTypeSpecType() == DeclSpec::TST_struct))
3814 Results.AddResult("final");
3815
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003816 if (AllowNonIdentifiers) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003817 Results.AddResult(Result("operator"));
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003818 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003819
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003820 // Add nested-name-specifiers.
3821 if (AllowNestedNameSpecifiers) {
3822 Results.allowNestedNameSpecifiers();
Douglas Gregor0ac41382010-09-23 23:01:17 +00003823 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003824 CodeCompletionDeclConsumer Consumer(Results, CurContext);
3825 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003826 CodeCompleter->includeGlobals(),
3827 CodeCompleter->loadExternal());
Craig Topperc3ec1492014-05-26 06:22:03 +00003828 Results.setFilter(nullptr);
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003829 }
3830 }
3831 Results.ExitScope();
3832
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003833 // If we're in a context where we might have an expression (rather than a
3834 // declaration), and what we've seen so far is an Objective-C type that could
3835 // be a receiver of a class message, this may be a class message send with
3836 // the initial opening bracket '[' missing. Add appropriate completions.
3837 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers &&
Richard Smithb4a9e862013-04-12 22:46:28 +00003838 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003839 DS.getTypeSpecType() == DeclSpec::TST_typename &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003840 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified &&
3841 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified &&
Fangrui Song050229d2018-11-24 00:14:31 +00003842 !DS.isTypeAltiVecVector() && S &&
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003843 (S->getFlags() & Scope::DeclScope) != 0 &&
3844 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope |
Fangrui Song050229d2018-11-24 00:14:31 +00003845 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) ==
3846 0) {
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003847 ParsedType T = DS.getRepAsType();
3848 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType())
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00003849 AddClassMessageCompletions(*this, S, T, None, false, false, Results);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00003850 }
3851
Douglas Gregor56ccce02010-08-24 04:59:56 +00003852 // Note that we intentionally suppress macro results here, since we do not
3853 // encourage using macros to produce the names of entities.
3854
Fangrui Song050229d2018-11-24 00:14:31 +00003855 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregorc49f5b22010-08-23 18:23:48 +00003856 Results.data(), Results.size());
3857}
3858
Douglas Gregor68762e72010-08-23 21:17:50 +00003859struct Sema::CodeCompleteExpressionData {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003860 CodeCompleteExpressionData(QualType PreferredType = QualType())
Fangrui Song050229d2018-11-24 00:14:31 +00003861 : PreferredType(PreferredType), IntegralConstantExpression(false),
3862 ObjCCollection(false) {}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003863
Douglas Gregor68762e72010-08-23 21:17:50 +00003864 QualType PreferredType;
3865 bool IntegralConstantExpression;
3866 bool ObjCCollection;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00003867 SmallVector<Decl *, 4> IgnoreDecls;
Douglas Gregor68762e72010-08-23 21:17:50 +00003868};
3869
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003870/// Perform code-completion in an expression context when we know what
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003871/// type we're looking for.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003872void Sema::CodeCompleteExpression(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00003873 const CodeCompleteExpressionData &Data) {
Eric Liuf5ba09f2018-07-04 10:01:18 +00003874 ResultBuilder Results(
3875 *this, CodeCompleter->getAllocator(),
3876 CodeCompleter->getCodeCompletionTUInfo(),
3877 CodeCompletionContext(CodeCompletionContext::CCC_Expression,
3878 Data.PreferredType));
Douglas Gregor68762e72010-08-23 21:17:50 +00003879 if (Data.ObjCCollection)
3880 Results.setFilter(&ResultBuilder::IsObjCCollection);
3881 else if (Data.IntegralConstantExpression)
Douglas Gregor85b50632010-07-28 21:50:18 +00003882 Results.setFilter(&ResultBuilder::IsIntegralConstantValue);
David Blaikiebbafb8a2012-03-11 07:00:24 +00003883 else if (WantTypesInContext(PCC_Expression, getLangOpts()))
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003884 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3885 else
3886 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Douglas Gregor68762e72010-08-23 21:17:50 +00003887
3888 if (!Data.PreferredType.isNull())
3889 Results.setPreferredType(Data.PreferredType.getNonReferenceType());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003890
Douglas Gregor68762e72010-08-23 21:17:50 +00003891 // Ignore any declarations that we were told that we don't care about.
3892 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I)
3893 Results.Ignore(Data.IgnoreDecls[I]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003894
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003895 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00003896 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00003897 CodeCompleter->includeGlobals(),
3898 CodeCompleter->loadExternal());
3899
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003900 Results.EnterNewScope();
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003901 AddOrdinaryNameResults(PCC_Expression, S, *this, Results);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003902 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003903
Douglas Gregor55b037b2010-07-08 20:55:51 +00003904 bool PreferredTypeIsPointer = false;
Douglas Gregor68762e72010-08-23 21:17:50 +00003905 if (!Data.PreferredType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00003906 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() ||
3907 Data.PreferredType->isMemberPointerType() ||
3908 Data.PreferredType->isBlockPointerType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003909
Fangrui Song050229d2018-11-24 00:14:31 +00003910 if (S->getFnParent() && !Data.ObjCCollection &&
Douglas Gregorce0e8562010-08-23 21:54:33 +00003911 !Data.IntegralConstantExpression)
Craig Topper12126262015-11-15 17:27:57 +00003912 AddPrettyFunctionResults(getLangOpts(), Results);
Douglas Gregorce0e8562010-08-23 21:54:33 +00003913
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003914 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00003915 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false,
3916 PreferredTypeIsPointer);
Eric Liuf5ba09f2018-07-04 10:01:18 +00003917 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
3918 Results.data(), Results.size());
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003919}
3920
Ilya Biryukov832c4af2018-09-07 14:04:39 +00003921void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType) {
3922 return CodeCompleteExpression(S, CodeCompleteExpressionData(PreferredType));
3923}
3924
Douglas Gregoreda7e542010-09-18 01:28:11 +00003925void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E) {
3926 if (E.isInvalid())
3927 CodeCompleteOrdinaryName(S, PCC_RecoveryInFunction);
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003928 else if (getLangOpts().ObjC)
Nikola Smiljanic01a75982014-05-29 10:55:11 +00003929 CodeCompleteObjCInstanceMessage(S, E.get(), None, false);
Douglas Gregored0b69d2010-09-15 16:23:04 +00003930}
Douglas Gregor7aa6b222010-05-30 01:49:25 +00003931
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003932/// The set of properties that have already been added, referenced by
Douglas Gregorb888acf2010-12-09 23:01:55 +00003933/// property name.
Fangrui Song050229d2018-11-24 00:14:31 +00003934typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet;
Douglas Gregorb888acf2010-12-09 23:01:55 +00003935
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003936/// Retrieve the container definition, if any?
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003937static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) {
3938 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) {
3939 if (Interface->hasDefinition())
3940 return Interface->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003941
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003942 return Interface;
3943 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003944
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003945 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
3946 if (Protocol->hasDefinition())
3947 return Protocol->getDefinition();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003948
Douglas Gregor9b4f3702012-06-12 13:44:08 +00003949 return Protocol;
3950 }
3951 return Container;
3952}
3953
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003954/// Adds a block invocation code completion result for the given block
Alex Lorenzbaef8022016-11-09 13:43:18 +00003955/// declaration \p BD.
3956static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy,
3957 CodeCompletionBuilder &Builder,
3958 const NamedDecl *BD,
3959 const FunctionTypeLoc &BlockLoc,
3960 const FunctionProtoTypeLoc &BlockProtoLoc) {
3961 Builder.AddResultTypeChunk(
3962 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context,
3963 Policy, Builder.getAllocator()));
3964
3965 AddTypedNameChunk(Context, Policy, BD, Builder);
3966 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
3967
3968 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) {
3969 Builder.AddPlaceholderChunk("...");
3970 } else {
3971 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) {
3972 if (I)
3973 Builder.AddChunk(CodeCompletionString::CK_Comma);
3974
3975 // Format the placeholder string.
3976 std::string PlaceholderStr =
3977 FormatFunctionParameter(Policy, BlockLoc.getParam(I));
3978
3979 if (I == N - 1 && BlockProtoLoc &&
3980 BlockProtoLoc.getTypePtr()->isVariadic())
3981 PlaceholderStr += ", ...";
3982
3983 // Add the placeholder string.
3984 Builder.AddPlaceholderChunk(
3985 Builder.getAllocator().CopyString(PlaceholderStr));
3986 }
3987 }
3988
3989 Builder.AddChunk(CodeCompletionString::CK_RightParen);
3990}
3991
Fangrui Song050229d2018-11-24 00:14:31 +00003992static void
3993AddObjCProperties(const CodeCompletionContext &CCContext,
3994 ObjCContainerDecl *Container, bool AllowCategories,
3995 bool AllowNullaryMethods, DeclContext *CurContext,
3996 AddedPropertiesSet &AddedProperties, ResultBuilder &Results,
3997 bool IsBaseExprStatement = false,
3998 bool IsClassProperty = false, bool InOriginalClass = true) {
John McCall276321a2010-08-25 06:19:51 +00003999 typedef CodeCompletionResult Result;
Douglas Gregor9291bad2009-11-18 01:29:26 +00004000
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004001 // Retrieve the definition.
4002 Container = getContainerDef(Container);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004003
Douglas Gregor9291bad2009-11-18 01:29:26 +00004004 // Add properties in this container.
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004005 const auto AddProperty = [&](const ObjCPropertyDecl *P) {
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004006 if (!AddedProperties.insert(P->getIdentifier()).second)
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004007 return;
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004008
Alex Lorenzbaef8022016-11-09 13:43:18 +00004009 // FIXME: Provide block invocation completion for non-statement
4010 // expressions.
4011 if (!P->getType().getTypePtr()->isBlockPointerType() ||
4012 !IsBaseExprStatement) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004013 Result R = Result(P, Results.getBasePriority(P), nullptr);
4014 if (!InOriginalClass)
4015 setInBaseClass(R);
4016 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004017 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004018 }
4019
4020 // Block setter and invocation completion is provided only when we are able
4021 // to find the FunctionProtoTypeLoc with parameter names for the block.
4022 FunctionTypeLoc BlockLoc;
4023 FunctionProtoTypeLoc BlockProtoLoc;
4024 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc,
4025 BlockProtoLoc);
4026 if (!BlockLoc) {
Sam McCall8e9baa32018-11-20 22:06:54 +00004027 Result R = Result(P, Results.getBasePriority(P), nullptr);
4028 if (!InOriginalClass)
4029 setInBaseClass(R);
4030 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004031 return;
Alex Lorenzbaef8022016-11-09 13:43:18 +00004032 }
4033
4034 // The default completion result for block properties should be the block
4035 // invocation completion when the base expression is a statement.
4036 CodeCompletionBuilder Builder(Results.getAllocator(),
4037 Results.getCodeCompletionTUInfo());
4038 AddObjCBlockCall(Container->getASTContext(),
4039 getCompletionPrintingPolicy(Results.getSema()), Builder, P,
4040 BlockLoc, BlockProtoLoc);
Sam McCall8e9baa32018-11-20 22:06:54 +00004041 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P));
4042 if (!InOriginalClass)
4043 setInBaseClass(R);
4044 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004045
4046 // Provide additional block setter completion iff the base expression is a
Alex Lorenzbaef8022016-11-09 13:43:18 +00004047 // statement and the block property is mutable.
4048 if (!P->isReadOnly()) {
4049 CodeCompletionBuilder Builder(Results.getAllocator(),
4050 Results.getCodeCompletionTUInfo());
4051 AddResultTypeChunk(Container->getASTContext(),
4052 getCompletionPrintingPolicy(Results.getSema()), P,
4053 CCContext.getBaseType(), Builder);
4054 Builder.AddTypedTextChunk(
4055 Results.getAllocator().CopyString(P->getName()));
4056 Builder.AddChunk(CodeCompletionString::CK_Equal);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004057
Alex Lorenzbaef8022016-11-09 13:43:18 +00004058 std::string PlaceholderStr = formatBlockPlaceholder(
4059 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc,
4060 BlockProtoLoc, /*SuppressBlockName=*/true);
4061 // Add the placeholder string.
4062 Builder.AddPlaceholderChunk(
4063 Builder.getAllocator().CopyString(PlaceholderStr));
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004064
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004065 // When completing blocks properties that return void the default
4066 // property completion result should show up before the setter,
4067 // otherwise the setter completion should show up before the default
4068 // property completion, as we normally want to use the result of the
4069 // call.
Sam McCall8e9baa32018-11-20 22:06:54 +00004070 Result R =
Alex Lorenzbaef8022016-11-09 13:43:18 +00004071 Result(Builder.TakeString(), P,
Alex Lorenz6e0f3932017-01-06 12:00:44 +00004072 Results.getBasePriority(P) +
4073 (BlockLoc.getTypePtr()->getReturnType()->isVoidType()
4074 ? CCD_BlockPropertySetter
Sam McCall8e9baa32018-11-20 22:06:54 +00004075 : -CCD_BlockPropertySetter));
4076 if (!InOriginalClass)
4077 setInBaseClass(R);
4078 Results.MaybeAddResult(R, CurContext);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004079 }
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004080 };
4081
4082 if (IsClassProperty) {
4083 for (const auto *P : Container->class_properties())
4084 AddProperty(P);
4085 } else {
4086 for (const auto *P : Container->instance_properties())
4087 AddProperty(P);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004088 }
Craig Topperc3ec1492014-05-26 06:22:03 +00004089
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004090 // Add nullary methods or implicit class properties
Douglas Gregor95147142011-05-05 15:50:42 +00004091 if (AllowNullaryMethods) {
4092 ASTContext &Context = Container->getASTContext();
Douglas Gregor75acd922011-09-27 23:30:47 +00004093 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004094 // Adds a method result
4095 const auto AddMethod = [&](const ObjCMethodDecl *M) {
4096 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0);
4097 if (!Name)
4098 return;
4099 if (!AddedProperties.insert(Name).second)
4100 return;
4101 CodeCompletionBuilder Builder(Results.getAllocator(),
4102 Results.getCodeCompletionTUInfo());
4103 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder);
4104 Builder.AddTypedTextChunk(
4105 Results.getAllocator().CopyString(Name->getName()));
Sam McCall8e9baa32018-11-20 22:06:54 +00004106 Result R = Result(Builder.TakeString(), M,
4107 CCP_MemberDeclaration + CCD_MethodAsProperty);
4108 if (!InOriginalClass)
4109 setInBaseClass(R);
4110 Results.MaybeAddResult(R, CurContext);
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004111 };
4112
4113 if (IsClassProperty) {
4114 for (const auto *M : Container->methods()) {
4115 // Gather the class method that can be used as implicit property
4116 // getters. Methods with arguments or methods that return void aren't
4117 // added to the results as they can't be used as a getter.
4118 if (!M->getSelector().isUnarySelector() ||
4119 M->getReturnType()->isVoidType() || M->isInstanceMethod())
4120 continue;
4121 AddMethod(M);
4122 }
4123 } else {
4124 for (auto *M : Container->methods()) {
4125 if (M->getSelector().isUnarySelector())
4126 AddMethod(M);
4127 }
Douglas Gregor95147142011-05-05 15:50:42 +00004128 }
4129 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004130
Douglas Gregor9291bad2009-11-18 01:29:26 +00004131 // Add properties in referenced protocols.
4132 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Aaron Ballman0f6e64d2014-03-13 22:58:06 +00004133 for (auto *P : Protocol->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004134 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004135 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004136 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004137 /*InOriginalClass*/ false);
4138 } else if (ObjCInterfaceDecl *IFace =
4139 dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor5d649882009-11-18 22:32:06 +00004140 if (AllowCategories) {
4141 // Look through categories.
Aaron Ballman15063e12014-03-13 21:35:02 +00004142 for (auto *Cat : IFace->known_categories())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004143 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004144 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004145 IsBaseExprStatement, IsClassProperty,
4146 InOriginalClass);
Douglas Gregor5d649882009-11-18 22:32:06 +00004147 }
Aaron Ballman15063e12014-03-13 21:35:02 +00004148
Douglas Gregor9291bad2009-11-18 01:29:26 +00004149 // Look through protocols.
Aaron Ballmana9f49e32014-03-13 20:55:22 +00004150 for (auto *I : IFace->all_referenced_protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004151 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004152 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004153 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004154 /*InOriginalClass*/ false);
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004155
Douglas Gregor9291bad2009-11-18 01:29:26 +00004156 // Look in the superclass.
4157 if (IFace->getSuperClass())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004158 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004159 AllowNullaryMethods, CurContext, AddedProperties,
Sam McCall8e9baa32018-11-20 22:06:54 +00004160 Results, IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004161 /*InOriginalClass*/ false);
4162 } else if (const auto *Category =
4163 dyn_cast<ObjCCategoryDecl>(Container)) {
Douglas Gregor9291bad2009-11-18 01:29:26 +00004164 // Look through protocols.
Aaron Ballman19a41762014-03-14 12:55:57 +00004165 for (auto *P : Category->protocols())
Douglas Gregorc3425b12015-07-07 06:20:19 +00004166 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004167 CurContext, AddedProperties, Results,
Sam McCall8e9baa32018-11-20 22:06:54 +00004168 IsBaseExprStatement, IsClassProperty,
Fangrui Song050229d2018-11-24 00:14:31 +00004169 /*InOriginalClass*/ false);
Douglas Gregor9291bad2009-11-18 01:29:26 +00004170 }
4171}
4172
Fangrui Song050229d2018-11-24 00:14:31 +00004173static void
4174AddRecordMembersCompletionResults(Sema &SemaRef, ResultBuilder &Results,
4175 Scope *S, QualType BaseType, RecordDecl *RD,
4176 Optional<FixItHint> AccessOpFixIt) {
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004177 // Indicate that we are performing a member access, and the cv-qualifiers
4178 // for the base object type.
4179 Results.setObjectTypeQualifiers(BaseType.getQualifiers());
4180
4181 // Access to a C/C++ class, struct, or union.
4182 Results.allowNestedNameSpecifiers();
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004183 std::vector<FixItHint> FixIts;
4184 if (AccessOpFixIt)
Fangrui Song050229d2018-11-24 00:14:31 +00004185 FixIts.emplace_back(AccessOpFixIt.getValue());
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004186 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts));
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004187 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer,
Alex Lorenze6afa392017-05-11 13:48:57 +00004188 SemaRef.CodeCompleter->includeGlobals(),
Sam McCallbb2cf632018-01-12 14:51:47 +00004189 /*IncludeDependentBases=*/true,
4190 SemaRef.CodeCompleter->loadExternal());
Alex Lorenz0fe0d982017-05-11 13:41:00 +00004191
4192 if (SemaRef.getLangOpts().CPlusPlus) {
4193 if (!Results.empty()) {
4194 // The "template" keyword can follow "->" or "." in the grammar.
4195 // However, we only want to suggest the template keyword if something
4196 // is dependent.
4197 bool IsDependent = BaseType->isDependentType();
4198 if (!IsDependent) {
4199 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent())
4200 if (DeclContext *Ctx = DepScope->getEntity()) {
4201 IsDependent = Ctx->isDependentContext();
4202 break;
4203 }
4204 }
4205
4206 if (IsDependent)
4207 Results.AddResult(CodeCompletionResult("template"));
4208 }
4209 }
4210}
4211
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004212void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base,
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004213 Expr *OtherOpBase,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00004214 SourceLocation OpLoc, bool IsArrow,
4215 bool IsBaseExprStatement) {
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004216 if (!Base || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004217 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004218
Douglas Gregor1cc88a92012-01-23 15:59:30 +00004219 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4220 if (ConvertedBase.isInvalid())
4221 return;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004222 QualType ConvertedBaseType = ConvertedBase.get()->getType();
4223
4224 enum CodeCompletionContext::Kind contextKind;
Douglas Gregor3545ff42009-09-21 16:56:56 +00004225
4226 if (IsArrow) {
Fangrui Song050229d2018-11-24 00:14:31 +00004227 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>())
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004228 ConvertedBaseType = Ptr->getPointeeType();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004229 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004230
Douglas Gregor21325842011-07-07 16:03:39 +00004231 if (IsArrow) {
4232 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004233 } else {
4234 if (ConvertedBaseType->isObjCObjectPointerType() ||
4235 ConvertedBaseType->isObjCObjectOrInterfaceType()) {
Douglas Gregor21325842011-07-07 16:03:39 +00004236 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess;
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004237 } else {
Douglas Gregor21325842011-07-07 16:03:39 +00004238 contextKind = CodeCompletionContext::CCC_DotMemberAccess;
4239 }
4240 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00004241
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004242 CodeCompletionContext CCContext(contextKind, ConvertedBaseType);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004243 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004244 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004245 &ResultBuilder::IsMember);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004246
Fangrui Song050229d2018-11-24 00:14:31 +00004247 auto DoCompletion = [&](Expr *Base, bool IsArrow,
4248 Optional<FixItHint> AccessOpFixIt) -> bool {
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004249 if (!Base)
4250 return false;
4251
4252 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow);
4253 if (ConvertedBase.isInvalid())
4254 return false;
4255 Base = ConvertedBase.get();
4256
4257 QualType BaseType = Base->getType();
4258
4259 if (IsArrow) {
4260 if (const PointerType *Ptr = BaseType->getAs<PointerType>())
4261 BaseType = Ptr->getPointeeType();
4262 else if (BaseType->isObjCObjectPointerType())
4263 /*Do nothing*/;
4264 else
4265 return false;
4266 }
4267
4268 if (const RecordType *Record = BaseType->getAs<RecordType>()) {
4269 AddRecordMembersCompletionResults(*this, Results, S, BaseType,
4270 Record->getDecl(),
4271 std::move(AccessOpFixIt));
4272 } else if (const auto *TST =
4273 BaseType->getAs<TemplateSpecializationType>()) {
4274 TemplateName TN = TST->getTemplateName();
4275 if (const auto *TD =
4276 dyn_cast_or_null<ClassTemplateDecl>(TN.getAsTemplateDecl())) {
4277 CXXRecordDecl *RD = TD->getTemplatedDecl();
4278 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4279 std::move(AccessOpFixIt));
4280 }
4281 } else if (const auto *ICNT = BaseType->getAs<InjectedClassNameType>()) {
4282 if (auto *RD = ICNT->getDecl())
4283 AddRecordMembersCompletionResults(*this, Results, S, BaseType, RD,
4284 std::move(AccessOpFixIt));
4285 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) {
4286 // Objective-C property reference.
4287 AddedPropertiesSet AddedProperties;
4288
4289 if (const ObjCObjectPointerType *ObjCPtr =
4290 BaseType->getAsObjCInterfacePointerType()) {
4291 // Add property results based on our interface.
4292 assert(ObjCPtr && "Non-NULL pointer guaranteed above!");
4293 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true,
4294 /*AllowNullaryMethods=*/true, CurContext,
4295 AddedProperties, Results, IsBaseExprStatement);
4296 }
4297
4298 // Add properties from the protocols in a qualified interface.
4299 for (auto *I : BaseType->getAs<ObjCObjectPointerType>()->quals())
4300 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true,
4301 CurContext, AddedProperties, Results,
Fangrui Song050229d2018-11-24 00:14:31 +00004302 IsBaseExprStatement, /*IsClassProperty*/ false,
4303 /*InOriginalClass*/ false);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004304 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) ||
4305 (!IsArrow && BaseType->isObjCObjectType())) {
4306 // Objective-C instance variable access.
4307 ObjCInterfaceDecl *Class = nullptr;
4308 if (const ObjCObjectPointerType *ObjCPtr =
4309 BaseType->getAs<ObjCObjectPointerType>())
4310 Class = ObjCPtr->getInterfaceDecl();
4311 else
4312 Class = BaseType->getAs<ObjCObjectType>()->getInterface();
4313
4314 // Add all ivars from this class and its superclasses.
4315 if (Class) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004316 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType);
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004317 Results.setFilter(&ResultBuilder::IsObjCIvar);
4318 LookupVisibleDecls(
4319 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(),
4320 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal());
4321 }
4322 }
4323
4324 // FIXME: How do we cope with isa?
4325 return true;
4326 };
4327
Douglas Gregor9291bad2009-11-18 01:29:26 +00004328 Results.EnterNewScope();
Alex Lorenz06cfa992016-10-12 11:40:15 +00004329
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004330 bool CompletionSucceded = DoCompletion(Base, IsArrow, None);
4331 if (CodeCompleter->includeFixIts()) {
4332 const CharSourceRange OpRange =
4333 CharSourceRange::getTokenRange(OpLoc, OpLoc);
4334 CompletionSucceded |= DoCompletion(
4335 OtherOpBase, !IsArrow,
4336 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->"));
Douglas Gregor3545ff42009-09-21 16:56:56 +00004337 }
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004338
Douglas Gregor9291bad2009-11-18 01:29:26 +00004339 Results.ExitScope();
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004340
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004341 if (!CompletionSucceded)
4342 return;
4343
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00004344 // Hand off the results found for code completion.
Ivan Donchevskiib4670fc2018-05-25 12:56:26 +00004345 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4346 Results.data(), Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004347}
4348
Alex Lorenzfeafdf62016-12-08 15:09:40 +00004349void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S,
4350 IdentifierInfo &ClassName,
4351 SourceLocation ClassNameLoc,
4352 bool IsBaseExprStatement) {
4353 IdentifierInfo *ClassNamePtr = &ClassName;
4354 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc);
4355 if (!IFace)
4356 return;
4357 CodeCompletionContext CCContext(
4358 CodeCompletionContext::CCC_ObjCPropertyAccess);
4359 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4360 CodeCompleter->getCodeCompletionTUInfo(), CCContext,
4361 &ResultBuilder::IsMember);
4362 Results.EnterNewScope();
4363 AddedPropertiesSet AddedProperties;
4364 AddObjCProperties(CCContext, IFace, true,
4365 /*AllowNullaryMethods=*/true, CurContext, AddedProperties,
4366 Results, IsBaseExprStatement,
4367 /*IsClassProperty=*/true);
4368 Results.ExitScope();
4369 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4370 Results.data(), Results.size());
4371}
4372
Faisal Vali090da2d2018-01-01 18:23:28 +00004373void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) {
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004374 if (!CodeCompleter)
4375 return;
Craig Topperc3ec1492014-05-26 06:22:03 +00004376
4377 ResultBuilder::LookupFilter Filter = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004378 enum CodeCompletionContext::Kind ContextKind =
4379 CodeCompletionContext::CCC_Other;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004380 switch ((DeclSpec::TST)TagSpec) {
4381 case DeclSpec::TST_enum:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004382 Filter = &ResultBuilder::IsEnum;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004383 ContextKind = CodeCompletionContext::CCC_EnumTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004384 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004385
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004386 case DeclSpec::TST_union:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004387 Filter = &ResultBuilder::IsUnion;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004388 ContextKind = CodeCompletionContext::CCC_UnionTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004389 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004390
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004391 case DeclSpec::TST_struct:
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004392 case DeclSpec::TST_class:
Joao Matosdc86f942012-08-31 18:45:21 +00004393 case DeclSpec::TST_interface:
Douglas Gregor3545ff42009-09-21 16:56:56 +00004394 Filter = &ResultBuilder::IsClassOrStruct;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004395 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag;
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004396 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004397
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004398 default:
David Blaikie83d382b2011-09-23 05:06:16 +00004399 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag");
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004400 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004401
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004402 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4403 CodeCompleter->getCodeCompletionTUInfo(), ContextKind);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004404 CodeCompletionDeclConsumer Consumer(Results, CurContext);
John McCalle87beb22010-04-23 18:46:30 +00004405
4406 // First pass: look for tags.
4407 Results.setFilter(Filter);
Douglas Gregor39982192010-08-15 06:18:01 +00004408 LookupVisibleDecls(S, LookupTagName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004409 CodeCompleter->includeGlobals(),
4410 CodeCompleter->loadExternal());
John McCalle87beb22010-04-23 18:46:30 +00004411
Douglas Gregor39982192010-08-15 06:18:01 +00004412 if (CodeCompleter->includeGlobals()) {
4413 // Second pass: look for nested name specifiers.
4414 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier);
Sam McCallbb2cf632018-01-12 14:51:47 +00004415 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer,
4416 CodeCompleter->includeGlobals(),
4417 CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00004418 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004419
Douglas Gregor0ac41382010-09-23 23:01:17 +00004420 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004421 Results.data(), Results.size());
Douglas Gregorf45b0cf2009-09-18 15:37:17 +00004422}
4423
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004424static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results,
4425 const LangOptions &LangOpts) {
4426 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const))
4427 Results.AddResult("const");
4428 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile))
4429 Results.AddResult("volatile");
4430 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict))
4431 Results.AddResult("restrict");
4432 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic))
4433 Results.AddResult("_Atomic");
4434 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned))
4435 Results.AddResult("__unaligned");
4436}
4437
Douglas Gregor28c78432010-08-27 17:35:51 +00004438void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004439 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004440 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004441 CodeCompletionContext::CCC_TypeQualifiers);
Douglas Gregor28c78432010-08-27 17:35:51 +00004442 Results.EnterNewScope();
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004443 AddTypeQualifierResults(DS, Results, LangOpts);
Douglas Gregor28c78432010-08-27 17:35:51 +00004444 Results.ExitScope();
Fangrui Song050229d2018-11-24 00:14:31 +00004445 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor28c78432010-08-27 17:35:51 +00004446 Results.data(), Results.size());
4447}
4448
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004449void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D,
4450 const VirtSpecifiers *VS) {
4451 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
4452 CodeCompleter->getCodeCompletionTUInfo(),
4453 CodeCompletionContext::CCC_TypeQualifiers);
4454 Results.EnterNewScope();
4455 AddTypeQualifierResults(DS, Results, LangOpts);
4456 if (LangOpts.CPlusPlus11) {
4457 Results.AddResult("noexcept");
Faisal Vali421b2d12017-12-29 05:41:00 +00004458 if (D.getContext() == DeclaratorContext::MemberContext &&
4459 !D.isCtorOrDtor() && !D.isStaticMember()) {
Alex Lorenz8f4d3992017-02-13 23:19:40 +00004460 if (!VS || !VS->isFinalSpecified())
4461 Results.AddResult("final");
4462 if (!VS || !VS->isOverrideSpecified())
4463 Results.AddResult("override");
4464 }
4465 }
4466 Results.ExitScope();
4467 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4468 Results.data(), Results.size());
4469}
4470
Benjamin Kramer72dae622016-02-18 15:30:24 +00004471void Sema::CodeCompleteBracketDeclarator(Scope *S) {
4472 CodeCompleteExpression(S, QualType(getASTContext().getSizeType()));
4473}
4474
Douglas Gregord328d572009-09-21 18:10:23 +00004475void Sema::CodeCompleteCase(Scope *S) {
John McCallaab3e412010-08-25 08:40:02 +00004476 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter)
Douglas Gregord328d572009-09-21 18:10:23 +00004477 return;
John McCall5939b162011-08-06 07:30:58 +00004478
Richard Smithef6c43d2018-07-26 18:41:30 +00004479 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer();
Kadir Cetinkaya6d572662018-10-23 13:49:37 +00004480 // Condition expression might be invalid, do not continue in this case.
4481 if (!Switch->getCond())
4482 return;
John McCall5939b162011-08-06 07:30:58 +00004483 QualType type = Switch->getCond()->IgnoreImplicit()->getType();
4484 if (!type->isEnumeralType()) {
4485 CodeCompleteExpressionData Data(type);
Douglas Gregor68762e72010-08-23 21:17:50 +00004486 Data.IntegralConstantExpression = true;
4487 CodeCompleteExpression(S, Data);
Douglas Gregord328d572009-09-21 18:10:23 +00004488 return;
Douglas Gregor85b50632010-07-28 21:50:18 +00004489 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004490
Douglas Gregord328d572009-09-21 18:10:23 +00004491 // Code-complete the cases of a switch statement over an enumeration type
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004492 // by providing the list of
John McCall5939b162011-08-06 07:30:58 +00004493 EnumDecl *Enum = type->castAs<EnumType>()->getDecl();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00004494 if (EnumDecl *Def = Enum->getDefinition())
4495 Enum = Def;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004496
Douglas Gregord328d572009-09-21 18:10:23 +00004497 // Determine which enumerators we have already seen in the switch statement.
4498 // FIXME: Ideally, we would also be able to look *past* the code-completion
4499 // token, in case we are code-completing in the middle of the switch and not
4500 // at the end. However, we aren't able to do so at the moment.
4501 llvm::SmallPtrSet<EnumConstantDecl *, 8> EnumeratorsSeen;
Craig Topperc3ec1492014-05-26 06:22:03 +00004502 NestedNameSpecifier *Qualifier = nullptr;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004503 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC;
Douglas Gregord328d572009-09-21 18:10:23 +00004504 SC = SC->getNextSwitchCase()) {
4505 CaseStmt *Case = dyn_cast<CaseStmt>(SC);
4506 if (!Case)
4507 continue;
4508
4509 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts();
Fangrui Song050229d2018-11-24 00:14:31 +00004510 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal))
4511 if (auto *Enumerator =
4512 dyn_cast<EnumConstantDecl>(DRE->getDecl())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004513 // We look into the AST of the case statement to determine which
4514 // enumerator was named. Alternatively, we could compute the value of
Douglas Gregord328d572009-09-21 18:10:23 +00004515 // the integral constant expression, then compare it against the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004516 // values of each enumerator. However, value-based approach would not
4517 // work as well with C++ templates where enumerators declared within a
Douglas Gregord328d572009-09-21 18:10:23 +00004518 // template are type- and value-dependent.
4519 EnumeratorsSeen.insert(Enumerator);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004520
Douglas Gregorf2510672009-09-21 19:57:38 +00004521 // If this is a qualified-id, keep track of the nested-name-specifier
4522 // so that we can reproduce it as part of code completion, e.g.,
Douglas Gregord328d572009-09-21 18:10:23 +00004523 //
4524 // switch (TagD.getKind()) {
4525 // case TagDecl::TK_enum:
4526 // break;
4527 // case XXX
4528 //
Douglas Gregorf2510672009-09-21 19:57:38 +00004529 // At the XXX, our completions are TagDecl::TK_union,
Douglas Gregord328d572009-09-21 18:10:23 +00004530 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union,
4531 // TK_struct, and TK_class.
Douglas Gregor4bd90e52009-10-23 18:54:35 +00004532 Qualifier = DRE->getQualifier();
Douglas Gregord328d572009-09-21 18:10:23 +00004533 }
4534 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004535
David Blaikiebbafb8a2012-03-11 07:00:24 +00004536 if (getLangOpts().CPlusPlus && !Qualifier && EnumeratorsSeen.empty()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004537 // If there are no prior enumerators in C++, check whether we have to
Douglas Gregorf2510672009-09-21 19:57:38 +00004538 // qualify the names of the enumerators that we suggest, because they
4539 // may not be visible in this scope.
Douglas Gregord3cebdb2012-02-01 05:02:47 +00004540 Qualifier = getRequiredQualification(Context, CurContext, Enum);
Douglas Gregorf2510672009-09-21 19:57:38 +00004541 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004542
Douglas Gregord328d572009-09-21 18:10:23 +00004543 // Add any enumerators that have not yet been mentioned.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004544 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004545 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004546 CodeCompletionContext::CCC_Expression);
Douglas Gregord328d572009-09-21 18:10:23 +00004547 Results.EnterNewScope();
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004548 for (auto *E : Enum->enumerators()) {
4549 if (EnumeratorsSeen.count(E))
Douglas Gregord328d572009-09-21 18:10:23 +00004550 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004551
Aaron Ballman23a6dcb2014-03-08 18:45:14 +00004552 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier);
Craig Topperc3ec1492014-05-26 06:22:03 +00004553 Results.AddResult(R, CurContext, nullptr, false);
Douglas Gregord328d572009-09-21 18:10:23 +00004554 }
4555 Results.ExitScope();
Douglas Gregor285560922010-04-06 20:02:15 +00004556
Douglas Gregor21325842011-07-07 16:03:39 +00004557 if (CodeCompleter->includeMacros()) {
Eric Liu88de9f62018-09-19 09:34:55 +00004558 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor21325842011-07-07 16:03:39 +00004559 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00004560 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4561 Results.data(), Results.size());
Douglas Gregord328d572009-09-21 18:10:23 +00004562}
4563
Robert Wilhelm16e94b92013-08-09 18:02:13 +00004564static bool anyNullArguments(ArrayRef<Expr *> Args) {
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004565 if (Args.size() && !Args.data())
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004566 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004567
4568 for (unsigned I = 0; I != Args.size(); ++I)
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004569 if (!Args[I])
4570 return true;
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004571
Douglas Gregor6ed3eb82010-05-30 06:10:08 +00004572 return false;
4573}
4574
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004575typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate;
4576
Fangrui Song050229d2018-11-24 00:14:31 +00004577static void mergeCandidatesWithResults(
4578 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results,
4579 OverloadCandidateSet &CandidateSet, SourceLocation Loc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004580 if (!CandidateSet.empty()) {
4581 // Sort the overload candidate set by placing the best overloads first.
4582 std::stable_sort(
4583 CandidateSet.begin(), CandidateSet.end(),
4584 [&](const OverloadCandidate &X, const OverloadCandidate &Y) {
Richard Smith67ef14f2017-09-26 18:37:55 +00004585 return isBetterOverloadCandidate(SemaRef, X, Y, Loc,
4586 CandidateSet.getKind());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004587 });
4588
4589 // Add the remaining viable overload candidates as code-completion results.
Fangrui Song050229d2018-11-24 00:14:31 +00004590 for (OverloadCandidate &Candidate : CandidateSet) {
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004591 if (Candidate.Function && Candidate.Function->isDeleted())
4592 continue;
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004593 if (Candidate.Viable)
4594 Results.push_back(ResultCandidate(Candidate.Function));
Erik Verbruggen7ec91072017-09-08 10:23:08 +00004595 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004596 }
4597}
4598
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00004599/// Get the type of the Nth parameter from a given set of overload
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004600/// candidates.
Francisco Lopes da Silva8cafefa2015-01-29 05:54:59 +00004601static QualType getParamType(Sema &SemaRef,
Fangrui Song050229d2018-11-24 00:14:31 +00004602 ArrayRef<ResultCandidate> Candidates, unsigned N) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004603
4604 // Given the overloads 'Candidates' for a function call matching all arguments
4605 // up to N, return the type of the Nth parameter if it is the same for all
4606 // overload candidates.
4607 QualType ParamType;
4608 for (auto &Candidate : Candidates) {
Fangrui Song050229d2018-11-24 00:14:31 +00004609 if (const auto *FType = Candidate.getFunctionType())
4610 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004611 if (N < Proto->getNumParams()) {
4612 if (ParamType.isNull())
4613 ParamType = Proto->getParamType(N);
4614 else if (!SemaRef.Context.hasSameUnqualifiedType(
Fangrui Song050229d2018-11-24 00:14:31 +00004615 ParamType.getNonReferenceType(),
4616 Proto->getParamType(N).getNonReferenceType()))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004617 // Otherwise return a default-constructed QualType.
4618 return QualType();
4619 }
4620 }
4621
4622 return ParamType;
4623}
4624
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004625static QualType
4626ProduceSignatureHelp(Sema &SemaRef, Scope *S,
4627 MutableArrayRef<ResultCandidate> Candidates,
4628 unsigned CurrentArg, SourceLocation OpenParLoc) {
4629 if (Candidates.empty())
4630 return QualType();
4631 SemaRef.CodeCompleter->ProcessOverloadCandidates(
4632 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc);
4633 return getParamType(SemaRef, Candidates, CurrentArg);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004634}
4635
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004636QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn,
4637 ArrayRef<Expr *> Args,
4638 SourceLocation OpenParLoc) {
Douglas Gregorcabea402009-09-22 15:41:20 +00004639 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004640 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004641
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004642 // FIXME: Provide support for variadic template functions.
Douglas Gregorcabea402009-09-22 15:41:20 +00004643 // Ignore type-dependent call expressions entirely.
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004644 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) ||
4645 Expr::hasAnyTypeDependentArguments(Args)) {
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004646 return QualType();
Douglas Gregor3ef59522009-12-11 19:06:04 +00004647 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004648
John McCall57500772009-12-16 12:17:52 +00004649 // Build an overload candidate set based on the functions we find.
John McCallbc077cf2010-02-08 23:07:23 +00004650 SourceLocation Loc = Fn->getExprLoc();
Richard Smith100b24a2014-04-17 01:52:14 +00004651 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
John McCall57500772009-12-16 12:17:52 +00004652
Chris Lattner0e62c1c2011-07-23 10:55:15 +00004653 SmallVector<ResultCandidate, 8> Results;
Douglas Gregorff59f672010-01-21 15:46:19 +00004654
John McCall57500772009-12-16 12:17:52 +00004655 Expr *NakedFn = Fn->IgnoreParenCasts();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004656 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn))
Ahmed Charlesb24b9aa2012-02-25 11:00:22 +00004657 AddOverloadedCallCandidates(ULE, Args, CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004658 /*PartialOverloading=*/true);
4659 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) {
4660 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr;
4661 if (UME->hasExplicitTemplateArgs()) {
4662 UME->copyTemplateArgumentsInto(TemplateArgsBuffer);
4663 TemplateArgs = &TemplateArgsBuffer;
Douglas Gregorff59f672010-01-21 15:46:19 +00004664 }
Erik Verbruggenf1898cf2017-03-28 07:22:21 +00004665
4666 // Add the base as first argument (use a nullptr if the base is implicit).
4667 SmallVector<Expr *, 12> ArgExprs(
4668 1, UME->isImplicitAccess() ? nullptr : UME->getBase());
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004669 ArgExprs.append(Args.begin(), Args.end());
4670 UnresolvedSet<8> Decls;
4671 Decls.append(UME->decls_begin(), UME->decls_end());
Benjamin Kramere3962ae2017-10-26 08:41:28 +00004672 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004673 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs,
4674 /*SuppressUsedConversions=*/false,
Fangrui Song050229d2018-11-24 00:14:31 +00004675 /*PartialOverloading=*/true, FirstArgumentIsBase);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004676 } else {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004677 FunctionDecl *FD = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00004678 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004679 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00004680 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn))
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004681 FD = dyn_cast<FunctionDecl>(DRE->getDecl());
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004682 if (FD) { // We check whether it's a resolved function declaration.
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00004683 if (!getLangOpts().CPlusPlus ||
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004684 !FD->getType()->getAs<FunctionProtoType>())
4685 Results.push_back(ResultCandidate(FD));
4686 else
4687 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()),
4688 Args, CandidateSet,
4689 /*SuppressUsedConversions=*/false,
4690 /*PartialOverloading=*/true);
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004691
4692 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) {
4693 // If expression's type is CXXRecordDecl, it may overload the function
4694 // call operator, so we check if it does and add them as candidates.
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004695 // A complete type is needed to lookup for member function call operators.
Richard Smithdb0ac552015-12-18 22:40:25 +00004696 if (isCompleteType(Loc, NakedFn->getType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00004697 DeclarationName OpName =
4698 Context.DeclarationNames.getCXXOperatorName(OO_Call);
Francisco Lopes da Silvaa349a8a2015-01-25 08:47:59 +00004699 LookupResult R(*this, OpName, Loc, LookupOrdinaryName);
4700 LookupQualifiedName(R, DC);
4701 R.suppressDiagnostics();
4702 SmallVector<Expr *, 12> ArgExprs(1, NakedFn);
4703 ArgExprs.append(Args.begin(), Args.end());
4704 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet,
4705 /*ExplicitArgs=*/nullptr,
4706 /*SuppressUsedConversions=*/false,
4707 /*PartialOverloading=*/true);
4708 }
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004709 } else {
4710 // Lastly we check whether expression's type is function pointer or
4711 // function.
4712 QualType T = NakedFn->getType();
4713 if (!T->getPointeeType().isNull())
4714 T = T->getPointeeType();
4715
4716 if (auto FP = T->getAs<FunctionProtoType>()) {
4717 if (!TooManyArguments(FP->getNumParams(), Args.size(),
Fangrui Song050229d2018-11-24 00:14:31 +00004718 /*PartialOverloading=*/true) ||
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004719 FP->isVariadic())
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004720 Results.push_back(ResultCandidate(FP));
4721 } else if (auto FT = T->getAs<FunctionType>())
Francisco Lopes da Silva62a9a4f2015-01-23 13:17:51 +00004722 // No prototype and declaration, it may be a K & R style function.
Francisco Lopes da Silvac6ccc4f2015-01-22 21:14:08 +00004723 Results.push_back(ResultCandidate(FT));
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004724 }
Douglas Gregorcabea402009-09-22 15:41:20 +00004725 }
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004726 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004727 QualType ParamType =
4728 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
4729 return !CandidateSet.empty() ? ParamType : QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004730}
4731
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004732QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type,
4733 SourceLocation Loc,
4734 ArrayRef<Expr *> Args,
4735 SourceLocation OpenParLoc) {
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004736 if (!CodeCompleter)
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004737 return QualType();
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004738
4739 // A complete type is needed to lookup for constructors.
Ilya Biryukovfb9dde72018-05-14 13:50:36 +00004740 CXXRecordDecl *RD =
4741 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr;
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004742 if (!RD)
4743 return Type;
Argyrios Kyrtzidisee1d76f2015-03-13 07:39:30 +00004744
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004745 // FIXME: Provide support for member initializers.
4746 // FIXME: Provide support for variadic template constructors.
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004747
4748 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal);
4749
Fangrui Song050229d2018-11-24 00:14:31 +00004750 for (NamedDecl *C : LookupConstructors(RD)) {
4751 if (auto *FD = dyn_cast<FunctionDecl>(C)) {
4752 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args,
4753 CandidateSet,
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004754 /*SuppressUsedConversions=*/false,
4755 /*PartialOverloading=*/true);
Fangrui Song050229d2018-11-24 00:14:31 +00004756 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) {
4757 AddTemplateOverloadCandidate(
4758 FTD, DeclAccessPair::make(FTD, C->getAccess()),
4759 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet,
4760 /*SuppressUsedConversions=*/false,
4761 /*PartialOverloading=*/true);
Francisco Lopes da Silva975a9f62015-01-21 16:24:11 +00004762 }
4763 }
4764
4765 SmallVector<ResultCandidate, 8> Results;
4766 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc);
Ilya Biryukov832c4af2018-09-07 14:04:39 +00004767 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc);
Douglas Gregorcabea402009-09-22 15:41:20 +00004768}
4769
Kadir Cetinkaya84774c32018-09-11 15:02:18 +00004770QualType Sema::ProduceCtorInitMemberSignatureHelp(
4771 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy,
4772 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) {
4773 if (!CodeCompleter)
4774 return QualType();
4775
4776 CXXConstructorDecl *Constructor =
4777 dyn_cast<CXXConstructorDecl>(ConstructorDecl);
4778 if (!Constructor)
4779 return QualType();
4780 // FIXME: Add support for Base class constructors as well.
4781 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl(
4782 Constructor->getParent(), SS, TemplateTypeTy, II))
4783 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(),
4784 MemberDecl->getLocation(), ArgExprs,
4785 OpenParLoc);
4786 return QualType();
4787}
4788
John McCall48871652010-08-21 09:40:31 +00004789void Sema::CodeCompleteInitializer(Scope *S, Decl *D) {
4790 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004791 if (!VD) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004792 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004793 return;
4794 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004795
Ilya Biryukovebf0a6d2018-11-07 10:02:31 +00004796 CodeCompleteExpressionData Data;
4797 Data.PreferredType = VD->getType();
4798 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'.
4799 Data.IgnoreDecls.push_back(VD);
4800
4801 CodeCompleteExpression(S, Data);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004802}
4803
4804void Sema::CodeCompleteReturn(Scope *S) {
4805 QualType ResultType;
4806 if (isa<BlockDecl>(CurContext)) {
4807 if (BlockScopeInfo *BSI = getCurBlock())
4808 ResultType = BSI->ReturnType;
Fangrui Song050229d2018-11-24 00:14:31 +00004809 } else if (const auto *Function = dyn_cast<FunctionDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004810 ResultType = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00004811 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00004812 ResultType = Method->getReturnType();
4813
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004814 if (ResultType.isNull())
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004815 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004816 else
4817 CodeCompleteExpression(S, ResultType);
4818}
4819
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004820void Sema::CodeCompleteAfterIf(Scope *S) {
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004821 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004822 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004823 mapCodeCompletionContext(*this, PCC_Statement));
4824 Results.setFilter(&ResultBuilder::IsOrdinaryName);
4825 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004826
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004827 CodeCompletionDeclConsumer Consumer(Results, CurContext);
4828 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004829 CodeCompleter->includeGlobals(),
4830 CodeCompleter->loadExternal());
4831
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004832 AddOrdinaryNameResults(PCC_Statement, S, *this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004833
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004834 // "else" block
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004835 CodeCompletionBuilder Builder(Results.getAllocator(),
4836 Results.getCodeCompletionTUInfo());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004837 Builder.AddTypedTextChunk("else");
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004838 if (Results.includeCodePatterns()) {
4839 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4840 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4841 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4842 Builder.AddPlaceholderChunk("statements");
4843 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4844 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4845 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004846 Results.AddResult(Builder.TakeString());
4847
4848 // "else if" block
4849 Builder.AddTypedTextChunk("else");
4850 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4851 Builder.AddTextChunk("if");
4852 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4853 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00004854 if (getLangOpts().CPlusPlus)
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004855 Builder.AddPlaceholderChunk("condition");
4856 else
4857 Builder.AddPlaceholderChunk("expression");
4858 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor3a5d6c22012-02-16 17:49:04 +00004859 if (Results.includeCodePatterns()) {
4860 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
4861 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
4862 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4863 Builder.AddPlaceholderChunk("statements");
4864 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
4865 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
4866 }
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004867 Results.AddResult(Builder.TakeString());
4868
4869 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004870
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004871 if (S->getFnParent())
Craig Topper12126262015-11-15 17:27:57 +00004872 AddPrettyFunctionResults(getLangOpts(), Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004873
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004874 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00004875 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004876
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004877 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00004878 Results.data(), Results.size());
Douglas Gregor4ecb7202011-07-30 08:36:53 +00004879}
4880
Richard Trieu2bd04012011-09-09 02:00:50 +00004881void Sema::CodeCompleteAssignmentRHS(Scope *S, Expr *LHS) {
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004882 if (LHS)
4883 CodeCompleteExpression(S, static_cast<Expr *>(LHS)->getType());
4884 else
Douglas Gregor00c37ef2010-08-11 21:23:17 +00004885 CodeCompleteOrdinaryName(S, PCC_Expression);
Douglas Gregor7aa6b222010-05-30 01:49:25 +00004886}
4887
Jeffrey Yasskinc76498d2010-04-08 16:38:48 +00004888void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS,
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004889 bool EnteringContext, QualType BaseType) {
Eric Liu06d34022017-12-12 11:35:46 +00004890 if (SS.isEmpty() || !CodeCompleter)
Douglas Gregor2436e712009-09-17 21:32:03 +00004891 return;
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004892
Eric Liu06d34022017-12-12 11:35:46 +00004893 // We want to keep the scope specifier even if it's invalid (e.g. the scope
4894 // "a::b::" is not corresponding to any context/namespace in the AST), since
4895 // it can be useful for global code completion which have information about
4896 // contexts/symbols that are not in the AST.
4897 if (SS.isInvalid()) {
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004898 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol);
Eric Liu06d34022017-12-12 11:35:46 +00004899 CC.setCXXScopeSpecifier(SS);
4900 HandleCodeCompleteResults(this, CodeCompleter, CC, nullptr, 0);
4901 return;
4902 }
Alex Lorenz8a7a4cf2017-06-15 21:40:54 +00004903 // Always pretend to enter a context to ensure that a dependent type
4904 // resolves to a dependent record.
4905 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true);
Douglas Gregor3545ff42009-09-21 16:56:56 +00004906 if (!Ctx)
4907 return;
Douglas Gregor800f2f02009-12-11 18:28:39 +00004908
4909 // Try to instantiate any non-dependent declaration contexts before
4910 // we look in them.
John McCall0b66eb32010-05-01 00:40:08 +00004911 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx))
Douglas Gregor800f2f02009-12-11 18:28:39 +00004912 return;
4913
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004914 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004915 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004916 CodeCompletionContext::CCC_Symbol);
Douglas Gregorac322ec2010-08-27 21:18:54 +00004917 Results.EnterNewScope();
Eric Liu06d34022017-12-12 11:35:46 +00004918
Douglas Gregor3545ff42009-09-21 16:56:56 +00004919 // The "template" keyword can follow "::" in the grammar, but only
4920 // put it into the grammar if the nested-name-specifier is dependent.
Aaron Ballman4a979672014-01-03 13:56:08 +00004921 NestedNameSpecifier *NNS = SS.getScopeRep();
Douglas Gregor3545ff42009-09-21 16:56:56 +00004922 if (!Results.empty() && NNS->isDependent())
Douglas Gregor78a21012010-01-14 16:01:26 +00004923 Results.AddResult("template");
Douglas Gregorac322ec2010-08-27 21:18:54 +00004924
4925 // Add calls to overridden virtual functions, if there are any.
4926 //
4927 // FIXME: This isn't wonderful, because we don't know whether we're actually
4928 // in a context that permits expressions. This is a general issue with
4929 // qualified-id completions.
4930 if (!EnteringContext)
4931 MaybeAddOverrideCalls(*this, Ctx, Results);
Eric Liu06d34022017-12-12 11:35:46 +00004932 Results.ExitScope();
4933
Eric Liufead6ae2017-12-13 10:26:49 +00004934 if (CodeCompleter->includeNamespaceLevelDecls() ||
4935 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00004936 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType);
Eric Liufead6ae2017-12-13 10:26:49 +00004937 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer,
4938 /*IncludeGlobalScope=*/true,
Sam McCallbb2cf632018-01-12 14:51:47 +00004939 /*IncludeDependentBases=*/true,
4940 CodeCompleter->loadExternal());
Eric Liufead6ae2017-12-13 10:26:49 +00004941 }
Douglas Gregorac322ec2010-08-27 21:18:54 +00004942
Eric Liu06d34022017-12-12 11:35:46 +00004943 auto CC = Results.getCompletionContext();
4944 CC.setCXXScopeSpecifier(SS);
4945
4946 HandleCodeCompleteResults(this, CodeCompleter, CC, Results.data(),
4947 Results.size());
Douglas Gregor2436e712009-09-17 21:32:03 +00004948}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004949
4950void Sema::CodeCompleteUsing(Scope *S) {
4951 if (!CodeCompleter)
4952 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004953
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004954 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004955 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00004956 // This can be both a using alias or using
4957 // declaration, in the former we expect a new name and a
4958 // symbol in the latter case.
4959 CodeCompletionContext::CCC_SymbolOrNewName,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004960 &ResultBuilder::IsNestedNameSpecifier);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004961 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004962
Douglas Gregor3545ff42009-09-21 16:56:56 +00004963 // If we aren't in class scope, we could see the "namespace" keyword.
4964 if (!S->isClassScope())
John McCall276321a2010-08-25 06:19:51 +00004965 Results.AddResult(CodeCompletionResult("namespace"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004966
4967 // After "using", we can see anything that would start a
Douglas Gregor3545ff42009-09-21 16:56:56 +00004968 // nested-name-specifier.
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004969 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004970 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004971 CodeCompleter->includeGlobals(),
4972 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004973 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004974
4975 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4976 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004977}
4978
4979void Sema::CodeCompleteUsingDirective(Scope *S) {
4980 if (!CodeCompleter)
4981 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00004982
Douglas Gregor3545ff42009-09-21 16:56:56 +00004983 // After "using namespace", we expect to see a namespace name or namespace
4984 // alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004985 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00004986 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00004987 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00004988 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregor64b12b52009-09-22 23:31:26 +00004989 Results.EnterNewScope();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00004990 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00004991 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00004992 CodeCompleter->includeGlobals(),
4993 CodeCompleter->loadExternal());
Douglas Gregor64b12b52009-09-22 23:31:26 +00004994 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00004995 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
4996 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00004997}
4998
Fangrui Song050229d2018-11-24 00:14:31 +00004999void Sema::CodeCompleteNamespaceDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005000 if (!CodeCompleter)
5001 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005002
Ted Kremenekc37877d2013-10-08 17:08:03 +00005003 DeclContext *Ctx = S->getEntity();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005004 if (!S->getParent())
5005 Ctx = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005006
Fangrui Song050229d2018-11-24 00:14:31 +00005007 bool SuppressedGlobalResults =
5008 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005009
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005010 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005011 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00005012 SuppressedGlobalResults
Fangrui Song050229d2018-11-24 00:14:31 +00005013 ? CodeCompletionContext::CCC_Namespace
5014 : CodeCompletionContext::CCC_Other,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005015 &ResultBuilder::IsNamespace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005016
Douglas Gregor0ac41382010-09-23 23:01:17 +00005017 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00005018 // We only want to see those namespaces that have already been defined
5019 // within this scope, because its likely that the user is creating an
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005020 // extended namespace declaration. Keep track of the most recent
Douglas Gregor3545ff42009-09-21 16:56:56 +00005021 // definition of each namespace.
5022 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005023 for (DeclContext::specific_decl_iterator<NamespaceDecl>
Fangrui Song050229d2018-11-24 00:14:31 +00005024 NS(Ctx->decls_begin()),
5025 NSEnd(Ctx->decls_end());
Douglas Gregor3545ff42009-09-21 16:56:56 +00005026 NS != NSEnd; ++NS)
David Blaikie40ed2972012-06-06 20:45:41 +00005027 OrigToLatest[NS->getOriginalNamespace()] = *NS;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005028
5029 // Add the most recent definition (or extended definition) of each
Douglas Gregor3545ff42009-09-21 16:56:56 +00005030 // namespace to the list of results.
Douglas Gregor64b12b52009-09-22 23:31:26 +00005031 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005032 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator
Fangrui Song050229d2018-11-24 00:14:31 +00005033 NS = OrigToLatest.begin(),
5034 NSEnd = OrigToLatest.end();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005035 NS != NSEnd; ++NS)
Fangrui Song050229d2018-11-24 00:14:31 +00005036 Results.AddResult(
5037 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second),
5038 nullptr),
5039 CurContext, nullptr, false);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005040 Results.ExitScope();
Douglas Gregor3545ff42009-09-21 16:56:56 +00005041 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005042
Fangrui Song050229d2018-11-24 00:14:31 +00005043 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5044 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005045}
5046
Fangrui Song050229d2018-11-24 00:14:31 +00005047void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) {
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005048 if (!CodeCompleter)
5049 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005050
Douglas Gregor3545ff42009-09-21 16:56:56 +00005051 // After "namespace", we expect to see a namespace or alias.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005052 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005053 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005054 CodeCompletionContext::CCC_Namespace,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005055 &ResultBuilder::IsNamespaceOrAlias);
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005056 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005057 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005058 CodeCompleter->includeGlobals(),
5059 CodeCompleter->loadExternal());
Fangrui Song050229d2018-11-24 00:14:31 +00005060 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5061 Results.data(), Results.size());
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005062}
5063
Douglas Gregorc811ede2009-09-18 20:05:18 +00005064void Sema::CodeCompleteOperatorName(Scope *S) {
5065 if (!CodeCompleter)
5066 return;
Douglas Gregor3545ff42009-09-21 16:56:56 +00005067
John McCall276321a2010-08-25 06:19:51 +00005068 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005069 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005070 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005071 CodeCompletionContext::CCC_Type,
Douglas Gregor0ac41382010-09-23 23:01:17 +00005072 &ResultBuilder::IsType);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005073 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005074
Douglas Gregor3545ff42009-09-21 16:56:56 +00005075 // Add the names of overloadable operators.
Fangrui Song050229d2018-11-24 00:14:31 +00005076#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
5077 if (std::strcmp(Spelling, "?")) \
Douglas Gregor78a21012010-01-14 16:01:26 +00005078 Results.AddResult(Result(Spelling));
Douglas Gregor3545ff42009-09-21 16:56:56 +00005079#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005080
Douglas Gregor3545ff42009-09-21 16:56:56 +00005081 // Add any type names visible from the current scope
Douglas Gregor6ae4c522010-01-14 03:21:49 +00005082 Results.allowNestedNameSpecifiers();
Douglas Gregora6e2edc2010-01-14 03:27:13 +00005083 CodeCompletionDeclConsumer Consumer(Results, CurContext);
Douglas Gregor39982192010-08-15 06:18:01 +00005084 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005085 CodeCompleter->includeGlobals(),
5086 CodeCompleter->loadExternal());
5087
Douglas Gregor3545ff42009-09-21 16:56:56 +00005088 // Add any type specifiers
David Blaikiebbafb8a2012-03-11 07:00:24 +00005089 AddTypeSpecifierResults(getLangOpts(), Results);
Douglas Gregor64b12b52009-09-22 23:31:26 +00005090 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005091
5092 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5093 Results.data(), Results.size());
Douglas Gregorc811ede2009-09-18 20:05:18 +00005094}
Douglas Gregor7e90c6d2009-09-18 19:03:04 +00005095
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005096void Sema::CodeCompleteConstructorInitializer(
Fangrui Song050229d2018-11-24 00:14:31 +00005097 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) {
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005098 if (!ConstructorD)
5099 return;
5100
5101 AdjustDeclIfTemplate(ConstructorD);
5102
Fangrui Song050229d2018-11-24 00:14:31 +00005103 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005104 if (!Constructor)
5105 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005106
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005107 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005108 CodeCompleter->getCodeCompletionTUInfo(),
Kadir Cetinkayab006e092018-10-24 15:23:49 +00005109 CodeCompletionContext::CCC_Symbol);
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005110 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005111
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005112 // Fill in any already-initialized fields or base classes.
5113 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields;
5114 llvm::SmallPtrSet<CanQualType, 4> InitializedBases;
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005115 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) {
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005116 if (Initializers[I]->isBaseInitializer())
Fangrui Song050229d2018-11-24 00:14:31 +00005117 InitializedBases.insert(Context.getCanonicalType(
5118 QualType(Initializers[I]->getBaseClass(), 0)));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005119 else
Fangrui Song050229d2018-11-24 00:14:31 +00005120 InitializedFields.insert(
5121 cast<FieldDecl>(Initializers[I]->getAnyMember()));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005122 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005123
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005124 // Add completions for base classes.
Benjamin Kramera4f8df02015-07-09 15:31:10 +00005125 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Dmitri Gribenko27cb3dd02013-06-23 22:58:02 +00005126 bool SawLastInitializer = Initializers.empty();
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005127 CXXRecordDecl *ClassDecl = Constructor->getParent();
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005128
5129 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) {
5130 CodeCompletionBuilder Builder(Results.getAllocator(),
5131 Results.getCodeCompletionTUInfo());
5132 Builder.AddTypedTextChunk(Name);
5133 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Fangrui Song050229d2018-11-24 00:14:31 +00005134 if (const auto *Function = dyn_cast<FunctionDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005135 AddFunctionParameterChunks(PP, Policy, Function, Builder);
Fangrui Song050229d2018-11-24 00:14:31 +00005136 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND))
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005137 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(),
5138 Builder);
5139 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5140 return Builder.TakeString();
5141 };
5142 auto AddDefaultCtorInit = [&](const char *Name, const char *Type,
5143 const NamedDecl *ND) {
5144 CodeCompletionBuilder Builder(Results.getAllocator(),
5145 Results.getCodeCompletionTUInfo());
5146 Builder.AddTypedTextChunk(Name);
5147 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5148 Builder.AddPlaceholderChunk(Type);
5149 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5150 if (ND) {
5151 auto CCR = CodeCompletionResult(
5152 Builder.TakeString(), ND,
5153 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration);
5154 if (isa<FieldDecl>(ND))
5155 CCR.CursorKind = CXCursor_MemberRef;
5156 return Results.AddResult(CCR);
5157 }
5158 return Results.AddResult(CodeCompletionResult(
5159 Builder.TakeString(),
5160 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration));
5161 };
5162 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority,
5163 const char *Name, const FieldDecl *FD) {
5164 if (!RD)
5165 return AddDefaultCtorInit(Name,
5166 FD ? Results.getAllocator().CopyString(
5167 FD->getType().getAsString(Policy))
5168 : Name,
5169 FD);
5170 auto Ctors = getConstructors(Context, RD);
5171 if (Ctors.begin() == Ctors.end())
5172 return AddDefaultCtorInit(Name, Name, RD);
Fangrui Song050229d2018-11-24 00:14:31 +00005173 for (const NamedDecl *Ctor : Ctors) {
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005174 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority);
5175 CCR.CursorKind = getCursorKindForDecl(Ctor);
5176 Results.AddResult(CCR);
5177 }
5178 };
5179 auto AddBase = [&](const CXXBaseSpecifier &Base) {
5180 const char *BaseName =
5181 Results.getAllocator().CopyString(Base.getType().getAsString(Policy));
5182 const auto *RD = Base.getType()->getAsCXXRecordDecl();
5183 AddCtorsWithName(
5184 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5185 BaseName, nullptr);
5186 };
5187 auto AddField = [&](const FieldDecl *FD) {
5188 const char *FieldName =
5189 Results.getAllocator().CopyString(FD->getIdentifier()->getName());
5190 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl();
5191 AddCtorsWithName(
5192 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration,
5193 FieldName, FD);
5194 };
5195
Aaron Ballman574705e2014-03-13 15:41:46 +00005196 for (const auto &Base : ClassDecl->bases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005197 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5198 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005199 SawLastInitializer =
5200 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5201 Context.hasSameUnqualifiedType(
5202 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005203 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005204 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005205
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005206 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005207 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005208 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005209
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005210 // Add completions for virtual base classes.
Aaron Ballman445a9392014-03-13 16:15:17 +00005211 for (const auto &Base : ClassDecl->vbases()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005212 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType()))
5213 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005214 SawLastInitializer =
5215 !Initializers.empty() && Initializers.back()->isBaseInitializer() &&
5216 Context.hasSameUnqualifiedType(
5217 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0));
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005218 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005219 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005220
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005221 AddBase(Base);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005222 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005223 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005224
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005225 // Add completions for members.
Aaron Ballmane8a8bae2014-03-08 20:12:42 +00005226 for (auto *Field : ClassDecl->fields()) {
David Blaikie82e95a32014-11-19 07:49:47 +00005227 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl()))
5228 .second) {
Fangrui Song050229d2018-11-24 00:14:31 +00005229 SawLastInitializer = !Initializers.empty() &&
5230 Initializers.back()->isAnyMemberInitializer() &&
5231 Initializers.back()->getAnyMember() == Field;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005232 continue;
Douglas Gregor99129ef2010-08-29 19:27:27 +00005233 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005234
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005235 if (!Field->getDeclName())
5236 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005237
Kadir Cetinkayafabaaaa2018-11-01 15:54:18 +00005238 AddField(Field);
Douglas Gregor99129ef2010-08-29 19:27:27 +00005239 SawLastInitializer = false;
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005240 }
5241 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005242
Douglas Gregor0ac41382010-09-23 23:01:17 +00005243 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregoreaeeca92010-08-28 00:00:50 +00005244 Results.data(), Results.size());
5245}
5246
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005247/// Determine whether this scope denotes a namespace.
Douglas Gregord8c61782012-02-15 15:34:24 +00005248static bool isNamespaceScope(Scope *S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00005249 DeclContext *DC = S->getEntity();
Douglas Gregord8c61782012-02-15 15:34:24 +00005250 if (!DC)
5251 return false;
5252
5253 return DC->isFileContext();
5254}
5255
5256void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro,
5257 bool AfterAmpersand) {
5258 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005259 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregord8c61782012-02-15 15:34:24 +00005260 CodeCompletionContext::CCC_Other);
5261 Results.EnterNewScope();
5262
5263 // Note what has already been captured.
5264 llvm::SmallPtrSet<IdentifierInfo *, 4> Known;
5265 bool IncludedThis = false;
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005266 for (const auto &C : Intro.Captures) {
5267 if (C.Kind == LCK_This) {
Douglas Gregord8c61782012-02-15 15:34:24 +00005268 IncludedThis = true;
5269 continue;
5270 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005271
Benjamin Kramerf3ca26982014-05-10 16:31:55 +00005272 Known.insert(C.Id);
Douglas Gregord8c61782012-02-15 15:34:24 +00005273 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005274
Douglas Gregord8c61782012-02-15 15:34:24 +00005275 // Look for other capturable variables.
5276 for (; S && !isNamespaceScope(S); S = S->getParent()) {
Aaron Ballman35c54952014-03-17 16:55:25 +00005277 for (const auto *D : S->decls()) {
5278 const auto *Var = dyn_cast<VarDecl>(D);
Fangrui Song050229d2018-11-24 00:14:31 +00005279 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>())
Douglas Gregord8c61782012-02-15 15:34:24 +00005280 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005281
David Blaikie82e95a32014-11-19 07:49:47 +00005282 if (Known.insert(Var->getIdentifier()).second)
Douglas Gregor0a0e2b32013-01-31 04:52:16 +00005283 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration),
Craig Topperc3ec1492014-05-26 06:22:03 +00005284 CurContext, nullptr, false);
Douglas Gregord8c61782012-02-15 15:34:24 +00005285 }
5286 }
5287
5288 // Add 'this', if it would be valid.
5289 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy)
5290 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005291
Douglas Gregord8c61782012-02-15 15:34:24 +00005292 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005293
Douglas Gregord8c61782012-02-15 15:34:24 +00005294 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5295 Results.data(), Results.size());
5296}
5297
James Dennett596e4752012-06-14 03:11:41 +00005298/// Macro that optionally prepends an "@" to the string literal passed in via
5299/// Keyword, depending on whether NeedAt is true or false.
Fangrui Song050229d2018-11-24 00:14:31 +00005300#define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword)
James Dennett596e4752012-06-14 03:11:41 +00005301
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005302static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005303 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005304 typedef CodeCompletionResult Result;
Douglas Gregorf1934162010-01-13 21:24:21 +00005305 // Since we have an implementation, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005306 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005307
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005308 CodeCompletionBuilder Builder(Results.getAllocator(),
5309 Results.getCodeCompletionTUInfo());
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005310 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005311 // @dynamic
Fangrui Song050229d2018-11-24 00:14:31 +00005312 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005313 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5314 Builder.AddPlaceholderChunk("property");
5315 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005316
Douglas Gregorf1934162010-01-13 21:24:21 +00005317 // @synthesize
Fangrui Song050229d2018-11-24 00:14:31 +00005318 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005319 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5320 Builder.AddPlaceholderChunk("property");
5321 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005322 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005323}
5324
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005325static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005326 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005327 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005328
Douglas Gregorf1934162010-01-13 21:24:21 +00005329 // Since we have an interface or protocol, we can end it.
Fangrui Song050229d2018-11-24 00:14:31 +00005330 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005331
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005332 if (LangOpts.ObjC) {
Douglas Gregorf1934162010-01-13 21:24:21 +00005333 // @property
Fangrui Song050229d2018-11-24 00:14:31 +00005334 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005335
Douglas Gregorf1934162010-01-13 21:24:21 +00005336 // @required
Fangrui Song050229d2018-11-24 00:14:31 +00005337 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required")));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005338
Douglas Gregorf1934162010-01-13 21:24:21 +00005339 // @optional
Fangrui Song050229d2018-11-24 00:14:31 +00005340 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional")));
Douglas Gregorf1934162010-01-13 21:24:21 +00005341 }
5342}
5343
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005344static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005345 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005346 CodeCompletionBuilder Builder(Results.getAllocator(),
5347 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005348
Douglas Gregorf1934162010-01-13 21:24:21 +00005349 // @class name ;
Fangrui Song050229d2018-11-24 00:14:31 +00005350 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005351 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5352 Builder.AddPlaceholderChunk("name");
5353 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005354
Douglas Gregorf4c33342010-05-28 00:22:41 +00005355 if (Results.includeCodePatterns()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005356 // @interface name
5357 // FIXME: Could introduce the whole pattern, including superclasses and
Douglas Gregorf4c33342010-05-28 00:22:41 +00005358 // such.
Fangrui Song050229d2018-11-24 00:14:31 +00005359 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005360 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5361 Builder.AddPlaceholderChunk("class");
5362 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005363
Douglas Gregorf4c33342010-05-28 00:22:41 +00005364 // @protocol name
Fangrui Song050229d2018-11-24 00:14:31 +00005365 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005366 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5367 Builder.AddPlaceholderChunk("protocol");
5368 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005369
Douglas Gregorf4c33342010-05-28 00:22:41 +00005370 // @implementation name
Fangrui Song050229d2018-11-24 00:14:31 +00005371 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005372 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5373 Builder.AddPlaceholderChunk("class");
5374 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005375 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005376
Douglas Gregorf1934162010-01-13 21:24:21 +00005377 // @compatibility_alias name
Fangrui Song050229d2018-11-24 00:14:31 +00005378 Builder.AddTypedTextChunk(
5379 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005380 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5381 Builder.AddPlaceholderChunk("alias");
5382 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5383 Builder.AddPlaceholderChunk("class");
5384 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor61e36812013-03-07 23:26:24 +00005385
5386 if (Results.getSema().getLangOpts().Modules) {
5387 // @import name
5388 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import"));
5389 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5390 Builder.AddPlaceholderChunk("module");
5391 Results.AddResult(Result(Builder.TakeString()));
5392 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005393}
5394
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005395void Sema::CodeCompleteObjCAtDirective(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005396 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005397 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005398 CodeCompletionContext::CCC_Other);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005399 Results.EnterNewScope();
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005400 if (isa<ObjCImplDecl>(CurContext))
David Blaikiebbafb8a2012-03-11 07:00:24 +00005401 AddObjCImplementationResults(getLangOpts(), Results, false);
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005402 else if (CurContext->isObjCContainer())
David Blaikiebbafb8a2012-03-11 07:00:24 +00005403 AddObjCInterfaceResults(getLangOpts(), Results, false);
Douglas Gregorf1934162010-01-13 21:24:21 +00005404 else
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005405 AddObjCTopLevelResults(Results, false);
Douglas Gregorf48706c2009-12-07 09:27:33 +00005406 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005407 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5408 Results.data(), Results.size());
Douglas Gregorf48706c2009-12-07 09:27:33 +00005409}
5410
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005411static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005412 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005413 CodeCompletionBuilder Builder(Results.getAllocator(),
5414 Results.getCodeCompletionTUInfo());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005415
5416 // @encode ( type-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005417 const char *EncodeType = "char[]";
David Blaikiebbafb8a2012-03-11 07:00:24 +00005418 if (Results.getSema().getLangOpts().CPlusPlus ||
5419 Results.getSema().getLangOpts().ConstStrings)
Jordan Rose9da05852012-06-15 18:19:56 +00005420 EncodeType = "const char[]";
Douglas Gregore5c79d52011-10-18 21:20:17 +00005421 Builder.AddResultTypeChunk(EncodeType);
Fangrui Song050229d2018-11-24 00:14:31 +00005422 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005423 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5424 Builder.AddPlaceholderChunk("type-name");
5425 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5426 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005427
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005428 // @protocol ( protocol-name )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005429 Builder.AddResultTypeChunk("Protocol *");
Fangrui Song050229d2018-11-24 00:14:31 +00005430 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005431 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5432 Builder.AddPlaceholderChunk("protocol-name");
5433 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5434 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005435
5436 // @selector ( selector )
Douglas Gregore5c79d52011-10-18 21:20:17 +00005437 Builder.AddResultTypeChunk("SEL");
Fangrui Song050229d2018-11-24 00:14:31 +00005438 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005439 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5440 Builder.AddPlaceholderChunk("selector");
5441 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5442 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005443
5444 // @"string"
5445 Builder.AddResultTypeChunk("NSString *");
Fangrui Song050229d2018-11-24 00:14:31 +00005446 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\""));
Jordan Rose9da05852012-06-15 18:19:56 +00005447 Builder.AddPlaceholderChunk("string");
5448 Builder.AddTextChunk("\"");
5449 Results.AddResult(Result(Builder.TakeString()));
5450
Douglas Gregor951de302012-07-17 23:24:47 +00005451 // @[objects, ...]
Jordan Rose9da05852012-06-15 18:19:56 +00005452 Builder.AddResultTypeChunk("NSArray *");
Fangrui Song050229d2018-11-24 00:14:31 +00005453 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "["));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005454 Builder.AddPlaceholderChunk("objects, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005455 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
5456 Results.AddResult(Result(Builder.TakeString()));
5457
Douglas Gregor951de302012-07-17 23:24:47 +00005458 // @{key : object, ...}
Jordan Rose9da05852012-06-15 18:19:56 +00005459 Builder.AddResultTypeChunk("NSDictionary *");
Fangrui Song050229d2018-11-24 00:14:31 +00005460 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{"));
Ted Kremeneke65b0862012-03-06 20:05:56 +00005461 Builder.AddPlaceholderChunk("key");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005462 Builder.AddChunk(CodeCompletionString::CK_Colon);
5463 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5464 Builder.AddPlaceholderChunk("object, ...");
Ted Kremeneke65b0862012-03-06 20:05:56 +00005465 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5466 Results.AddResult(Result(Builder.TakeString()));
Jordan Rose9da05852012-06-15 18:19:56 +00005467
Douglas Gregor951de302012-07-17 23:24:47 +00005468 // @(expression)
Jordan Rose9da05852012-06-15 18:19:56 +00005469 Builder.AddResultTypeChunk("id");
5470 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "("));
Jordan Rose9da05852012-06-15 18:19:56 +00005471 Builder.AddPlaceholderChunk("expression");
Jordan Rose9da05852012-06-15 18:19:56 +00005472 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5473 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005474}
5475
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005476static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005477 typedef CodeCompletionResult Result;
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005478 CodeCompletionBuilder Builder(Results.getAllocator(),
5479 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005480
Douglas Gregorf4c33342010-05-28 00:22:41 +00005481 if (Results.includeCodePatterns()) {
5482 // @try { statements } @catch ( declaration ) { statements } @finally
5483 // { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005484 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005485 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5486 Builder.AddPlaceholderChunk("statements");
5487 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5488 Builder.AddTextChunk("@catch");
5489 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5490 Builder.AddPlaceholderChunk("parameter");
5491 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5492 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5493 Builder.AddPlaceholderChunk("statements");
5494 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5495 Builder.AddTextChunk("@finally");
5496 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5497 Builder.AddPlaceholderChunk("statements");
5498 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5499 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005500 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005501
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005502 // @throw
Fangrui Song050229d2018-11-24 00:14:31 +00005503 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005504 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5505 Builder.AddPlaceholderChunk("expression");
5506 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005507
Douglas Gregorf4c33342010-05-28 00:22:41 +00005508 if (Results.includeCodePatterns()) {
5509 // @synchronized ( expression ) { statements }
Fangrui Song050229d2018-11-24 00:14:31 +00005510 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized"));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005511 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
5512 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
5513 Builder.AddPlaceholderChunk("expression");
5514 Builder.AddChunk(CodeCompletionString::CK_RightParen);
5515 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
5516 Builder.AddPlaceholderChunk("statements");
5517 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
5518 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00005519 }
Douglas Gregorf1934162010-01-13 21:24:21 +00005520}
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005521
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005522static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00005523 ResultBuilder &Results, bool NeedAt) {
John McCall276321a2010-08-25 06:19:51 +00005524 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00005525 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private")));
5526 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected")));
5527 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public")));
Erik Pilkingtonfa983902018-10-30 20:31:30 +00005528 if (LangOpts.ObjC)
Fangrui Song050229d2018-11-24 00:14:31 +00005529 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package")));
Douglas Gregor48d46252010-01-13 21:54:15 +00005530}
5531
5532void Sema::CodeCompleteObjCAtVisibility(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005533 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005534 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005535 CodeCompletionContext::CCC_Other);
Douglas Gregor48d46252010-01-13 21:54:15 +00005536 Results.EnterNewScope();
David Blaikiebbafb8a2012-03-11 07:00:24 +00005537 AddObjCVisibilityResults(getLangOpts(), Results, false);
Douglas Gregor48d46252010-01-13 21:54:15 +00005538 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005539 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5540 Results.data(), Results.size());
Douglas Gregor48d46252010-01-13 21:54:15 +00005541}
5542
5543void Sema::CodeCompleteObjCAtStatement(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005544 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005545 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005546 CodeCompletionContext::CCC_Other);
Douglas Gregorf1934162010-01-13 21:24:21 +00005547 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005548 AddObjCStatementResults(Results, false);
5549 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005550 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005551 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5552 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005553}
5554
5555void Sema::CodeCompleteObjCAtExpression(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005556 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005557 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005558 CodeCompletionContext::CCC_Other);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005559 Results.EnterNewScope();
Douglas Gregorf98e6a22010-01-13 23:51:12 +00005560 AddObjCExpressionResults(Results, false);
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005561 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005562 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5563 Results.data(), Results.size());
Douglas Gregorbc7c5e42009-12-07 09:51:25 +00005564}
5565
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005566/// Determine whether the addition of the given flag to an Objective-C
Douglas Gregore6078da2009-11-19 00:14:45 +00005567/// property's attributes will cause a conflict.
Bill Wendling44426052012-12-20 19:22:21 +00005568static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) {
Douglas Gregore6078da2009-11-19 00:14:45 +00005569 // Check if we've already added this flag.
Bill Wendling44426052012-12-20 19:22:21 +00005570 if (Attributes & NewFlag)
Douglas Gregore6078da2009-11-19 00:14:45 +00005571 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005572
Bill Wendling44426052012-12-20 19:22:21 +00005573 Attributes |= NewFlag;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005574
Douglas Gregore6078da2009-11-19 00:14:45 +00005575 // Check for collisions with "readonly".
Bill Wendling44426052012-12-20 19:22:21 +00005576 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) &&
5577 (Attributes & ObjCDeclSpec::DQ_PR_readwrite))
Douglas Gregore6078da2009-11-19 00:14:45 +00005578 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005579
Jordan Rose53cb2f32012-08-20 20:01:13 +00005580 // Check for more than one of { assign, copy, retain, strong, weak }.
Fangrui Song050229d2018-11-24 00:14:31 +00005581 unsigned AssignCopyRetMask =
5582 Attributes &
5583 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained |
5584 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain |
5585 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak);
5586 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign &&
John McCall31168b02011-06-15 23:02:42 +00005587 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained &&
Douglas Gregore6078da2009-11-19 00:14:45 +00005588 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy &&
John McCall31168b02011-06-15 23:02:42 +00005589 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain &&
Jordan Rose53cb2f32012-08-20 20:01:13 +00005590 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong &&
5591 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak)
Douglas Gregore6078da2009-11-19 00:14:45 +00005592 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005593
Douglas Gregore6078da2009-11-19 00:14:45 +00005594 return false;
5595}
5596
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005597void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) {
Steve Naroff936354c2009-10-08 21:55:05 +00005598 if (!CodeCompleter)
5599 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005600
Bill Wendling44426052012-12-20 19:22:21 +00005601 unsigned Attributes = ODS.getPropertyAttributes();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005602
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005603 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005604 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005605 CodeCompletionContext::CCC_Other);
Steve Naroff936354c2009-10-08 21:55:05 +00005606 Results.EnterNewScope();
Bill Wendling44426052012-12-20 19:22:21 +00005607 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly))
John McCall276321a2010-08-25 06:19:51 +00005608 Results.AddResult(CodeCompletionResult("readonly"));
Bill Wendling44426052012-12-20 19:22:21 +00005609 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign))
John McCall276321a2010-08-25 06:19:51 +00005610 Results.AddResult(CodeCompletionResult("assign"));
Bill Wendling44426052012-12-20 19:22:21 +00005611 if (!ObjCPropertyFlagConflicts(Attributes,
John McCall31168b02011-06-15 23:02:42 +00005612 ObjCDeclSpec::DQ_PR_unsafe_unretained))
5613 Results.AddResult(CodeCompletionResult("unsafe_unretained"));
Bill Wendling44426052012-12-20 19:22:21 +00005614 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite))
John McCall276321a2010-08-25 06:19:51 +00005615 Results.AddResult(CodeCompletionResult("readwrite"));
Bill Wendling44426052012-12-20 19:22:21 +00005616 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain))
John McCall276321a2010-08-25 06:19:51 +00005617 Results.AddResult(CodeCompletionResult("retain"));
Bill Wendling44426052012-12-20 19:22:21 +00005618 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong))
John McCall31168b02011-06-15 23:02:42 +00005619 Results.AddResult(CodeCompletionResult("strong"));
Bill Wendling44426052012-12-20 19:22:21 +00005620 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy))
John McCall276321a2010-08-25 06:19:51 +00005621 Results.AddResult(CodeCompletionResult("copy"));
Bill Wendling44426052012-12-20 19:22:21 +00005622 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic))
John McCall276321a2010-08-25 06:19:51 +00005623 Results.AddResult(CodeCompletionResult("nonatomic"));
Bill Wendling44426052012-12-20 19:22:21 +00005624 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic))
Fariborz Jahanian1c2d29e2011-06-11 17:14:27 +00005625 Results.AddResult(CodeCompletionResult("atomic"));
Jordan Rose53cb2f32012-08-20 20:01:13 +00005626
5627 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC.
John McCall460ce582015-10-22 18:38:17 +00005628 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC)
Bill Wendling44426052012-12-20 19:22:21 +00005629 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak))
Jordan Rose53cb2f32012-08-20 20:01:13 +00005630 Results.AddResult(CodeCompletionResult("weak"));
5631
Bill Wendling44426052012-12-20 19:22:21 +00005632 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005633 CodeCompletionBuilder Setter(Results.getAllocator(),
5634 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005635 Setter.AddTypedTextChunk("setter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005636 Setter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005637 Setter.AddPlaceholderChunk("method");
5638 Results.AddResult(CodeCompletionResult(Setter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005639 }
Bill Wendling44426052012-12-20 19:22:21 +00005640 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005641 CodeCompletionBuilder Getter(Results.getAllocator(),
5642 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005643 Getter.AddTypedTextChunk("getter");
Argyrios Kyrtzidis7bbb8812014-02-20 07:55:15 +00005644 Getter.AddTextChunk("=");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005645 Getter.AddPlaceholderChunk("method");
5646 Results.AddResult(CodeCompletionResult(Getter.TakeString()));
Douglas Gregor45f83ee2009-11-19 00:01:57 +00005647 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005648 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) {
5649 Results.AddResult(CodeCompletionResult("nonnull"));
5650 Results.AddResult(CodeCompletionResult("nullable"));
5651 Results.AddResult(CodeCompletionResult("null_unspecified"));
5652 Results.AddResult(CodeCompletionResult("null_resettable"));
5653 }
Steve Naroff936354c2009-10-08 21:55:05 +00005654 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005655 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5656 Results.data(), Results.size());
Steve Naroff936354c2009-10-08 21:55:05 +00005657}
Steve Naroffeae65032009-11-07 02:08:14 +00005658
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005659/// Describes the kind of Objective-C method that we want to find
Douglas Gregorc8537c52009-11-19 07:41:15 +00005660/// via code completion.
5661enum ObjCMethodKind {
Dmitri Gribenko4280e5c2012-06-08 23:13:42 +00005662 MK_Any, ///< Any kind of method, provided it means other specified criteria.
5663 MK_ZeroArgSelector, ///< Zero-argument (unary) selector.
Fangrui Song050229d2018-11-24 00:14:31 +00005664 MK_OneArgSelector ///< One-argument selector.
Douglas Gregorc8537c52009-11-19 07:41:15 +00005665};
5666
Fangrui Song050229d2018-11-24 00:14:31 +00005667static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005668 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005669 bool AllowSameLength = true) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005670 unsigned NumSelIdents = SelIdents.size();
Douglas Gregor67c692c2010-08-26 15:07:07 +00005671 if (NumSelIdents > Sel.getNumArgs())
5672 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005673
Douglas Gregor67c692c2010-08-26 15:07:07 +00005674 switch (WantKind) {
Fangrui Song050229d2018-11-24 00:14:31 +00005675 case MK_Any:
5676 break;
5677 case MK_ZeroArgSelector:
5678 return Sel.isUnarySelector();
5679 case MK_OneArgSelector:
5680 return Sel.getNumArgs() == 1;
Douglas Gregor67c692c2010-08-26 15:07:07 +00005681 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005682
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005683 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs())
5684 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005685
Douglas Gregor67c692c2010-08-26 15:07:07 +00005686 for (unsigned I = 0; I != NumSelIdents; ++I)
5687 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I))
5688 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005689
Douglas Gregor67c692c2010-08-26 15:07:07 +00005690 return true;
5691}
5692
Douglas Gregorc8537c52009-11-19 07:41:15 +00005693static bool isAcceptableObjCMethod(ObjCMethodDecl *Method,
5694 ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005695 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005696 bool AllowSameLength = true) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00005697 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005698 AllowSameLength);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005699}
Douglas Gregor1154e272010-09-16 16:06:31 +00005700
Fangrui Song050229d2018-11-24 00:14:31 +00005701/// A set of selectors, which is used to avoid introducing multiple
5702/// completions with the same selector into the result set.
5703typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet;
Douglas Gregor1154e272010-09-16 16:06:31 +00005704
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005705/// Add all of the Objective-C methods in the given Objective-C
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005706/// container to the set of results.
5707///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005708/// The container will be a class, protocol, category, or implementation of
5709/// any of the above. This mether will recurse to include methods from
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005710/// the superclasses of classes along with their categories, protocols, and
5711/// implementations.
5712///
5713/// \param Container the container in which we'll look to find methods.
5714///
James Dennett596e4752012-06-14 03:11:41 +00005715/// \param WantInstanceMethods Whether to add instance methods (only); if
5716/// false, this routine will add factory methods (only).
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005717///
5718/// \param CurContext the context in which we're performing the lookup that
5719/// finds methods.
5720///
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005721/// \param AllowSameLength Whether we allow a method to be added to the list
5722/// when it has the same number of parameters as we have selector identifiers.
5723///
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005724/// \param Results the structure into which we'll add results.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005725static void AddObjCMethods(ObjCContainerDecl *Container,
5726 bool WantInstanceMethods, ObjCMethodKind WantKind,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005727 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005728 DeclContext *CurContext,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005729 VisitedSelectorSet &Selectors, bool AllowSameLength,
5730 ResultBuilder &Results, bool InOriginalClass = true,
5731 bool IsRootClass = false) {
John McCall276321a2010-08-25 06:19:51 +00005732 typedef CodeCompletionResult Result;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00005733 Container = getContainerDef(Container);
Douglas Gregor41778c32013-01-30 06:58:39 +00005734 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container);
Alex Lorenz638dbc32017-01-24 14:15:08 +00005735 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass());
Fangrui Song050229d2018-11-24 00:14:31 +00005736 for (ObjCMethodDecl *M : Container->methods()) {
Douglas Gregor41778c32013-01-30 06:58:39 +00005737 // The instance methods on the root class can be messaged via the
5738 // metaclass.
5739 if (M->isInstanceMethod() == WantInstanceMethods ||
Alex Lorenz638dbc32017-01-24 14:15:08 +00005740 (IsRootClass && !WantInstanceMethods)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005741 // Check whether the selector identifiers we've been given are a
Douglas Gregor1b605f72009-11-19 01:08:35 +00005742 // subset of the identifiers for this particular method.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00005743 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength))
Douglas Gregor1b605f72009-11-19 01:08:35 +00005744 continue;
Douglas Gregorc8537c52009-11-19 07:41:15 +00005745
David Blaikie82e95a32014-11-19 07:49:47 +00005746 if (!Selectors.insert(M->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00005747 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00005748
5749 Result R = Result(M, Results.getBasePriority(M), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005750 R.StartParameter = SelIdents.size();
Douglas Gregorc8537c52009-11-19 07:41:15 +00005751 R.AllParametersAreInformative = (WantKind != MK_Any);
Douglas Gregor416b5752010-08-25 01:08:01 +00005752 if (!InOriginalClass)
Eric Liu4a7cd632018-10-24 12:57:27 +00005753 setInBaseClass(R);
Douglas Gregor1b605f72009-11-19 01:08:35 +00005754 Results.MaybeAddResult(R, CurContext);
5755 }
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005756 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005757
Douglas Gregorf37c9492010-09-16 15:34:59 +00005758 // Visit the protocols of protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005759 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregore6e48b12012-01-01 19:29:29 +00005760 if (Protocol->hasDefinition()) {
Fangrui Song050229d2018-11-24 00:14:31 +00005761 const ObjCList<ObjCProtocolDecl> &Protocols =
5762 Protocol->getReferencedProtocols();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005763 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005764 E = Protocols.end();
Douglas Gregore6e48b12012-01-01 19:29:29 +00005765 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005766 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5767 Selectors, AllowSameLength, Results, false, IsRootClass);
Douglas Gregore6e48b12012-01-01 19:29:29 +00005768 }
Douglas Gregorf37c9492010-09-16 15:34:59 +00005769 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005770
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00005771 if (!IFace || !IFace->hasDefinition())
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005772 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005773
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005774 // Add methods in protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00005775 for (ObjCProtocolDecl *I : IFace->protocols())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005776 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5777 Selectors, AllowSameLength, Results, false, IsRootClass);
5778
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005779 // Add methods in categories.
Fangrui Song050229d2018-11-24 00:14:31 +00005780 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00005781 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents,
Alex Lorenz638dbc32017-01-24 14:15:08 +00005782 CurContext, Selectors, AllowSameLength, Results,
5783 InOriginalClass, IsRootClass);
5784
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005785 // Add a categories protocol methods.
Fangrui Song050229d2018-11-24 00:14:31 +00005786 const ObjCList<ObjCProtocolDecl> &Protocols =
5787 CatDecl->getReferencedProtocols();
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005788 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
5789 E = Protocols.end();
5790 I != E; ++I)
Alex Lorenz638dbc32017-01-24 14:15:08 +00005791 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext,
5792 Selectors, AllowSameLength, Results, false, IsRootClass);
5793
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005794 // Add methods in category implementations.
5795 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005796 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5797 Selectors, AllowSameLength, Results, InOriginalClass,
5798 IsRootClass);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005799 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005800
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005801 // Add methods in superclass.
Alex Lorenz638dbc32017-01-24 14:15:08 +00005802 // Avoid passing in IsRootClass since root classes won't have super classes.
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005803 if (IFace->getSuperClass())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005804 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind,
5805 SelIdents, CurContext, Selectors, AllowSameLength, Results,
5806 /*IsRootClass=*/false);
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005807
5808 // Add methods in our implementation, if any.
5809 if (ObjCImplementationDecl *Impl = IFace->getImplementation())
Alex Lorenz638dbc32017-01-24 14:15:08 +00005810 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext,
5811 Selectors, AllowSameLength, Results, InOriginalClass,
5812 IsRootClass);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005813}
5814
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005815void Sema::CodeCompleteObjCPropertyGetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005816 // Try to find the interface where getters might live.
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005817 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005818 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00005819 if (ObjCCategoryDecl *Category =
5820 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005821 Class = Category->getClassInterface();
5822
5823 if (!Class)
5824 return;
5825 }
5826
5827 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005828 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005829 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005830 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005831 Results.EnterNewScope();
5832
Douglas Gregor1154e272010-09-16 16:06:31 +00005833 VisitedSelectorSet Selectors;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00005834 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors,
Douglas Gregorb4a7c032010-11-17 21:36:08 +00005835 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005836 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005837 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5838 Results.data(), Results.size());
Douglas Gregorc8537c52009-11-19 07:41:15 +00005839}
5840
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00005841void Sema::CodeCompleteObjCPropertySetter(Scope *S) {
Douglas Gregorc8537c52009-11-19 07:41:15 +00005842 // Try to find the interface where setters might live.
Fangrui Song050229d2018-11-24 00:14:31 +00005843 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005844 if (!Class) {
Fangrui Song050229d2018-11-24 00:14:31 +00005845 if (ObjCCategoryDecl *Category =
5846 dyn_cast_or_null<ObjCCategoryDecl>(CurContext))
Douglas Gregorc8537c52009-11-19 07:41:15 +00005847 Class = Category->getClassInterface();
5848
5849 if (!Class)
5850 return;
5851 }
5852
5853 // Find all of the potential getters.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005854 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005855 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005856 CodeCompletionContext::CCC_Other);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005857 Results.EnterNewScope();
5858
Douglas Gregor1154e272010-09-16 16:06:31 +00005859 VisitedSelectorSet Selectors;
Fangrui Song050229d2018-11-24 00:14:31 +00005860 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors,
5861 /*AllowSameLength=*/true, Results);
Douglas Gregorc8537c52009-11-19 07:41:15 +00005862
5863 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00005864 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
5865 Results.data(), Results.size());
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00005866}
5867
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005868void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS,
5869 bool IsParameter) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005870 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005871 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00005872 CodeCompletionContext::CCC_Type);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005873 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005874
Douglas Gregor99fa2642010-08-24 01:06:58 +00005875 // Add context-sensitive, Objective-C parameter-passing keywords.
5876 bool AddedInOut = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005877 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005878 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) {
5879 Results.AddResult("in");
5880 Results.AddResult("inout");
5881 AddedInOut = true;
5882 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005883 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005884 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) {
5885 Results.AddResult("out");
5886 if (!AddedInOut)
5887 Results.AddResult("inout");
5888 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005889 if ((DS.getObjCDeclQualifier() &
Douglas Gregor99fa2642010-08-24 01:06:58 +00005890 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref |
5891 ObjCDeclSpec::DQ_Oneway)) == 0) {
Fangrui Song050229d2018-11-24 00:14:31 +00005892 Results.AddResult("bycopy");
5893 Results.AddResult("byref");
5894 Results.AddResult("oneway");
Douglas Gregor99fa2642010-08-24 01:06:58 +00005895 }
Douglas Gregor86b42682015-06-19 18:27:52 +00005896 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) {
5897 Results.AddResult("nonnull");
5898 Results.AddResult("nullable");
5899 Results.AddResult("null_unspecified");
5900 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005901
5902 // If we're completing the return type of an Objective-C method and the
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005903 // identifier IBAction refers to a macro, provide a completion item for
5904 // an action, e.g.,
5905 // IBAction)<#selector#>:(id)sender
5906 if (DS.getObjCDeclQualifier() == 0 && !IsParameter &&
Richard Smith20e883e2015-04-29 23:20:19 +00005907 PP.isMacroDefined("IBAction")) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00005908 CodeCompletionBuilder Builder(Results.getAllocator(),
5909 Results.getCodeCompletionTUInfo(),
5910 CCP_CodePattern, CXAvailability_Available);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005911 Builder.AddTypedTextChunk("IBAction");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005912 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005913 Builder.AddPlaceholderChunk("selector");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005914 Builder.AddChunk(CodeCompletionString::CK_Colon);
5915 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005916 Builder.AddTextChunk("id");
Benjamin Kramerdb534a42012-03-26 16:57:36 +00005917 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorf34a6f02011-02-15 22:19:42 +00005918 Builder.AddTextChunk("sender");
5919 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
5920 }
Douglas Gregored1f5972013-01-30 07:11:43 +00005921
5922 // If we're completing the return type, provide 'instancetype'.
5923 if (!IsParameter) {
5924 Results.AddResult(CodeCompletionResult("instancetype"));
5925 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005926
Douglas Gregor99fa2642010-08-24 01:06:58 +00005927 // Add various builtin type names and specifiers.
5928 AddOrdinaryNameResults(PCC_Type, S, *this, Results);
5929 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00005930
Douglas Gregor99fa2642010-08-24 01:06:58 +00005931 // Add the various type names
5932 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
5933 CodeCompletionDeclConsumer Consumer(Results, CurContext);
5934 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00005935 CodeCompleter->includeGlobals(),
5936 CodeCompleter->loadExternal());
5937
Douglas Gregor99fa2642010-08-24 01:06:58 +00005938 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00005939 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor99fa2642010-08-24 01:06:58 +00005940
Eric Liuf5ba09f2018-07-04 10:01:18 +00005941 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor99fa2642010-08-24 01:06:58 +00005942 Results.data(), Results.size());
5943}
5944
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00005945/// When we have an expression with type "id", we may assume
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005946/// that it has some more-specific class type based on knowledge of
5947/// common uses of Objective-C. This routine returns that class type,
5948/// or NULL if no better result could be determined.
5949static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) {
Fangrui Song050229d2018-11-24 00:14:31 +00005950 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005951 if (!Msg)
Craig Topperc3ec1492014-05-26 06:22:03 +00005952 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005953
5954 Selector Sel = Msg->getSelector();
5955 if (Sel.isNull())
Craig Topperc3ec1492014-05-26 06:22:03 +00005956 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005957
5958 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0);
5959 if (!Id)
Craig Topperc3ec1492014-05-26 06:22:03 +00005960 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005961
5962 ObjCMethodDecl *Method = Msg->getMethodDecl();
5963 if (!Method)
Craig Topperc3ec1492014-05-26 06:22:03 +00005964 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005965
5966 // Determine the class that we're sending the message to.
Craig Topperc3ec1492014-05-26 06:22:03 +00005967 ObjCInterfaceDecl *IFace = nullptr;
Douglas Gregor9a129192010-04-21 00:45:42 +00005968 switch (Msg->getReceiverKind()) {
5969 case ObjCMessageExpr::Class:
Fangrui Song050229d2018-11-24 00:14:31 +00005970 if (const ObjCObjectType *ObjType =
5971 Msg->getClassReceiver()->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00005972 IFace = ObjType->getInterface();
Douglas Gregor9a129192010-04-21 00:45:42 +00005973 break;
5974
5975 case ObjCMessageExpr::Instance: {
5976 QualType T = Msg->getInstanceReceiver()->getType();
5977 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
5978 IFace = Ptr->getInterfaceDecl();
5979 break;
5980 }
5981
5982 case ObjCMessageExpr::SuperInstance:
5983 case ObjCMessageExpr::SuperClass:
5984 break;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005985 }
5986
5987 if (!IFace)
Craig Topperc3ec1492014-05-26 06:22:03 +00005988 return nullptr;
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00005989
5990 ObjCInterfaceDecl *Super = IFace->getSuperClass();
5991 if (Method->isInstanceMethod())
5992 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00005993 .Case("retain", IFace)
5994 .Case("strong", IFace)
5995 .Case("autorelease", IFace)
5996 .Case("copy", IFace)
5997 .Case("copyWithZone", IFace)
5998 .Case("mutableCopy", IFace)
5999 .Case("mutableCopyWithZone", IFace)
6000 .Case("awakeFromCoder", IFace)
6001 .Case("replacementObjectFromCoder", IFace)
6002 .Case("class", IFace)
6003 .Case("classForCoder", IFace)
6004 .Case("superclass", Super)
6005 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006006
6007 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName())
Fangrui Song050229d2018-11-24 00:14:31 +00006008 .Case("new", IFace)
6009 .Case("alloc", IFace)
6010 .Case("allocWithZone", IFace)
6011 .Case("class", IFace)
6012 .Case("superclass", Super)
6013 .Default(nullptr);
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006014}
6015
Douglas Gregor6fc04132010-08-27 15:10:57 +00006016// Add a special completion for a message send to "super", which fills in the
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006017// most likely case of forwarding all of our arguments to the superclass
Douglas Gregor6fc04132010-08-27 15:10:57 +00006018// function.
6019///
6020/// \param S The semantic analysis object.
6021///
Dmitri Gribenkoadba9be2012-08-23 17:58:28 +00006022/// \param NeedSuperKeyword Whether we need to prefix this completion with
Douglas Gregor6fc04132010-08-27 15:10:57 +00006023/// the "super" keyword. Otherwise, we just need to provide the arguments.
6024///
6025/// \param SelIdents The identifiers in the selector that have already been
6026/// provided as arguments for a send to "super".
6027///
Douglas Gregor6fc04132010-08-27 15:10:57 +00006028/// \param Results The set of results to augment.
6029///
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006030/// \returns the Objective-C method declaration that would be invoked by
Douglas Gregor6fc04132010-08-27 15:10:57 +00006031/// this "super" completion. If NULL, no completion was added.
Fangrui Song050229d2018-11-24 00:14:31 +00006032static ObjCMethodDecl *
6033AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword,
6034 ArrayRef<IdentifierInfo *> SelIdents,
6035 ResultBuilder &Results) {
Douglas Gregor6fc04132010-08-27 15:10:57 +00006036 ObjCMethodDecl *CurMethod = S.getCurMethodDecl();
6037 if (!CurMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006038 return nullptr;
6039
Douglas Gregor6fc04132010-08-27 15:10:57 +00006040 ObjCInterfaceDecl *Class = CurMethod->getClassInterface();
6041 if (!Class)
Craig Topperc3ec1492014-05-26 06:22:03 +00006042 return nullptr;
6043
Douglas Gregor6fc04132010-08-27 15:10:57 +00006044 // Try to find a superclass method with the same selector.
Craig Topperc3ec1492014-05-26 06:22:03 +00006045 ObjCMethodDecl *SuperMethod = nullptr;
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006046 while ((Class = Class->getSuperClass()) && !SuperMethod) {
6047 // Check in the class
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006048 SuperMethod = Class->getMethod(CurMethod->getSelector(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006049 CurMethod->isInstanceMethod());
6050
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006051 // Check in categories or class extensions.
6052 if (!SuperMethod) {
Aaron Ballman15063e12014-03-13 21:35:02 +00006053 for (const auto *Cat : Class->known_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006054 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(),
Fangrui Song050229d2018-11-24 00:14:31 +00006055 CurMethod->isInstanceMethod())))
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006056 break;
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006057 }
Douglas Gregorb5f1e462011-02-16 00:51:18 +00006058 }
6059 }
6060
Douglas Gregor6fc04132010-08-27 15:10:57 +00006061 if (!SuperMethod)
Craig Topperc3ec1492014-05-26 06:22:03 +00006062 return nullptr;
6063
Douglas Gregor6fc04132010-08-27 15:10:57 +00006064 // Check whether the superclass method has the same signature.
6065 if (CurMethod->param_size() != SuperMethod->param_size() ||
6066 CurMethod->isVariadic() != SuperMethod->isVariadic())
Craig Topperc3ec1492014-05-26 06:22:03 +00006067 return nullptr;
6068
Douglas Gregor6fc04132010-08-27 15:10:57 +00006069 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006070 CurPEnd = CurMethod->param_end(),
6071 SuperP = SuperMethod->param_begin();
Douglas Gregor6fc04132010-08-27 15:10:57 +00006072 CurP != CurPEnd; ++CurP, ++SuperP) {
6073 // Make sure the parameter types are compatible.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006074 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006075 (*SuperP)->getType()))
Craig Topperc3ec1492014-05-26 06:22:03 +00006076 return nullptr;
6077
Douglas Gregor6fc04132010-08-27 15:10:57 +00006078 // Make sure we have a parameter name to forward!
6079 if (!(*CurP)->getIdentifier())
Craig Topperc3ec1492014-05-26 06:22:03 +00006080 return nullptr;
Douglas Gregor6fc04132010-08-27 15:10:57 +00006081 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006082
Douglas Gregor6fc04132010-08-27 15:10:57 +00006083 // We have a superclass method. Now, form the send-to-super completion.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006084 CodeCompletionBuilder Builder(Results.getAllocator(),
6085 Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006086
Douglas Gregor6fc04132010-08-27 15:10:57 +00006087 // Give this completion a return type.
Douglas Gregorc3425b12015-07-07 06:20:19 +00006088 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00006089 Results.getCompletionContext().getBaseType(), Builder);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006090
6091 // If we need the "super" keyword, add it (plus some spacing).
6092 if (NeedSuperKeyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006093 Builder.AddTypedTextChunk("super");
6094 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006095 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006096
Douglas Gregor6fc04132010-08-27 15:10:57 +00006097 Selector Sel = CurMethod->getSelector();
6098 if (Sel.isUnarySelector()) {
6099 if (NeedSuperKeyword)
Fangrui Song050229d2018-11-24 00:14:31 +00006100 Builder.AddTextChunk(
6101 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006102 else
Fangrui Song050229d2018-11-24 00:14:31 +00006103 Builder.AddTypedTextChunk(
6104 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006105 } else {
6106 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin();
6107 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006108 if (I > SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006109 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006110
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006111 if (I < SelIdents.size())
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006112 Builder.AddInformativeChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006113 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006114 else if (NeedSuperKeyword || I > SelIdents.size()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006115 Builder.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006116 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006117 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006118 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006119 } else {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006120 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00006121 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00006122 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00006123 (*CurP)->getIdentifier()->getName()));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006124 }
6125 }
6126 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006127
Douglas Gregor78254c82012-03-27 23:34:16 +00006128 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod,
6129 CCP_SuperCompletion));
Douglas Gregor6fc04132010-08-27 15:10:57 +00006130 return SuperMethod;
6131}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006132
Douglas Gregora817a192010-05-27 23:06:34 +00006133void Sema::CodeCompleteObjCMessageReceiver(Scope *S) {
John McCall276321a2010-08-25 06:19:51 +00006134 typedef CodeCompletionResult Result;
Fangrui Song050229d2018-11-24 00:14:31 +00006135 ResultBuilder Results(
6136 *this, CodeCompleter->getAllocator(),
6137 CodeCompleter->getCodeCompletionTUInfo(),
6138 CodeCompletionContext::CCC_ObjCMessageReceiver,
6139 getLangOpts().CPlusPlus11
6140 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture
6141 : &ResultBuilder::IsObjCMessageReceiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006142
Douglas Gregora817a192010-05-27 23:06:34 +00006143 CodeCompletionDeclConsumer Consumer(Results, CurContext);
6144 Results.EnterNewScope();
Douglas Gregor39982192010-08-15 06:18:01 +00006145 LookupVisibleDecls(S, LookupOrdinaryName, Consumer,
Sam McCallbb2cf632018-01-12 14:51:47 +00006146 CodeCompleter->includeGlobals(),
6147 CodeCompleter->loadExternal());
6148
Douglas Gregora817a192010-05-27 23:06:34 +00006149 // If we are in an Objective-C method inside a class that has a superclass,
6150 // add "super" as an option.
6151 if (ObjCMethodDecl *Method = getCurMethodDecl())
6152 if (ObjCInterfaceDecl *Iface = Method->getClassInterface())
Douglas Gregor6fc04132010-08-27 15:10:57 +00006153 if (Iface->getSuperClass()) {
Douglas Gregora817a192010-05-27 23:06:34 +00006154 Results.AddResult(Result("super"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006155
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006156 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results);
Douglas Gregor6fc04132010-08-27 15:10:57 +00006157 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006158
Richard Smith2bf7fdb2013-01-02 11:42:31 +00006159 if (getLangOpts().CPlusPlus11)
Douglas Gregord8c61782012-02-15 15:34:24 +00006160 addThisCompletion(*this, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006161
Douglas Gregora817a192010-05-27 23:06:34 +00006162 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006163
Douglas Gregora817a192010-05-27 23:06:34 +00006164 if (CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00006165 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false);
Douglas Gregor50832e02010-09-20 22:39:41 +00006166 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor00c37ef2010-08-11 21:23:17 +00006167 Results.data(), Results.size());
Douglas Gregora817a192010-05-27 23:06:34 +00006168}
6169
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006170void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006171 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006172 bool AtArgumentExpression) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006173 ObjCInterfaceDecl *CDecl = nullptr;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006174 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6175 // Figure out which interface we're in.
6176 CDecl = CurMethod->getClassInterface();
6177 if (!CDecl)
6178 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006179
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006180 // Find the superclass of this class.
6181 CDecl = CDecl->getSuperClass();
6182 if (!CDecl)
6183 return;
6184
6185 if (CurMethod->isInstanceMethod()) {
6186 // We are inside an instance method, which means that the message
6187 // send [super ...] is actually calling an instance method on the
Douglas Gregor392a84b2010-10-13 21:24:53 +00006188 // current object.
Craig Topperc3ec1492014-05-26 06:22:03 +00006189 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006190 AtArgumentExpression, CDecl);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006191 }
6192
6193 // Fall through to send to the superclass in CDecl.
6194 } else {
6195 // "super" may be the name of a type or variable. Figure out which
6196 // it is.
Argyrios Kyrtzidis3e56dd42013-03-14 22:56:43 +00006197 IdentifierInfo *Super = getSuperIdentifier();
Fangrui Song050229d2018-11-24 00:14:31 +00006198 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006199 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) {
6200 // "super" names an interface. Use it.
6201 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006202 if (const ObjCObjectType *Iface =
6203 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>())
John McCall8b07ec22010-05-15 11:32:37 +00006204 CDecl = Iface->getInterface();
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006205 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) {
6206 // "super" names an unresolved type; we can't be more specific.
6207 } else {
6208 // Assume that "super" names some kind of value and parse that way.
6209 CXXScopeSpec SS;
Abramo Bagnara7945c982012-01-27 09:46:47 +00006210 SourceLocation TemplateKWLoc;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006211 UnqualifiedId id;
6212 id.setIdentifier(Super, SuperLoc);
Fangrui Song050229d2018-11-24 00:14:31 +00006213 ExprResult SuperExpr =
6214 ActOnIdExpression(S, SS, TemplateKWLoc, id, false, false);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006215 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(),
Fangrui Song050229d2018-11-24 00:14:31 +00006216 SelIdents, AtArgumentExpression);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006217 }
6218
6219 // Fall through
6220 }
6221
John McCallba7bf592010-08-24 05:47:05 +00006222 ParsedType Receiver;
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006223 if (CDecl)
John McCallba7bf592010-08-24 05:47:05 +00006224 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006225 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006226 AtArgumentExpression,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006227 /*IsSuper=*/true);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006228}
6229
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006230/// Given a set of code-completion results for the argument of a message
Douglas Gregor74661272010-09-21 00:03:25 +00006231/// send, determine the preferred type (if any) for that argument expression.
6232static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results,
6233 unsigned NumSelIdents) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006234 typedef CodeCompletionResult Result;
Douglas Gregor74661272010-09-21 00:03:25 +00006235 ASTContext &Context = Results.getSema().Context;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006236
Douglas Gregor74661272010-09-21 00:03:25 +00006237 QualType PreferredType;
6238 unsigned BestPriority = CCP_Unlikely * 2;
6239 Result *ResultsData = Results.data();
6240 for (unsigned I = 0, N = Results.size(); I != N; ++I) {
6241 Result &R = ResultsData[I];
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006242 if (R.Kind == Result::RK_Declaration &&
Douglas Gregor74661272010-09-21 00:03:25 +00006243 isa<ObjCMethodDecl>(R.Declaration)) {
6244 if (R.Priority <= BestPriority) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00006245 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration);
Douglas Gregor74661272010-09-21 00:03:25 +00006246 if (NumSelIdents <= Method->param_size()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006247 QualType MyPreferredType =
6248 Method->parameters()[NumSelIdents - 1]->getType();
Douglas Gregor74661272010-09-21 00:03:25 +00006249 if (R.Priority < BestPriority || PreferredType.isNull()) {
6250 BestPriority = R.Priority;
6251 PreferredType = MyPreferredType;
6252 } else if (!Context.hasSameUnqualifiedType(PreferredType,
6253 MyPreferredType)) {
6254 PreferredType = QualType();
6255 }
6256 }
6257 }
6258 }
6259 }
6260
6261 return PreferredType;
6262}
6263
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006264static void AddClassMessageCompletions(Sema &SemaRef, Scope *S,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006265 ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006266 ArrayRef<IdentifierInfo *> SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006267 bool AtArgumentExpression, bool IsSuper,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006268 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006269 typedef CodeCompletionResult Result;
Craig Topperc3ec1492014-05-26 06:22:03 +00006270 ObjCInterfaceDecl *CDecl = nullptr;
6271
Douglas Gregor8ce33212009-11-17 17:59:40 +00006272 // If the given name refers to an interface type, retrieve the
6273 // corresponding declaration.
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006274 if (Receiver) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006275 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006276 if (!T.isNull())
John McCall8b07ec22010-05-15 11:32:37 +00006277 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>())
6278 CDecl = Interface->getInterface();
Douglas Gregor8ce33212009-11-17 17:59:40 +00006279 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006280
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006281 // Add all of the factory methods in this Objective-C class, its protocols,
6282 // superclasses, categories, implementation, etc.
Steve Naroffeae65032009-11-07 02:08:14 +00006283 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006284
6285 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006286 // completion.
6287 if (IsSuper) {
Fangrui Song050229d2018-11-24 00:14:31 +00006288 if (ObjCMethodDecl *SuperMethod =
6289 AddSuperSendCompletion(SemaRef, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006290 Results.Ignore(SuperMethod);
6291 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006292
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006293 // If we're inside an Objective-C method definition, prefer its selector to
6294 // others.
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006295 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl())
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006296 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006297
Douglas Gregor1154e272010-09-16 16:06:31 +00006298 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006299 if (CDecl)
Fangrui Song050229d2018-11-24 00:14:31 +00006300 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext,
6301 Selectors, AtArgumentExpression, Results);
Douglas Gregor0c78ad92010-04-21 19:57:20 +00006302 else {
Douglas Gregor6285f752010-04-06 16:40:00 +00006303 // We're messaging "id" as a type; provide all class/factory methods.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006304
Douglas Gregord720daf2010-04-06 17:30:22 +00006305 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006306 // pool from the AST file.
Axel Naumanndd433f02012-10-18 19:05:02 +00006307 if (SemaRef.getExternalSource()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006308 for (uint32_t I = 0,
Axel Naumanndd433f02012-10-18 19:05:02 +00006309 N = SemaRef.getExternalSource()->GetNumExternalSelectors();
John McCall75b960e2010-06-01 09:23:16 +00006310 I != N; ++I) {
Axel Naumanndd433f02012-10-18 19:05:02 +00006311 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I);
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006312 if (Sel.isNull() || SemaRef.MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006313 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006314
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006315 SemaRef.ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006316 }
6317 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006318
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006319 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006320 MEnd = SemaRef.MethodPool.end();
Sebastian Redl75d8a322010-08-02 23:18:59 +00006321 M != MEnd; ++M) {
6322 for (ObjCMethodList *MethList = &M->second.second;
Fangrui Song050229d2018-11-24 00:14:31 +00006323 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006324 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006325 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006326
Nico Weber2e0c8f72014-12-27 03:58:08 +00006327 Result R(MethList->getMethod(),
6328 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006329 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006330 R.AllParametersAreInformative = false;
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006331 Results.MaybeAddResult(R, SemaRef.CurContext);
Douglas Gregor6285f752010-04-06 16:40:00 +00006332 }
6333 }
6334 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006335
6336 Results.ExitScope();
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006337}
Douglas Gregor6285f752010-04-06 16:40:00 +00006338
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006339void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006340 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006341 bool AtArgumentExpression,
Douglas Gregorbfcea8b2010-09-16 15:14:18 +00006342 bool IsSuper) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006343
Douglas Gregor63745d52011-07-21 01:05:26 +00006344 QualType T = this->GetTypeFromParser(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006345
Fangrui Song050229d2018-11-24 00:14:31 +00006346 ResultBuilder Results(
6347 *this, CodeCompleter->getAllocator(),
6348 CodeCompleter->getCodeCompletionTUInfo(),
6349 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T,
6350 SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006351
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006352 AddClassMessageCompletions(*this, S, Receiver, SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006353 AtArgumentExpression, IsSuper, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006354
6355 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006356 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006357 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006358 // code-complete the expression using the corresponding parameter type as
6359 // our preferred type, improving completion results.
6360 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006361 QualType PreferredType =
6362 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006363 if (PreferredType.isNull())
6364 CodeCompleteOrdinaryName(S, PCC_Expression);
6365 else
6366 CodeCompleteExpression(S, PreferredType);
6367 return;
6368 }
6369
Fangrui Song050229d2018-11-24 00:14:31 +00006370 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor6fc04132010-08-27 15:10:57 +00006371 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006372}
6373
Richard Trieu2bd04012011-09-09 02:00:50 +00006374void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver,
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006375 ArrayRef<IdentifierInfo *> SelIdents,
Douglas Gregorf86e4da2010-09-20 23:34:21 +00006376 bool AtArgumentExpression,
Douglas Gregor392a84b2010-10-13 21:24:53 +00006377 ObjCInterfaceDecl *Super) {
John McCall276321a2010-08-25 06:19:51 +00006378 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006379
Steve Naroffeae65032009-11-07 02:08:14 +00006380 Expr *RecExpr = static_cast<Expr *>(Receiver);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006381
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006382 // If necessary, apply function/array conversion to the receiver.
6383 // C99 6.7.5.3p[7,8].
John Wiegley01296292011-04-08 18:41:53 +00006384 if (RecExpr) {
6385 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr);
6386 if (Conv.isInvalid()) // conversion failed. bail.
6387 return;
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006388 RecExpr = Conv.get();
John Wiegley01296292011-04-08 18:41:53 +00006389 }
Fangrui Song050229d2018-11-24 00:14:31 +00006390 QualType ReceiverType = RecExpr
6391 ? RecExpr->getType()
6392 : Super ? Context.getObjCObjectPointerType(
Douglas Gregor392a84b2010-10-13 21:24:53 +00006393 Context.getObjCInterfaceType(Super))
Fangrui Song050229d2018-11-24 00:14:31 +00006394 : Context.getObjCIdType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006395
Douglas Gregordc520b02010-11-08 21:12:30 +00006396 // If we're messaging an expression with type "id" or "Class", check
6397 // whether we know something special about the receiver that allows
6398 // us to assume a more-specific receiver type.
Anders Carlsson382ba412014-02-28 19:07:22 +00006399 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) {
Douglas Gregordc520b02010-11-08 21:12:30 +00006400 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) {
6401 if (ReceiverType->isObjCClassType())
Fangrui Song050229d2018-11-24 00:14:31 +00006402 return CodeCompleteObjCClassMessage(
6403 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents,
6404 AtArgumentExpression, Super);
Douglas Gregordc520b02010-11-08 21:12:30 +00006405
Fangrui Song050229d2018-11-24 00:14:31 +00006406 ReceiverType =
6407 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace));
Douglas Gregordc520b02010-11-08 21:12:30 +00006408 }
Anders Carlsson382ba412014-02-28 19:07:22 +00006409 } else if (RecExpr && getLangOpts().CPlusPlus) {
6410 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr);
6411 if (Conv.isUsable()) {
Nikola Smiljanic01a75982014-05-29 10:55:11 +00006412 RecExpr = Conv.get();
Anders Carlsson382ba412014-02-28 19:07:22 +00006413 ReceiverType = RecExpr->getType();
6414 }
6415 }
Douglas Gregordc520b02010-11-08 21:12:30 +00006416
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006417 // Build the set of methods we can see.
Fangrui Song050229d2018-11-24 00:14:31 +00006418 ResultBuilder Results(
6419 *this, CodeCompleter->getAllocator(),
6420 CodeCompleter->getCodeCompletionTUInfo(),
6421 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage,
6422 ReceiverType, SelIdents));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006423
Douglas Gregorbab2b3c2009-11-17 23:22:23 +00006424 Results.EnterNewScope();
Douglas Gregor9d2ddb22010-04-06 19:22:33 +00006425
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006426 // If this is a send-to-super, try to add the special "super" send
Douglas Gregor6fc04132010-08-27 15:10:57 +00006427 // completion.
Douglas Gregor392a84b2010-10-13 21:24:53 +00006428 if (Super) {
Fangrui Song050229d2018-11-24 00:14:31 +00006429 if (ObjCMethodDecl *SuperMethod =
6430 AddSuperSendCompletion(*this, false, SelIdents, Results))
Douglas Gregor6fc04132010-08-27 15:10:57 +00006431 Results.Ignore(SuperMethod);
6432 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006433
Douglas Gregorc2cb2e22010-08-27 15:29:55 +00006434 // If we're inside an Objective-C method definition, prefer its selector to
6435 // others.
6436 if (ObjCMethodDecl *CurMethod = getCurMethodDecl())
6437 Results.setPreferredSelector(CurMethod->getSelector());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006438
Douglas Gregor1154e272010-09-16 16:06:31 +00006439 // Keep track of the selectors we've already added.
6440 VisitedSelectorSet Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006441
Douglas Gregora3329fa2009-11-18 00:06:18 +00006442 // Handle messages to Class. This really isn't a message to an instance
6443 // method, so we treat it the same way we would treat a message send to a
6444 // class method.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006445 if (ReceiverType->isObjCClassType() ||
Douglas Gregora3329fa2009-11-18 00:06:18 +00006446 ReceiverType->isObjCQualifiedClassType()) {
6447 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) {
6448 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface())
Fangrui Song050229d2018-11-24 00:14:31 +00006449 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext,
6450 Selectors, AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006451 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006452 }
Douglas Gregora3329fa2009-11-18 00:06:18 +00006453 // Handle messages to a qualified ID ("id<foo>").
Fangrui Song050229d2018-11-24 00:14:31 +00006454 else if (const ObjCObjectPointerType *QualID =
6455 ReceiverType->getAsObjCQualifiedIdType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006456 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006457 for (auto *I : QualID->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006458 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6459 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006460 }
6461 // Handle messages to a pointer to interface type.
Fangrui Song050229d2018-11-24 00:14:31 +00006462 else if (const ObjCObjectPointerType *IFacePtr =
6463 ReceiverType->getAsObjCInterfacePointerType()) {
Douglas Gregora3329fa2009-11-18 00:06:18 +00006464 // Search the class, its superclasses, etc., for instance methods.
Douglas Gregorc8537c52009-11-19 07:41:15 +00006465 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents,
Fangrui Song050229d2018-11-24 00:14:31 +00006466 CurContext, Selectors, AtArgumentExpression, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006467
Douglas Gregora3329fa2009-11-18 00:06:18 +00006468 // Search protocols for instance methods.
Aaron Ballman83731462014-03-17 16:14:00 +00006469 for (auto *I : IFacePtr->quals())
Fangrui Song050229d2018-11-24 00:14:31 +00006470 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors,
6471 AtArgumentExpression, Results);
Douglas Gregora3329fa2009-11-18 00:06:18 +00006472 }
Douglas Gregor6285f752010-04-06 16:40:00 +00006473 // Handle messages to "id".
6474 else if (ReceiverType->isObjCIdType()) {
Douglas Gregord720daf2010-04-06 17:30:22 +00006475 // We're messaging "id", so provide all instance methods we know
6476 // about as code-completion results.
6477
6478 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00006479 // pool from the AST file.
Douglas Gregord720daf2010-04-06 17:30:22 +00006480 if (ExternalSource) {
John McCall75b960e2010-06-01 09:23:16 +00006481 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors();
6482 I != N; ++I) {
6483 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00006484 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregord720daf2010-04-06 17:30:22 +00006485 continue;
6486
Sebastian Redl75d8a322010-08-02 23:18:59 +00006487 ReadMethodPool(Sel);
Douglas Gregord720daf2010-04-06 17:30:22 +00006488 }
6489 }
6490
Sebastian Redl75d8a322010-08-02 23:18:59 +00006491 for (GlobalMethodPool::iterator M = MethodPool.begin(),
6492 MEnd = MethodPool.end();
6493 M != MEnd; ++M) {
6494 for (ObjCMethodList *MethList = &M->second.first;
Fangrui Song050229d2018-11-24 00:14:31 +00006495 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00006496 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor6285f752010-04-06 16:40:00 +00006497 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006498
Nico Weber2e0c8f72014-12-27 03:58:08 +00006499 if (!Selectors.insert(MethList->getMethod()->getSelector()).second)
Douglas Gregor1154e272010-09-16 16:06:31 +00006500 continue;
Craig Topperc3ec1492014-05-26 06:22:03 +00006501
Nico Weber2e0c8f72014-12-27 03:58:08 +00006502 Result R(MethList->getMethod(),
6503 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006504 R.StartParameter = SelIdents.size();
Douglas Gregor6285f752010-04-06 16:40:00 +00006505 R.AllParametersAreInformative = false;
6506 Results.MaybeAddResult(R, CurContext);
6507 }
6508 }
6509 }
Steve Naroffeae65032009-11-07 02:08:14 +00006510 Results.ExitScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006511
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006512 // If we're actually at the argument expression (rather than prior to the
Douglas Gregor74661272010-09-21 00:03:25 +00006513 // selector), we're actually performing code completion for an expression.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006514 // Determine whether we have a single, best method. If so, we can
Douglas Gregor74661272010-09-21 00:03:25 +00006515 // code-complete the expression using the corresponding parameter type as
6516 // our preferred type, improving completion results.
6517 if (AtArgumentExpression) {
Fangrui Song050229d2018-11-24 00:14:31 +00006518 QualType PreferredType =
6519 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size());
Douglas Gregor74661272010-09-21 00:03:25 +00006520 if (PreferredType.isNull())
6521 CodeCompleteOrdinaryName(S, PCC_Expression);
6522 else
6523 CodeCompleteExpression(S, PreferredType);
6524 return;
6525 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006526
Fangrui Song050229d2018-11-24 00:14:31 +00006527 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6528 Results.data(), Results.size());
Steve Naroffeae65032009-11-07 02:08:14 +00006529}
Douglas Gregorbaf69612009-11-18 04:19:12 +00006530
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006531void Sema::CodeCompleteObjCForCollection(Scope *S,
Douglas Gregor68762e72010-08-23 21:17:50 +00006532 DeclGroupPtrTy IterationVar) {
6533 CodeCompleteExpressionData Data;
6534 Data.ObjCCollection = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006535
Douglas Gregor68762e72010-08-23 21:17:50 +00006536 if (IterationVar.getAsOpaquePtr()) {
Serge Pavlov9ddb76e2013-08-27 13:15:56 +00006537 DeclGroupRef DG = IterationVar.get();
Douglas Gregor68762e72010-08-23 21:17:50 +00006538 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) {
6539 if (*I)
6540 Data.IgnoreDecls.push_back(*I);
6541 }
6542 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006543
Douglas Gregor68762e72010-08-23 21:17:50 +00006544 CodeCompleteExpression(S, Data);
6545}
6546
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006547void Sema::CodeCompleteObjCSelector(Scope *S,
6548 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006549 // If we have an external source, load the entire class method
6550 // pool from the AST file.
6551 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00006552 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
6553 ++I) {
Douglas Gregor67c692c2010-08-26 15:07:07 +00006554 Selector Sel = ExternalSource->GetExternalSelector(I);
6555 if (Sel.isNull() || MethodPool.count(Sel))
6556 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006557
Douglas Gregor67c692c2010-08-26 15:07:07 +00006558 ReadMethodPool(Sel);
6559 }
6560 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006561
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006562 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006563 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006564 CodeCompletionContext::CCC_SelectorName);
Douglas Gregor67c692c2010-08-26 15:07:07 +00006565 Results.EnterNewScope();
6566 for (GlobalMethodPool::iterator M = MethodPool.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00006567 MEnd = MethodPool.end();
Douglas Gregor67c692c2010-08-26 15:07:07 +00006568 M != MEnd; ++M) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006569
Douglas Gregor67c692c2010-08-26 15:07:07 +00006570 Selector Sel = M->first;
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006571 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents))
Douglas Gregor67c692c2010-08-26 15:07:07 +00006572 continue;
6573
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006574 CodeCompletionBuilder Builder(Results.getAllocator(),
6575 Results.getCodeCompletionTUInfo());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006576 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006577 Builder.AddTypedTextChunk(
6578 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006579 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006580 continue;
6581 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006582
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006583 std::string Accumulator;
Douglas Gregor67c692c2010-08-26 15:07:07 +00006584 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) {
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00006585 if (I == SelIdents.size()) {
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006586 if (!Accumulator.empty()) {
Fangrui Song050229d2018-11-24 00:14:31 +00006587 Builder.AddInformativeChunk(
6588 Builder.getAllocator().CopyString(Accumulator));
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006589 Accumulator.clear();
6590 }
6591 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006592
Benjamin Kramer632500c2011-07-26 16:59:25 +00006593 Accumulator += Sel.getNameForSlot(I);
Douglas Gregor9ac1ad12010-08-26 16:46:39 +00006594 Accumulator += ':';
Douglas Gregor67c692c2010-08-26 15:07:07 +00006595 }
Fangrui Song050229d2018-11-24 00:14:31 +00006596 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006597 Results.AddResult(Builder.TakeString());
Douglas Gregor67c692c2010-08-26 15:07:07 +00006598 }
6599 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006600
6601 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor67c692c2010-08-26 15:07:07 +00006602 Results.data(), Results.size());
6603}
6604
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006605/// Add all of the protocol declarations that we find in the given
Douglas Gregorbaf69612009-11-18 04:19:12 +00006606/// (translation unit) context.
6607static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext,
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006608 bool OnlyForwardDeclarations,
Douglas Gregorbaf69612009-11-18 04:19:12 +00006609 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006610 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006611
Aaron Ballman629afae2014-03-07 19:56:05 +00006612 for (const auto *D : Ctx->decls()) {
Douglas Gregorbaf69612009-11-18 04:19:12 +00006613 // Record any protocols we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006614 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D))
Douglas Gregore6e48b12012-01-01 19:29:29 +00006615 if (!OnlyForwardDeclarations || !Proto->hasDefinition())
Fangrui Song050229d2018-11-24 00:14:31 +00006616 Results.AddResult(
6617 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext,
6618 nullptr, false);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006619 }
6620}
6621
Craig Topper883dd332015-12-24 23:58:11 +00006622void Sema::CodeCompleteObjCProtocolReferences(
Fangrui Song050229d2018-11-24 00:14:31 +00006623 ArrayRef<IdentifierLocPair> Protocols) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006624 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006625 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006626 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006627
Chandler Carruthede11632016-11-04 06:06:50 +00006628 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006629 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006630
Douglas Gregora3b23b02010-12-09 21:44:02 +00006631 // Tell the result set to ignore all of the protocols we have
6632 // already seen.
6633 // FIXME: This doesn't work when caching code-completion results.
Craig Topper883dd332015-12-24 23:58:11 +00006634 for (const IdentifierLocPair &Pair : Protocols)
Fangrui Song050229d2018-11-24 00:14:31 +00006635 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second))
Douglas Gregora3b23b02010-12-09 21:44:02 +00006636 Results.Ignore(Protocol);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006637
Douglas Gregora3b23b02010-12-09 21:44:02 +00006638 // Add all protocols.
6639 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false,
6640 Results);
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006641
Douglas Gregora3b23b02010-12-09 21:44:02 +00006642 Results.ExitScope();
6643 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006644
6645 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6646 Results.data(), Results.size());
Douglas Gregor5b4671c2009-11-18 04:49:41 +00006647}
6648
6649void Sema::CodeCompleteObjCProtocolDecl(Scope *) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006650 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006651 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006652 CodeCompletionContext::CCC_ObjCProtocolName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006653
Chandler Carruthede11632016-11-04 06:06:50 +00006654 if (CodeCompleter->includeGlobals()) {
Douglas Gregora3b23b02010-12-09 21:44:02 +00006655 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006656
Douglas Gregora3b23b02010-12-09 21:44:02 +00006657 // Add all protocols.
6658 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true,
6659 Results);
Douglas Gregorbaf69612009-11-18 04:19:12 +00006660
Douglas Gregora3b23b02010-12-09 21:44:02 +00006661 Results.ExitScope();
6662 }
Eric Liuf5ba09f2018-07-04 10:01:18 +00006663
6664 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6665 Results.data(), Results.size());
Douglas Gregorbaf69612009-11-18 04:19:12 +00006666}
Douglas Gregor49c22a72009-11-18 16:26:39 +00006667
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006668/// Add all of the Objective-C interface declarations that we find in
Douglas Gregor49c22a72009-11-18 16:26:39 +00006669/// the given (translation unit) context.
6670static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext,
6671 bool OnlyForwardDeclarations,
6672 bool OnlyUnimplemented,
6673 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00006674 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006675
Aaron Ballman629afae2014-03-07 19:56:05 +00006676 for (const auto *D : Ctx->decls()) {
Douglas Gregor1c283312010-08-11 12:19:30 +00006677 // Record any interfaces we find.
Aaron Ballman629afae2014-03-07 19:56:05 +00006678 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D))
Douglas Gregordc9166c2011-12-15 20:29:51 +00006679 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) &&
Douglas Gregor1c283312010-08-11 12:19:30 +00006680 (!OnlyUnimplemented || !Class->getImplementation()))
Fangrui Song050229d2018-11-24 00:14:31 +00006681 Results.AddResult(
6682 Result(Class, Results.getBasePriority(Class), nullptr), CurContext,
6683 nullptr, false);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006684 }
6685}
6686
Eric Liuf5ba09f2018-07-04 10:01:18 +00006687void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006688 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006689 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006690 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006691 Results.EnterNewScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006692
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006693 if (CodeCompleter->includeGlobals()) {
6694 // Add all classes.
6695 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6696 false, Results);
6697 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006698
Douglas Gregor49c22a72009-11-18 16:26:39 +00006699 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006700
Eric Liuf5ba09f2018-07-04 10:01:18 +00006701 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6702 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006703}
6704
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006705void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006706 SourceLocation ClassNameLoc) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006707 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006708 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006709 CodeCompletionContext::CCC_ObjCInterfaceName);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006710 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006711
Douglas Gregor49c22a72009-11-18 16:26:39 +00006712 // Make sure that we ignore the class we're currently defining.
Fangrui Song050229d2018-11-24 00:14:31 +00006713 NamedDecl *CurClass =
6714 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006715 if (CurClass && isa<ObjCInterfaceDecl>(CurClass))
Douglas Gregor49c22a72009-11-18 16:26:39 +00006716 Results.Ignore(CurClass);
6717
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006718 if (CodeCompleter->includeGlobals()) {
6719 // Add all classes.
6720 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6721 false, Results);
6722 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006723
Douglas Gregor49c22a72009-11-18 16:26:39 +00006724 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006725
Eric Liuf5ba09f2018-07-04 10:01:18 +00006726 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6727 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006728}
6729
Eric Liuf5ba09f2018-07-04 10:01:18 +00006730void Sema::CodeCompleteObjCImplementationDecl(Scope *S) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006731 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006732 CodeCompleter->getCodeCompletionTUInfo(),
Eric Liuf5ba09f2018-07-04 10:01:18 +00006733 CodeCompletionContext::CCC_ObjCImplementation);
Douglas Gregor49c22a72009-11-18 16:26:39 +00006734 Results.EnterNewScope();
6735
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006736 if (CodeCompleter->includeGlobals()) {
6737 // Add all unimplemented classes.
6738 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false,
6739 true, Results);
6740 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006741
Douglas Gregor49c22a72009-11-18 16:26:39 +00006742 Results.ExitScope();
Douglas Gregor2c595ad2011-07-30 06:55:39 +00006743
Eric Liuf5ba09f2018-07-04 10:01:18 +00006744 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6745 Results.data(), Results.size());
Douglas Gregor49c22a72009-11-18 16:26:39 +00006746}
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006747
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006748void Sema::CodeCompleteObjCInterfaceCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006749 IdentifierInfo *ClassName,
6750 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006751 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006752
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006753 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006754 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006755 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006756
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006757 // Ignore any categories we find that have already been implemented by this
6758 // interface.
6759 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
Fangrui Song050229d2018-11-24 00:14:31 +00006760 NamedDecl *CurClass =
6761 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
6762 if (ObjCInterfaceDecl *Class =
6763 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006764 for (const auto *Cat : Class->visible_categories())
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006765 CategoryNames.insert(Cat->getIdentifier());
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006766 }
6767
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006768 // Add all of the categories we know about.
6769 Results.EnterNewScope();
6770 TranslationUnitDecl *TU = Context.getTranslationUnitDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006771 for (const auto *D : TU->decls())
Aaron Ballman629afae2014-03-07 19:56:05 +00006772 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D))
David Blaikie82e95a32014-11-19 07:49:47 +00006773 if (CategoryNames.insert(Category->getIdentifier()).second)
Fangrui Song050229d2018-11-24 00:14:31 +00006774 Results.AddResult(
6775 Result(Category, Results.getBasePriority(Category), nullptr),
6776 CurContext, nullptr, false);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006777 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006778
6779 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6780 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006781}
6782
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006783void Sema::CodeCompleteObjCImplementationCategory(Scope *S,
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006784 IdentifierInfo *ClassName,
6785 SourceLocation ClassNameLoc) {
John McCall276321a2010-08-25 06:19:51 +00006786 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006787
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006788 // Find the corresponding interface. If we couldn't find the interface, the
6789 // program itself is ill-formed. However, we'll try to be helpful still by
6790 // providing the list of all of the categories we know about.
Fangrui Song050229d2018-11-24 00:14:31 +00006791 NamedDecl *CurClass =
6792 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName);
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006793 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass);
6794 if (!Class)
Douglas Gregorb2ccf012010-04-15 22:33:43 +00006795 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006796
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006797 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006798 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor21325842011-07-07 16:03:39 +00006799 CodeCompletionContext::CCC_ObjCCategoryName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006800
6801 // Add all of the categories that have have corresponding interface
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006802 // declarations in this class and any of its superclasses, except for
6803 // already-implemented categories in the class itself.
6804 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames;
6805 Results.EnterNewScope();
6806 bool IgnoreImplemented = true;
6807 while (Class) {
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006808 for (const auto *Cat : Class->visible_categories()) {
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006809 if ((!IgnoreImplemented || !Cat->getImplementation()) &&
David Blaikie82e95a32014-11-19 07:49:47 +00006810 CategoryNames.insert(Cat->getIdentifier()).second)
Craig Topperc3ec1492014-05-26 06:22:03 +00006811 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr),
6812 CurContext, nullptr, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006813 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006814
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006815 Class = Class->getSuperClass();
6816 IgnoreImplemented = false;
6817 }
6818 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006819
6820 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6821 Results.data(), Results.size());
Douglas Gregor5d34fd32009-11-18 19:08:43 +00006822}
Douglas Gregor5d649882009-11-18 22:32:06 +00006823
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00006824void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00006825 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006826 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Fangrui Song050229d2018-11-24 00:14:31 +00006827 CodeCompleter->getCodeCompletionTUInfo(), CCContext);
Douglas Gregor5d649882009-11-18 22:32:06 +00006828
6829 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00006830 ObjCContainerDecl *Container =
6831 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
6832 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
6833 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006834 return;
Douglas Gregor5d649882009-11-18 22:32:06 +00006835
6836 // Ignore any properties that have already been implemented.
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006837 Container = getContainerDef(Container);
Aaron Ballman629afae2014-03-07 19:56:05 +00006838 for (const auto *D : Container->decls())
6839 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D))
Douglas Gregor5d649882009-11-18 22:32:06 +00006840 Results.Ignore(PropertyImpl->getPropertyDecl());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006841
Douglas Gregor5d649882009-11-18 22:32:06 +00006842 // Add any properties that we find.
Douglas Gregorb888acf2010-12-09 23:01:55 +00006843 AddedPropertiesSet AddedProperties;
Douglas Gregor5d649882009-11-18 22:32:06 +00006844 Results.EnterNewScope();
Fangrui Song050229d2018-11-24 00:14:31 +00006845 if (ObjCImplementationDecl *ClassImpl =
6846 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregorc3425b12015-07-07 06:20:19 +00006847 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006848 /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregorb888acf2010-12-09 23:01:55 +00006849 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006850 else
Douglas Gregorc3425b12015-07-07 06:20:19 +00006851 AddObjCProperties(CCContext,
6852 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006853 false, /*AllowNullaryMethods=*/false, CurContext,
Douglas Gregor95147142011-05-05 15:50:42 +00006854 AddedProperties, Results);
Douglas Gregor5d649882009-11-18 22:32:06 +00006855 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006856
6857 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6858 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006859}
6860
Fangrui Song050229d2018-11-24 00:14:31 +00006861void Sema::CodeCompleteObjCPropertySynthesizeIvar(
6862 Scope *S, IdentifierInfo *PropertyName) {
John McCall276321a2010-08-25 06:19:51 +00006863 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006864 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006865 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00006866 CodeCompletionContext::CCC_Other);
Douglas Gregor5d649882009-11-18 22:32:06 +00006867
6868 // Figure out where this @synthesize lives.
Fangrui Song050229d2018-11-24 00:14:31 +00006869 ObjCContainerDecl *Container =
6870 dyn_cast_or_null<ObjCContainerDecl>(CurContext);
6871 if (!Container || (!isa<ObjCImplementationDecl>(Container) &&
6872 !isa<ObjCCategoryImplDecl>(Container)))
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006873 return;
6874
Douglas Gregor5d649882009-11-18 22:32:06 +00006875 // Figure out which interface we're looking into.
Craig Topperc3ec1492014-05-26 06:22:03 +00006876 ObjCInterfaceDecl *Class = nullptr;
Fangrui Song050229d2018-11-24 00:14:31 +00006877 if (ObjCImplementationDecl *ClassImpl =
6878 dyn_cast<ObjCImplementationDecl>(Container))
Douglas Gregor5d649882009-11-18 22:32:06 +00006879 Class = ClassImpl->getClassInterface();
6880 else
Fangrui Song050229d2018-11-24 00:14:31 +00006881 Class = cast<ObjCCategoryImplDecl>(Container)
6882 ->getCategoryDecl()
6883 ->getClassInterface();
Douglas Gregor5d649882009-11-18 22:32:06 +00006884
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006885 // Determine the type of the property we're synthesizing.
6886 QualType PropertyType = Context.getObjCIdType();
6887 if (Class) {
Manman Ren5b786402016-01-28 18:49:28 +00006888 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration(
6889 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) {
Fangrui Song050229d2018-11-24 00:14:31 +00006890 PropertyType =
6891 Property->getType().getNonReferenceType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006892
6893 // Give preference to ivars
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006894 Results.setPreferredType(PropertyType);
6895 }
6896 }
6897
Douglas Gregor5d649882009-11-18 22:32:06 +00006898 // Add all of the instance variables in this class and its superclasses.
6899 Results.EnterNewScope();
Douglas Gregor331faa02011-04-18 14:13:53 +00006900 bool SawSimilarlyNamedIvar = false;
6901 std::string NameWithPrefix;
6902 NameWithPrefix += '_';
Benjamin Kramer632500c2011-07-26 16:59:25 +00006903 NameWithPrefix += PropertyName->getName();
Douglas Gregor331faa02011-04-18 14:13:53 +00006904 std::string NameWithSuffix = PropertyName->getName().str();
6905 NameWithSuffix += '_';
Fangrui Song050229d2018-11-24 00:14:31 +00006906 for (; Class; Class = Class->getSuperClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006907 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar;
Douglas Gregor331faa02011-04-18 14:13:53 +00006908 Ivar = Ivar->getNextIvar()) {
Craig Topperc3ec1492014-05-26 06:22:03 +00006909 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr),
6910 CurContext, nullptr, false);
6911
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006912 // Determine whether we've seen an ivar with a name similar to the
Douglas Gregor331faa02011-04-18 14:13:53 +00006913 // property.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006914 if ((PropertyName == Ivar->getIdentifier() ||
Douglas Gregor331faa02011-04-18 14:13:53 +00006915 NameWithPrefix == Ivar->getName() ||
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006916 NameWithSuffix == Ivar->getName())) {
Douglas Gregor331faa02011-04-18 14:13:53 +00006917 SawSimilarlyNamedIvar = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006918
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006919 // Reduce the priority of this result by one, to give it a slight
6920 // advantage over other results whose names don't match so closely.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006921 if (Results.size() &&
Fangrui Song050229d2018-11-24 00:14:31 +00006922 Results.data()[Results.size() - 1].Kind ==
6923 CodeCompletionResult::RK_Declaration &&
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006924 Results.data()[Results.size() - 1].Declaration == Ivar)
6925 Results.data()[Results.size() - 1].Priority--;
6926 }
Douglas Gregor331faa02011-04-18 14:13:53 +00006927 }
Douglas Gregor5d649882009-11-18 22:32:06 +00006928 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006929
Douglas Gregor331faa02011-04-18 14:13:53 +00006930 if (!SawSimilarlyNamedIvar) {
6931 // Create ivar result _propName, that the user can use to synthesize
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006932 // an ivar of the appropriate type.
Douglas Gregor6c7a9ee2011-04-18 14:40:46 +00006933 unsigned Priority = CCP_MemberDeclaration + 1;
Douglas Gregor331faa02011-04-18 14:13:53 +00006934 typedef CodeCompletionResult Result;
6935 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00006936 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00006937 Priority, CXAvailability_Available);
Douglas Gregor331faa02011-04-18 14:13:53 +00006938
Douglas Gregor75acd922011-09-27 23:30:47 +00006939 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Fangrui Song050229d2018-11-24 00:14:31 +00006940 Builder.AddResultTypeChunk(
6941 GetCompletionTypeString(PropertyType, Context, Policy, Allocator));
Douglas Gregor331faa02011-04-18 14:13:53 +00006942 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix));
Fangrui Song050229d2018-11-24 00:14:31 +00006943 Results.AddResult(
6944 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl));
Douglas Gregor331faa02011-04-18 14:13:53 +00006945 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006946
Douglas Gregor5d649882009-11-18 22:32:06 +00006947 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00006948
6949 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
6950 Results.data(), Results.size());
Douglas Gregor5d649882009-11-18 22:32:06 +00006951}
Douglas Gregor636a61e2010-04-07 00:21:17 +00006952
Douglas Gregor416b5752010-08-25 01:08:01 +00006953// Mapping from selectors to the methods that implement that selector, along
6954// with the "in original class" flag.
Fangrui Song050229d2018-11-24 00:14:31 +00006955typedef llvm::DenseMap<Selector,
6956 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>>
6957 KnownMethodsMap;
Douglas Gregor636a61e2010-04-07 00:21:17 +00006958
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00006959/// Find all of the methods that reside in the given container
Douglas Gregor636a61e2010-04-07 00:21:17 +00006960/// (and its superclasses, protocols, etc.) that meet the given
6961/// criteria. Insert those methods into the map of known methods,
6962/// indexed by selector so they can be easily found.
6963static void FindImplementableMethods(ASTContext &Context,
6964 ObjCContainerDecl *Container,
Alex Lorenzb8740422017-10-24 16:39:37 +00006965 Optional<bool> WantInstanceMethods,
Douglas Gregor636a61e2010-04-07 00:21:17 +00006966 QualType ReturnType,
Douglas Gregor416b5752010-08-25 01:08:01 +00006967 KnownMethodsMap &KnownMethods,
6968 bool InOriginalClass = true) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00006969 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006970 // Make sure we have a definition; that's what we'll walk.
Douglas Gregorc0ac7d62011-12-15 05:27:12 +00006971 if (!IFace->hasDefinition())
6972 return;
Douglas Gregor9b4f3702012-06-12 13:44:08 +00006973
6974 IFace = IFace->getDefinition();
6975 Container = IFace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006976
Fangrui Song050229d2018-11-24 00:14:31 +00006977 const ObjCList<ObjCProtocolDecl> &Protocols =
6978 IFace->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006979 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006980 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00006981 I != E; ++I)
6982 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006983 KnownMethods, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006984
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006985 // Add methods from any class extensions and categories.
Aaron Ballman3fe486a2014-03-13 21:23:55 +00006986 for (auto *Cat : IFace->visible_categories()) {
6987 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006988 KnownMethods, false);
Douglas Gregor048fbfa2013-01-16 23:00:23 +00006989 }
6990
Douglas Gregor1b035bb2010-10-18 18:21:28 +00006991 // Visit the superclass.
6992 if (IFace->getSuperClass())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00006993 FindImplementableMethods(Context, IFace->getSuperClass(),
Fangrui Song050229d2018-11-24 00:14:31 +00006994 WantInstanceMethods, ReturnType, KnownMethods,
6995 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00006996 }
6997
6998 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) {
6999 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007000 const ObjCList<ObjCProtocolDecl> &Protocols =
7001 Category->getReferencedProtocols();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007002 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007003 E = Protocols.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007004 I != E; ++I)
7005 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007006 KnownMethods, InOriginalClass);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007007
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007008 // If this category is the original class, jump to the interface.
7009 if (InOriginalClass && Category->getClassInterface())
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007010 FindImplementableMethods(Context, Category->getClassInterface(),
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007011 WantInstanceMethods, ReturnType, KnownMethods,
7012 false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007013 }
7014
7015 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) {
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007016 // Make sure we have a definition; that's what we'll walk.
7017 if (!Protocol->hasDefinition())
7018 return;
7019 Protocol = Protocol->getDefinition();
7020 Container = Protocol;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007021
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007022 // Recurse into protocols.
Fangrui Song050229d2018-11-24 00:14:31 +00007023 const ObjCList<ObjCProtocolDecl> &Protocols =
7024 Protocol->getReferencedProtocols();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007025 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007026 E = Protocols.end();
Douglas Gregor9b4f3702012-06-12 13:44:08 +00007027 I != E; ++I)
7028 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType,
7029 KnownMethods, false);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007030 }
7031
7032 // Add methods in this container. This operation occurs last because
7033 // we want the methods from this container to override any methods
7034 // we've previously seen with the same selector.
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007035 for (auto *M : Container->methods()) {
Alex Lorenzb8740422017-10-24 16:39:37 +00007036 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007037 if (!ReturnType.isNull() &&
Alp Toker314cc812014-01-25 16:55:45 +00007038 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType()))
Douglas Gregor636a61e2010-04-07 00:21:17 +00007039 continue;
7040
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007041 KnownMethods[M->getSelector()] =
Aaron Ballmanaff18c02014-03-13 19:03:34 +00007042 KnownMethodsMap::mapped_type(M, InOriginalClass);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007043 }
7044 }
7045}
7046
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007047/// Add the parenthesized return or parameter type chunk to a code
Douglas Gregor669a25a2011-02-17 00:22:45 +00007048/// completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00007049static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007050 ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00007051 const PrintingPolicy &Policy,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007052 CodeCompletionBuilder &Builder) {
7053 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregor86b42682015-06-19 18:27:52 +00007054 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type);
Douglas Gregor29979142012-04-10 18:35:07 +00007055 if (!Quals.empty())
7056 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals));
Fangrui Song050229d2018-11-24 00:14:31 +00007057 Builder.AddTextChunk(
7058 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007059 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7060}
7061
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007062/// Determine whether the given class is or inherits from a class by
Douglas Gregor669a25a2011-02-17 00:22:45 +00007063/// the given name.
Fangrui Song050229d2018-11-24 00:14:31 +00007064static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007065 if (!Class)
7066 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007067
Douglas Gregor669a25a2011-02-17 00:22:45 +00007068 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name)
7069 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007070
Douglas Gregor669a25a2011-02-17 00:22:45 +00007071 return InheritsFromClassNamed(Class->getSuperClass(), Name);
7072}
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007073
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00007074/// Add code completions for Objective-C Key-Value Coding (KVC) and
Douglas Gregor669a25a2011-02-17 00:22:45 +00007075/// Key-Value Observing (KVO).
7076static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property,
7077 bool IsInstanceMethod,
Fangrui Song050229d2018-11-24 00:14:31 +00007078 QualType ReturnType, ASTContext &Context,
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007079 VisitedSelectorSet &KnownSelectors,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007080 ResultBuilder &Results) {
7081 IdentifierInfo *PropName = Property->getIdentifier();
7082 if (!PropName || PropName->getLength() == 0)
7083 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007084
Douglas Gregor75acd922011-09-27 23:30:47 +00007085 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema());
7086
Douglas Gregor669a25a2011-02-17 00:22:45 +00007087 // Builder that will create each code completion.
7088 typedef CodeCompletionResult Result;
7089 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007090 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007091
Douglas Gregor669a25a2011-02-17 00:22:45 +00007092 // The selector table.
7093 SelectorTable &Selectors = Context.Selectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007094
Douglas Gregor669a25a2011-02-17 00:22:45 +00007095 // The property name, copied into the code completion allocation region
7096 // on demand.
7097 struct KeyHolder {
7098 CodeCompletionAllocator &Allocator;
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007099 StringRef Key;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007100 const char *CopiedKey;
Craig Topperc3ec1492014-05-26 06:22:03 +00007101
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007102 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key)
Fangrui Song050229d2018-11-24 00:14:31 +00007103 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {}
Craig Topperc3ec1492014-05-26 06:22:03 +00007104
Douglas Gregor669a25a2011-02-17 00:22:45 +00007105 operator const char *() {
7106 if (CopiedKey)
7107 return CopiedKey;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007108
Douglas Gregor669a25a2011-02-17 00:22:45 +00007109 return CopiedKey = Allocator.CopyString(Key);
7110 }
7111 } Key(Allocator, PropName->getName());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007112
Douglas Gregor669a25a2011-02-17 00:22:45 +00007113 // The uppercased name of the property name.
7114 std::string UpperKey = PropName->getName();
7115 if (!UpperKey.empty())
Jordan Rose4938f272013-02-09 10:09:43 +00007116 UpperKey[0] = toUppercase(UpperKey[0]);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007117
Fangrui Song050229d2018-11-24 00:14:31 +00007118 bool ReturnTypeMatchesProperty =
7119 ReturnType.isNull() ||
7120 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(),
7121 Property->getType());
7122 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007123
Douglas Gregor669a25a2011-02-17 00:22:45 +00007124 // Add the normal accessor -(type)key.
7125 if (IsInstanceMethod &&
David Blaikie82e95a32014-11-19 07:49:47 +00007126 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007127 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) {
7128 if (ReturnType.isNull())
Fangrui Song050229d2018-11-24 00:14:31 +00007129 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7130 Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007131
Douglas Gregor669a25a2011-02-17 00:22:45 +00007132 Builder.AddTypedTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007133 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007134 CXCursor_ObjCInstanceMethodDecl));
7135 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007136
Douglas Gregor669a25a2011-02-17 00:22:45 +00007137 // If we have an integral or boolean property (or the user has provided
7138 // an integral or boolean return type), add the accessor -(type)isKey.
7139 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007140 ((!ReturnType.isNull() &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007141 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) ||
Fangrui Song050229d2018-11-24 00:14:31 +00007142 (ReturnType.isNull() && (Property->getType()->isIntegerType() ||
7143 Property->getType()->isBooleanType())))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007144 std::string SelectorName = (Twine("is") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007145 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007146 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7147 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007148 if (ReturnType.isNull()) {
7149 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7150 Builder.AddTextChunk("BOOL");
7151 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7152 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007153
Fangrui Song050229d2018-11-24 00:14:31 +00007154 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007155 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007156 CXCursor_ObjCInstanceMethodDecl));
7157 }
7158 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007159
Douglas Gregor669a25a2011-02-17 00:22:45 +00007160 // Add the normal mutator.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007161 if (IsInstanceMethod && ReturnTypeMatchesVoid &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007162 !Property->getSetterMethodDecl()) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007163 std::string SelectorName = (Twine("set") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007164 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007165 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007166 if (ReturnType.isNull()) {
7167 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7168 Builder.AddTextChunk("void");
7169 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7170 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007171
Fangrui Song050229d2018-11-24 00:14:31 +00007172 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007173 Builder.AddTypedTextChunk(":");
Fangrui Song050229d2018-11-24 00:14:31 +00007174 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy,
7175 Builder);
Douglas Gregor669a25a2011-02-17 00:22:45 +00007176 Builder.AddTextChunk(Key);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007177 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007178 CXCursor_ObjCInstanceMethodDecl));
7179 }
7180 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007181
Douglas Gregor669a25a2011-02-17 00:22:45 +00007182 // Indexed and unordered accessors
7183 unsigned IndexedGetterPriority = CCP_CodePattern;
7184 unsigned IndexedSetterPriority = CCP_CodePattern;
7185 unsigned UnorderedGetterPriority = CCP_CodePattern;
7186 unsigned UnorderedSetterPriority = CCP_CodePattern;
Fangrui Song050229d2018-11-24 00:14:31 +00007187 if (const auto *ObjCPointer =
7188 Property->getType()->getAs<ObjCObjectPointerType>()) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007189 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) {
7190 // If this interface type is not provably derived from a known
7191 // collection, penalize the corresponding completions.
7192 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007193 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007194 if (!InheritsFromClassNamed(IFace, "NSArray"))
7195 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7196 }
7197
7198 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007199 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007200 if (!InheritsFromClassNamed(IFace, "NSSet"))
7201 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7202 }
7203 }
7204 } else {
7205 IndexedGetterPriority += CCD_ProbablyNotObjCCollection;
7206 IndexedSetterPriority += CCD_ProbablyNotObjCCollection;
7207 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection;
7208 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection;
7209 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007210
Douglas Gregor669a25a2011-02-17 00:22:45 +00007211 // Add -(NSUInteger)countOf<key>
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007212 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007213 (ReturnType.isNull() || ReturnType->isIntegerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007214 std::string SelectorName = (Twine("countOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007215 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007216 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7217 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007218 if (ReturnType.isNull()) {
7219 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7220 Builder.AddTextChunk("NSUInteger");
7221 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7222 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007223
Fangrui Song050229d2018-11-24 00:14:31 +00007224 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName()));
7225 Results.AddResult(
7226 Result(Builder.TakeString(),
7227 std::min(IndexedGetterPriority, UnorderedGetterPriority),
7228 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007229 }
7230 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007231
Douglas Gregor669a25a2011-02-17 00:22:45 +00007232 // Indexed getters
7233 // Add -(id)objectInKeyAtIndex:(NSUInteger)index
7234 if (IsInstanceMethod &&
7235 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007236 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007237 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007238 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007239 if (ReturnType.isNull()) {
7240 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7241 Builder.AddTextChunk("id");
7242 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7243 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007244
Douglas Gregor669a25a2011-02-17 00:22:45 +00007245 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7246 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7247 Builder.AddTextChunk("NSUInteger");
7248 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7249 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007250 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007251 CXCursor_ObjCInstanceMethodDecl));
7252 }
7253 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007254
Douglas Gregor669a25a2011-02-17 00:22:45 +00007255 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes
7256 if (IsInstanceMethod &&
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007257 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007258 (ReturnType->isObjCObjectPointerType() &&
7259 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007260 ReturnType->getAs<ObjCObjectPointerType>()
7261 ->getInterfaceDecl()
7262 ->getName() == "NSArray"))) {
7263 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007264 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007265 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007266 if (ReturnType.isNull()) {
7267 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7268 Builder.AddTextChunk("NSArray *");
7269 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7270 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007271
Douglas Gregor669a25a2011-02-17 00:22:45 +00007272 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7273 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7274 Builder.AddTextChunk("NSIndexSet *");
7275 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7276 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007277 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007278 CXCursor_ObjCInstanceMethodDecl));
7279 }
7280 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007281
Douglas Gregor669a25a2011-02-17 00:22:45 +00007282 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange
7283 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007284 std::string SelectorName = (Twine("get") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007285 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7286 &Context.Idents.get("range")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007287
David Blaikie82e95a32014-11-19 07:49:47 +00007288 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007289 if (ReturnType.isNull()) {
7290 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7291 Builder.AddTextChunk("void");
7292 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7293 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007294
Douglas Gregor669a25a2011-02-17 00:22:45 +00007295 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7296 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7297 Builder.AddPlaceholderChunk("object-type");
7298 Builder.AddTextChunk(" **");
7299 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7300 Builder.AddTextChunk("buffer");
7301 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7302 Builder.AddTypedTextChunk("range:");
7303 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7304 Builder.AddTextChunk("NSRange");
7305 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7306 Builder.AddTextChunk("inRange");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007307 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007308 CXCursor_ObjCInstanceMethodDecl));
7309 }
7310 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007311
Douglas Gregor669a25a2011-02-17 00:22:45 +00007312 // Mutable indexed accessors
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007313
Douglas Gregor669a25a2011-02-17 00:22:45 +00007314 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index
7315 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007316 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str();
Fangrui Song050229d2018-11-24 00:14:31 +00007317 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"),
7318 &Context.Idents.get(SelectorName)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007319
David Blaikie82e95a32014-11-19 07:49:47 +00007320 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007321 if (ReturnType.isNull()) {
7322 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7323 Builder.AddTextChunk("void");
7324 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7325 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007326
Douglas Gregor669a25a2011-02-17 00:22:45 +00007327 Builder.AddTypedTextChunk("insertObject:");
7328 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7329 Builder.AddPlaceholderChunk("object-type");
7330 Builder.AddTextChunk(" *");
7331 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7332 Builder.AddTextChunk("object");
7333 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7334 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7335 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7336 Builder.AddPlaceholderChunk("NSUInteger");
7337 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7338 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007339 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007340 CXCursor_ObjCInstanceMethodDecl));
7341 }
7342 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007343
Douglas Gregor669a25a2011-02-17 00:22:45 +00007344 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes
7345 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007346 std::string SelectorName = (Twine("insert") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007347 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7348 &Context.Idents.get("atIndexes")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007349
David Blaikie82e95a32014-11-19 07:49:47 +00007350 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007351 if (ReturnType.isNull()) {
7352 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7353 Builder.AddTextChunk("void");
7354 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7355 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007356
Douglas Gregor669a25a2011-02-17 00:22:45 +00007357 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7358 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7359 Builder.AddTextChunk("NSArray *");
7360 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7361 Builder.AddTextChunk("array");
7362 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7363 Builder.AddTypedTextChunk("atIndexes:");
7364 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7365 Builder.AddPlaceholderChunk("NSIndexSet *");
7366 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7367 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007368 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007369 CXCursor_ObjCInstanceMethodDecl));
7370 }
7371 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007372
Douglas Gregor669a25a2011-02-17 00:22:45 +00007373 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index
7374 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007375 std::string SelectorName =
7376 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007377 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007378 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007379 if (ReturnType.isNull()) {
7380 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7381 Builder.AddTextChunk("void");
7382 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7383 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007384
Douglas Gregor669a25a2011-02-17 00:22:45 +00007385 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7386 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7387 Builder.AddTextChunk("NSUInteger");
7388 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7389 Builder.AddTextChunk("index");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007390 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007391 CXCursor_ObjCInstanceMethodDecl));
7392 }
7393 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007394
Douglas Gregor669a25a2011-02-17 00:22:45 +00007395 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes
7396 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007397 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007398 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007399 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007400 if (ReturnType.isNull()) {
7401 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7402 Builder.AddTextChunk("void");
7403 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7404 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007405
Douglas Gregor669a25a2011-02-17 00:22:45 +00007406 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7407 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7408 Builder.AddTextChunk("NSIndexSet *");
7409 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7410 Builder.AddTextChunk("indexes");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007411 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007412 CXCursor_ObjCInstanceMethodDecl));
7413 }
7414 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007415
Douglas Gregor669a25a2011-02-17 00:22:45 +00007416 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object
7417 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007418 std::string SelectorName =
7419 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str();
7420 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName),
7421 &Context.Idents.get("withObject")};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007422
David Blaikie82e95a32014-11-19 07:49:47 +00007423 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007424 if (ReturnType.isNull()) {
7425 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7426 Builder.AddTextChunk("void");
7427 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7428 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007429
Douglas Gregor669a25a2011-02-17 00:22:45 +00007430 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7431 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7432 Builder.AddPlaceholderChunk("NSUInteger");
7433 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7434 Builder.AddTextChunk("index");
7435 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7436 Builder.AddTypedTextChunk("withObject:");
7437 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7438 Builder.AddTextChunk("id");
7439 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7440 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007441 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007442 CXCursor_ObjCInstanceMethodDecl));
7443 }
7444 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007445
Douglas Gregor669a25a2011-02-17 00:22:45 +00007446 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array
7447 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007448 std::string SelectorName1 =
7449 (Twine("replace") + UpperKey + "AtIndexes").str();
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007450 std::string SelectorName2 = (Twine("with") + UpperKey).str();
Fangrui Song050229d2018-11-24 00:14:31 +00007451 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1),
7452 &Context.Idents.get(SelectorName2)};
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007453
David Blaikie82e95a32014-11-19 07:49:47 +00007454 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007455 if (ReturnType.isNull()) {
7456 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7457 Builder.AddTextChunk("void");
7458 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7459 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007460
Douglas Gregor669a25a2011-02-17 00:22:45 +00007461 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":"));
7462 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7463 Builder.AddPlaceholderChunk("NSIndexSet *");
7464 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7465 Builder.AddTextChunk("indexes");
7466 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7467 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":"));
7468 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7469 Builder.AddTextChunk("NSArray *");
7470 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7471 Builder.AddTextChunk("array");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007472 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007473 CXCursor_ObjCInstanceMethodDecl));
7474 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007475 }
7476
Douglas Gregor669a25a2011-02-17 00:22:45 +00007477 // Unordered getters
7478 // - (NSEnumerator *)enumeratorOfKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007479 if (IsInstanceMethod &&
7480 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007481 (ReturnType->isObjCObjectPointerType() &&
7482 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007483 ReturnType->getAs<ObjCObjectPointerType>()
7484 ->getInterfaceDecl()
7485 ->getName() == "NSEnumerator"))) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007486 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007487 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007488 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7489 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007490 if (ReturnType.isNull()) {
7491 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7492 Builder.AddTextChunk("NSEnumerator *");
7493 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7494 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007495
Douglas Gregor669a25a2011-02-17 00:22:45 +00007496 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007497 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Fangrui Song050229d2018-11-24 00:14:31 +00007498 CXCursor_ObjCInstanceMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007499 }
7500 }
7501
7502 // - (type *)memberOfKey:(type *)object
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007503 if (IsInstanceMethod &&
Douglas Gregor669a25a2011-02-17 00:22:45 +00007504 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007505 std::string SelectorName = (Twine("memberOf") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007506 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007507 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007508 if (ReturnType.isNull()) {
7509 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7510 Builder.AddPlaceholderChunk("object-type");
7511 Builder.AddTextChunk(" *");
7512 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7513 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007514
Douglas Gregor669a25a2011-02-17 00:22:45 +00007515 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7516 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7517 if (ReturnType.isNull()) {
7518 Builder.AddPlaceholderChunk("object-type");
7519 Builder.AddTextChunk(" *");
7520 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00007521 Builder.AddTextChunk(GetCompletionTypeString(
7522 ReturnType, Context, Policy, Builder.getAllocator()));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007523 }
7524 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7525 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007526 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007527 CXCursor_ObjCInstanceMethodDecl));
7528 }
7529 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007530
Douglas Gregor669a25a2011-02-17 00:22:45 +00007531 // Mutable unordered accessors
7532 // - (void)addKeyObject:(type *)object
7533 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007534 std::string SelectorName =
7535 (Twine("add") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007536 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007537 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007538 if (ReturnType.isNull()) {
7539 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7540 Builder.AddTextChunk("void");
7541 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7542 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007543
Douglas Gregor669a25a2011-02-17 00:22:45 +00007544 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7545 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7546 Builder.AddPlaceholderChunk("object-type");
7547 Builder.AddTextChunk(" *");
7548 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7549 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007550 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007551 CXCursor_ObjCInstanceMethodDecl));
7552 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007553 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007554
7555 // - (void)addKey:(NSSet *)objects
7556 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007557 std::string SelectorName = (Twine("add") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007558 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007559 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007560 if (ReturnType.isNull()) {
7561 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7562 Builder.AddTextChunk("void");
7563 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7564 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007565
Douglas Gregor669a25a2011-02-17 00:22:45 +00007566 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7567 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7568 Builder.AddTextChunk("NSSet *");
7569 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7570 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007571 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007572 CXCursor_ObjCInstanceMethodDecl));
7573 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007574 }
7575
Douglas Gregor669a25a2011-02-17 00:22:45 +00007576 // - (void)removeKeyObject:(type *)object
7577 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Fangrui Song050229d2018-11-24 00:14:31 +00007578 std::string SelectorName =
7579 (Twine("remove") + UpperKey + Twine("Object")).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007580 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007581 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007582 if (ReturnType.isNull()) {
7583 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7584 Builder.AddTextChunk("void");
7585 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7586 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007587
Douglas Gregor669a25a2011-02-17 00:22:45 +00007588 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7589 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7590 Builder.AddPlaceholderChunk("object-type");
7591 Builder.AddTextChunk(" *");
7592 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7593 Builder.AddTextChunk("object");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007594 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007595 CXCursor_ObjCInstanceMethodDecl));
7596 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007597 }
7598
Douglas Gregor669a25a2011-02-17 00:22:45 +00007599 // - (void)removeKey:(NSSet *)objects
7600 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007601 std::string SelectorName = (Twine("remove") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007602 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007603 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007604 if (ReturnType.isNull()) {
7605 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7606 Builder.AddTextChunk("void");
7607 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7608 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007609
Douglas Gregor669a25a2011-02-17 00:22:45 +00007610 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7611 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7612 Builder.AddTextChunk("NSSet *");
7613 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7614 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007615 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007616 CXCursor_ObjCInstanceMethodDecl));
7617 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007618 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007619
7620 // - (void)intersectKey:(NSSet *)objects
7621 if (IsInstanceMethod && ReturnTypeMatchesVoid) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007622 std::string SelectorName = (Twine("intersect") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007623 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007624 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007625 if (ReturnType.isNull()) {
7626 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7627 Builder.AddTextChunk("void");
7628 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7629 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007630
Douglas Gregor669a25a2011-02-17 00:22:45 +00007631 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":"));
7632 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7633 Builder.AddTextChunk("NSSet *");
7634 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7635 Builder.AddTextChunk("objects");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007636 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority,
Douglas Gregor669a25a2011-02-17 00:22:45 +00007637 CXCursor_ObjCInstanceMethodDecl));
7638 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007639 }
7640
Douglas Gregor669a25a2011-02-17 00:22:45 +00007641 // Key-Value Observing
7642 // + (NSSet *)keyPathsForValuesAffectingKey
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007643 if (!IsInstanceMethod &&
7644 (ReturnType.isNull() ||
Douglas Gregor669a25a2011-02-17 00:22:45 +00007645 (ReturnType->isObjCObjectPointerType() &&
7646 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() &&
Fangrui Song050229d2018-11-24 00:14:31 +00007647 ReturnType->getAs<ObjCObjectPointerType>()
7648 ->getInterfaceDecl()
7649 ->getName() == "NSSet"))) {
7650 std::string SelectorName =
7651 (Twine("keyPathsForValuesAffecting") + UpperKey).str();
Douglas Gregor0e5d72f2011-02-17 03:19:26 +00007652 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007653 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7654 .second) {
Douglas Gregor669a25a2011-02-17 00:22:45 +00007655 if (ReturnType.isNull()) {
7656 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Alex Lorenz71ecb072016-12-08 16:49:05 +00007657 Builder.AddTextChunk("NSSet<NSString *> *");
Douglas Gregor669a25a2011-02-17 00:22:45 +00007658 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7659 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007660
Douglas Gregor669a25a2011-02-17 00:22:45 +00007661 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007662 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007663 CXCursor_ObjCClassMethodDecl));
Douglas Gregor857bcda2011-06-02 04:02:27 +00007664 }
7665 }
7666
7667 // + (BOOL)automaticallyNotifiesObserversForKey
7668 if (!IsInstanceMethod &&
Fangrui Song050229d2018-11-24 00:14:31 +00007669 (ReturnType.isNull() || ReturnType->isIntegerType() ||
Douglas Gregor857bcda2011-06-02 04:02:27 +00007670 ReturnType->isBooleanType())) {
Fangrui Song050229d2018-11-24 00:14:31 +00007671 std::string SelectorName =
7672 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str();
Douglas Gregor857bcda2011-06-02 04:02:27 +00007673 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName);
David Blaikie82e95a32014-11-19 07:49:47 +00007674 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId))
7675 .second) {
Douglas Gregor857bcda2011-06-02 04:02:27 +00007676 if (ReturnType.isNull()) {
7677 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
7678 Builder.AddTextChunk("BOOL");
7679 Builder.AddChunk(CodeCompletionString::CK_RightParen);
7680 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007681
Douglas Gregor857bcda2011-06-02 04:02:27 +00007682 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007683 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern,
Fangrui Song050229d2018-11-24 00:14:31 +00007684 CXCursor_ObjCClassMethodDecl));
Douglas Gregor669a25a2011-02-17 00:22:45 +00007685 }
7686 }
7687}
7688
Alex Lorenzb8740422017-10-24 16:39:37 +00007689void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod,
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007690 ParsedType ReturnTy) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007691 // Determine the return type of the method we're declaring, if
7692 // provided.
7693 QualType ReturnType = GetTypeFromParser(ReturnTy);
Craig Topperc3ec1492014-05-26 06:22:03 +00007694 Decl *IDecl = nullptr;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007695 if (CurContext->isObjCContainer()) {
Fangrui Song050229d2018-11-24 00:14:31 +00007696 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext);
7697 IDecl = OCD;
Fariborz Jahanian8d382dc2011-08-22 15:54:49 +00007698 }
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007699 // Determine where we should start searching for methods.
Craig Topperc3ec1492014-05-26 06:22:03 +00007700 ObjCContainerDecl *SearchDecl = nullptr;
Douglas Gregor636a61e2010-04-07 00:21:17 +00007701 bool IsInImplementation = false;
John McCall48871652010-08-21 09:40:31 +00007702 if (Decl *D = IDecl) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007703 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) {
7704 SearchDecl = Impl->getClassInterface();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007705 IsInImplementation = true;
Fangrui Song050229d2018-11-24 00:14:31 +00007706 } else if (ObjCCategoryImplDecl *CatImpl =
7707 dyn_cast<ObjCCategoryImplDecl>(D)) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007708 SearchDecl = CatImpl->getCategoryDecl();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007709 IsInImplementation = true;
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007710 } else
Douglas Gregor636a61e2010-04-07 00:21:17 +00007711 SearchDecl = dyn_cast<ObjCContainerDecl>(D);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007712 }
7713
7714 if (!SearchDecl && S) {
Ted Kremenekc37877d2013-10-08 17:08:03 +00007715 if (DeclContext *DC = S->getEntity())
Douglas Gregor636a61e2010-04-07 00:21:17 +00007716 SearchDecl = dyn_cast<ObjCContainerDecl>(DC);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007717 }
7718
Douglas Gregor1b035bb2010-10-18 18:21:28 +00007719 if (!SearchDecl) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007720 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00007721 CodeCompletionContext::CCC_Other, nullptr, 0);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007722 return;
7723 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007724
Douglas Gregor636a61e2010-04-07 00:21:17 +00007725 // Find all of the methods that we could declare/implement here.
7726 KnownMethodsMap KnownMethods;
Fangrui Song050229d2018-11-24 00:14:31 +00007727 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType,
7728 KnownMethods);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007729
Douglas Gregor636a61e2010-04-07 00:21:17 +00007730 // Add declarations or definitions for each of the known methods.
John McCall276321a2010-08-25 06:19:51 +00007731 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007732 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007733 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007734 CodeCompletionContext::CCC_Other);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007735 Results.EnterNewScope();
Douglas Gregor75acd922011-09-27 23:30:47 +00007736 PrintingPolicy Policy = getCompletionPrintingPolicy(*this);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007737 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007738 MEnd = KnownMethods.end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007739 M != MEnd; ++M) {
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007740 ObjCMethodDecl *Method = M->second.getPointer();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007741 CodeCompletionBuilder Builder(Results.getAllocator(),
7742 Results.getCodeCompletionTUInfo());
Alex Lorenzb8740422017-10-24 16:39:37 +00007743
7744 // Add the '-'/'+' prefix if it wasn't provided yet.
7745 if (!IsInstanceMethod) {
7746 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+");
7747 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7748 }
7749
Douglas Gregor636a61e2010-04-07 00:21:17 +00007750 // If the result type was not already provided, add it to the
7751 // pattern as (type).
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007752 if (ReturnType.isNull()) {
7753 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context);
7754 AttributedType::stripOuterNullability(ResTy);
Fangrui Song050229d2018-11-24 00:14:31 +00007755 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context,
7756 Policy, Builder);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007757 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007758
7759 Selector Sel = Method->getSelector();
7760
7761 // Add the first part of the selector to the pattern.
Fangrui Song050229d2018-11-24 00:14:31 +00007762 Builder.AddTypedTextChunk(
7763 Builder.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007764
7765 // Add parameters to the pattern.
7766 unsigned I = 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007767 for (ObjCMethodDecl::param_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007768 PEnd = Method->param_end();
Douglas Gregor636a61e2010-04-07 00:21:17 +00007769 P != PEnd; (void)++P, ++I) {
7770 // Add the part of the selector name.
7771 if (I == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007772 Builder.AddTypedTextChunk(":");
Douglas Gregor636a61e2010-04-07 00:21:17 +00007773 else if (I < Sel.getNumArgs()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007774 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7775 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00007776 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":"));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007777 } else
7778 break;
7779
7780 // Add the parameter type.
Douglas Gregor86b42682015-06-19 18:27:52 +00007781 QualType ParamType;
7782 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability)
7783 ParamType = (*P)->getType();
7784 else
7785 ParamType = (*P)->getOriginalType();
Fangrui Song050229d2018-11-24 00:14:31 +00007786 ParamType = ParamType.substObjCTypeArgs(
7787 Context, {}, ObjCSubstitutionContext::Parameter);
Argyrios Kyrtzidisf0917ab2015-07-24 17:00:19 +00007788 AttributedType::stripOuterNullability(ParamType);
Fangrui Song050229d2018-11-24 00:14:31 +00007789 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context,
7790 Policy, Builder);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007791
Douglas Gregor636a61e2010-04-07 00:21:17 +00007792 if (IdentifierInfo *Id = (*P)->getIdentifier())
Fangrui Song050229d2018-11-24 00:14:31 +00007793 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName()));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007794 }
7795
7796 if (Method->isVariadic()) {
7797 if (Method->param_size() > 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007798 Builder.AddChunk(CodeCompletionString::CK_Comma);
7799 Builder.AddTextChunk("...");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007800 }
Douglas Gregor636a61e2010-04-07 00:21:17 +00007801
Douglas Gregord37c59d2010-05-28 00:57:46 +00007802 if (IsInImplementation && Results.includeCodePatterns()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007803 // We will be defining the method here, so add a compound statement.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007804 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7805 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
7806 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
Alp Toker314cc812014-01-25 16:55:45 +00007807 if (!Method->getReturnType()->isVoidType()) {
Douglas Gregor636a61e2010-04-07 00:21:17 +00007808 // If the result type is not void, add a return clause.
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007809 Builder.AddTextChunk("return");
7810 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7811 Builder.AddPlaceholderChunk("expression");
7812 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007813 } else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007814 Builder.AddPlaceholderChunk("statements");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007815
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007816 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
7817 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
Douglas Gregor636a61e2010-04-07 00:21:17 +00007818 }
7819
Douglas Gregor416b5752010-08-25 01:08:01 +00007820 unsigned Priority = CCP_CodePattern;
Eric Liu4a7cd632018-10-24 12:57:27 +00007821 auto R = Result(Builder.TakeString(), Method, Priority);
Benjamin Kramereb8c4462013-06-29 17:52:13 +00007822 if (!M->second.getInt())
Eric Liu4a7cd632018-10-24 12:57:27 +00007823 setInBaseClass(R);
7824 Results.AddResult(std::move(R));
Douglas Gregor636a61e2010-04-07 00:21:17 +00007825 }
7826
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007827 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of
Douglas Gregor669a25a2011-02-17 00:22:45 +00007828 // the properties in this class and its categories.
Erik Pilkingtonfa983902018-10-30 20:31:30 +00007829 if (Context.getLangOpts().ObjC) {
Chris Lattner0e62c1c2011-07-23 10:55:15 +00007830 SmallVector<ObjCContainerDecl *, 4> Containers;
Douglas Gregor669a25a2011-02-17 00:22:45 +00007831 Containers.push_back(SearchDecl);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007832
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007833 VisitedSelectorSet KnownSelectors;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007834 for (KnownMethodsMap::iterator M = KnownMethods.begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00007835 MEnd = KnownMethods.end();
Douglas Gregord4a8ced2011-05-04 23:50:46 +00007836 M != MEnd; ++M)
7837 KnownSelectors.insert(M->first);
7838
Douglas Gregor669a25a2011-02-17 00:22:45 +00007839 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl);
7840 if (!IFace)
7841 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl))
7842 IFace = Category->getClassInterface();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007843
Aaron Ballman3fe486a2014-03-13 21:23:55 +00007844 if (IFace)
7845 for (auto *Cat : IFace->visible_categories())
7846 Containers.push_back(Cat);
Alex Lorenzb8740422017-10-24 16:39:37 +00007847
7848 if (IsInstanceMethod) {
7849 for (unsigned I = 0, N = Containers.size(); I != N; ++I)
7850 for (auto *P : Containers[I]->instance_properties())
7851 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context,
7852 KnownSelectors, Results);
7853 }
Douglas Gregor669a25a2011-02-17 00:22:45 +00007854 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007855
Douglas Gregor636a61e2010-04-07 00:21:17 +00007856 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00007857
7858 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7859 Results.data(), Results.size());
Douglas Gregor636a61e2010-04-07 00:21:17 +00007860}
Douglas Gregor95887f92010-07-08 23:20:03 +00007861
Fangrui Song050229d2018-11-24 00:14:31 +00007862void Sema::CodeCompleteObjCMethodDeclSelector(
7863 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy,
7864 ArrayRef<IdentifierInfo *> SelIdents) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007865 // If we have an external source, load the entire class method
Sebastian Redld44cd6a2010-08-18 23:57:06 +00007866 // pool from the AST file.
Douglas Gregor95887f92010-07-08 23:20:03 +00007867 if (ExternalSource) {
Fangrui Song050229d2018-11-24 00:14:31 +00007868 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N;
7869 ++I) {
Douglas Gregor95887f92010-07-08 23:20:03 +00007870 Selector Sel = ExternalSource->GetExternalSelector(I);
Sebastian Redl75d8a322010-08-02 23:18:59 +00007871 if (Sel.isNull() || MethodPool.count(Sel))
Douglas Gregor95887f92010-07-08 23:20:03 +00007872 continue;
Sebastian Redl75d8a322010-08-02 23:18:59 +00007873
7874 ReadMethodPool(Sel);
Douglas Gregor95887f92010-07-08 23:20:03 +00007875 }
7876 }
7877
7878 // Build the set of methods we can see.
John McCall276321a2010-08-25 06:19:51 +00007879 typedef CodeCompletionResult Result;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007880 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007881 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007882 CodeCompletionContext::CCC_Other);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007883
Douglas Gregor95887f92010-07-08 23:20:03 +00007884 if (ReturnTy)
7885 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType());
Sebastian Redl75d8a322010-08-02 23:18:59 +00007886
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007887 Results.EnterNewScope();
Sebastian Redl75d8a322010-08-02 23:18:59 +00007888 for (GlobalMethodPool::iterator M = MethodPool.begin(),
7889 MEnd = MethodPool.end();
7890 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00007891 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first
7892 : &M->second.second;
7893 MethList && MethList->getMethod(); MethList = MethList->getNext()) {
Nico Weber2e0c8f72014-12-27 03:58:08 +00007894 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents))
Douglas Gregor95887f92010-07-08 23:20:03 +00007895 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007896
Douglas Gregor45879692010-07-08 23:37:41 +00007897 if (AtParameterName) {
7898 // Suggest parameter names we've seen before.
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007899 unsigned NumSelIdents = SelIdents.size();
Nico Weber2e0c8f72014-12-27 03:58:08 +00007900 if (NumSelIdents &&
7901 NumSelIdents <= MethList->getMethod()->param_size()) {
7902 ParmVarDecl *Param =
7903 MethList->getMethod()->parameters()[NumSelIdents - 1];
Douglas Gregor45879692010-07-08 23:37:41 +00007904 if (Param->getIdentifier()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007905 CodeCompletionBuilder Builder(Results.getAllocator(),
7906 Results.getCodeCompletionTUInfo());
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00007907 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00007908 Param->getIdentifier()->getName()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007909 Results.AddResult(Builder.TakeString());
Douglas Gregor45879692010-07-08 23:37:41 +00007910 }
7911 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007912
Douglas Gregor45879692010-07-08 23:37:41 +00007913 continue;
7914 }
Craig Topperc3ec1492014-05-26 06:22:03 +00007915
Nico Weber2e0c8f72014-12-27 03:58:08 +00007916 Result R(MethList->getMethod(),
7917 Results.getBasePriority(MethList->getMethod()), nullptr);
Dmitri Gribenko070a10e2013-06-16 03:47:57 +00007918 R.StartParameter = SelIdents.size();
Douglas Gregor95887f92010-07-08 23:20:03 +00007919 R.AllParametersAreInformative = false;
7920 R.DeclaringEntity = true;
7921 Results.MaybeAddResult(R, CurContext);
7922 }
7923 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007924
Douglas Gregor95887f92010-07-08 23:20:03 +00007925 Results.ExitScope();
Alex Lorenz847fda12017-01-03 11:56:40 +00007926
7927 if (!AtParameterName && !SelIdents.empty() &&
7928 SelIdents.front()->getName().startswith("init")) {
7929 for (const auto &M : PP.macros()) {
7930 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER")
7931 continue;
7932 Results.EnterNewScope();
7933 CodeCompletionBuilder Builder(Results.getAllocator(),
7934 Results.getCodeCompletionTUInfo());
7935 Builder.AddTypedTextChunk(
7936 Builder.getAllocator().CopyString(M.first->getName()));
7937 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro,
7938 CXCursor_MacroDefinition));
7939 Results.ExitScope();
7940 }
7941 }
7942
Eric Liuf5ba09f2018-07-04 10:01:18 +00007943 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
7944 Results.data(), Results.size());
Douglas Gregor95887f92010-07-08 23:20:03 +00007945}
Douglas Gregorb14904c2010-08-13 22:48:40 +00007946
Douglas Gregorec00a262010-08-24 22:20:20 +00007947void Sema::CodeCompletePreprocessorDirective(bool InConditional) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007948 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007949 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00007950 CodeCompletionContext::CCC_PreprocessorDirective);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007951 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007952
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007953 // #if <condition>
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00007954 CodeCompletionBuilder Builder(Results.getAllocator(),
7955 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007956 Builder.AddTypedTextChunk("if");
7957 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7958 Builder.AddPlaceholderChunk("condition");
7959 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007960
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007961 // #ifdef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007962 Builder.AddTypedTextChunk("ifdef");
7963 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7964 Builder.AddPlaceholderChunk("macro");
7965 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007966
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007967 // #ifndef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007968 Builder.AddTypedTextChunk("ifndef");
7969 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7970 Builder.AddPlaceholderChunk("macro");
7971 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007972
7973 if (InConditional) {
7974 // #elif <condition>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007975 Builder.AddTypedTextChunk("elif");
7976 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7977 Builder.AddPlaceholderChunk("condition");
7978 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007979
7980 // #else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007981 Builder.AddTypedTextChunk("else");
7982 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007983
7984 // #endif
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007985 Builder.AddTypedTextChunk("endif");
7986 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007987 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00007988
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007989 // #include "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007990 Builder.AddTypedTextChunk("include");
7991 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
7992 Builder.AddTextChunk("\"");
7993 Builder.AddPlaceholderChunk("header");
7994 Builder.AddTextChunk("\"");
7995 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00007996
7997 // #include <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00007998 Builder.AddTypedTextChunk("include");
7999 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8000 Builder.AddTextChunk("<");
8001 Builder.AddPlaceholderChunk("header");
8002 Builder.AddTextChunk(">");
8003 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008004
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008005 // #define <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008006 Builder.AddTypedTextChunk("define");
8007 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8008 Builder.AddPlaceholderChunk("macro");
8009 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008010
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008011 // #define <macro>(<args>)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008012 Builder.AddTypedTextChunk("define");
8013 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8014 Builder.AddPlaceholderChunk("macro");
8015 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8016 Builder.AddPlaceholderChunk("args");
8017 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8018 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008019
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008020 // #undef <macro>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008021 Builder.AddTypedTextChunk("undef");
8022 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8023 Builder.AddPlaceholderChunk("macro");
8024 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008025
8026 // #line <number>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008027 Builder.AddTypedTextChunk("line");
8028 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8029 Builder.AddPlaceholderChunk("number");
8030 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008031
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008032 // #line <number> "filename"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008033 Builder.AddTypedTextChunk("line");
8034 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8035 Builder.AddPlaceholderChunk("number");
8036 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8037 Builder.AddTextChunk("\"");
8038 Builder.AddPlaceholderChunk("filename");
8039 Builder.AddTextChunk("\"");
8040 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008041
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008042 // #error <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008043 Builder.AddTypedTextChunk("error");
8044 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8045 Builder.AddPlaceholderChunk("message");
8046 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008047
8048 // #pragma <arguments>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008049 Builder.AddTypedTextChunk("pragma");
8050 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8051 Builder.AddPlaceholderChunk("arguments");
8052 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008053
Erik Pilkingtonfa983902018-10-30 20:31:30 +00008054 if (getLangOpts().ObjC) {
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008055 // #import "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008056 Builder.AddTypedTextChunk("import");
8057 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8058 Builder.AddTextChunk("\"");
8059 Builder.AddPlaceholderChunk("header");
8060 Builder.AddTextChunk("\"");
8061 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008062
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008063 // #import <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008064 Builder.AddTypedTextChunk("import");
8065 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8066 Builder.AddTextChunk("<");
8067 Builder.AddPlaceholderChunk("header");
8068 Builder.AddTextChunk(">");
8069 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008070 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008071
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008072 // #include_next "header"
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008073 Builder.AddTypedTextChunk("include_next");
8074 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8075 Builder.AddTextChunk("\"");
8076 Builder.AddPlaceholderChunk("header");
8077 Builder.AddTextChunk("\"");
8078 Results.AddResult(Builder.TakeString());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008079
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008080 // #include_next <header>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008081 Builder.AddTypedTextChunk("include_next");
8082 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8083 Builder.AddTextChunk("<");
8084 Builder.AddPlaceholderChunk("header");
8085 Builder.AddTextChunk(">");
8086 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008087
8088 // #warning <message>
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008089 Builder.AddTypedTextChunk("warning");
8090 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8091 Builder.AddPlaceholderChunk("message");
8092 Results.AddResult(Builder.TakeString());
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008093
8094 // Note: #ident and #sccs are such crazy anachronisms that we don't provide
8095 // completions for them. And __include_macros is a Clang-internal extension
8096 // that we don't want to encourage anyone to use.
8097
8098 // FIXME: we don't support #assert or #unassert, so don't suggest them.
8099 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008100
8101 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008102 Results.data(), Results.size());
8103}
8104
8105void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) {
Fangrui Song050229d2018-11-24 00:14:31 +00008106 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction
8107 : Sema::PCC_Namespace);
Douglas Gregor3a7ad252010-08-24 19:08:16 +00008108}
8109
Douglas Gregorec00a262010-08-24 22:20:20 +00008110void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008111 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008112 CodeCompleter->getCodeCompletionTUInfo(),
Fangrui Song050229d2018-11-24 00:14:31 +00008113 IsDefinition ? CodeCompletionContext::CCC_MacroName
8114 : CodeCompletionContext::CCC_MacroNameUse);
Douglas Gregor12785102010-08-24 20:21:13 +00008115 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008116 // Add just the names of macros, not their arguments.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008117 CodeCompletionBuilder Builder(Results.getAllocator(),
8118 Results.getCodeCompletionTUInfo());
Douglas Gregor12785102010-08-24 20:21:13 +00008119 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008120 for (Preprocessor::macro_iterator M = PP.macro_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00008121 MEnd = PP.macro_end();
Douglas Gregor12785102010-08-24 20:21:13 +00008122 M != MEnd; ++M) {
Fangrui Song050229d2018-11-24 00:14:31 +00008123 Builder.AddTypedTextChunk(
8124 Builder.getAllocator().CopyString(M->first->getName()));
8125 Results.AddResult(CodeCompletionResult(
8126 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition));
Douglas Gregor12785102010-08-24 20:21:13 +00008127 }
8128 Results.ExitScope();
8129 } else if (IsDefinition) {
8130 // FIXME: Can we detect when the user just wrote an include guard above?
8131 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008132
Douglas Gregor0ac41382010-09-23 23:01:17 +00008133 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008134 Results.data(), Results.size());
Douglas Gregor12785102010-08-24 20:21:13 +00008135}
8136
Douglas Gregorec00a262010-08-24 22:20:20 +00008137void Sema::CodeCompletePreprocessorExpression() {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008138 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008139 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00008140 CodeCompletionContext::CCC_PreprocessorExpression);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008141
Douglas Gregorec00a262010-08-24 22:20:20 +00008142 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008143 AddMacroResults(PP, Results,
8144 CodeCompleter ? CodeCompleter->loadExternal() : false,
8145 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008146
Fangrui Song050229d2018-11-24 00:14:31 +00008147 // defined (<macro>)
Douglas Gregorec00a262010-08-24 22:20:20 +00008148 Results.EnterNewScope();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008149 CodeCompletionBuilder Builder(Results.getAllocator(),
8150 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00008151 Builder.AddTypedTextChunk("defined");
8152 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
8153 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
8154 Builder.AddPlaceholderChunk("macro");
8155 Builder.AddChunk(CodeCompletionString::CK_RightParen);
8156 Results.AddResult(Builder.TakeString());
Douglas Gregorec00a262010-08-24 22:20:20 +00008157 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008158
8159 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8160 Results.data(), Results.size());
Douglas Gregorec00a262010-08-24 22:20:20 +00008161}
8162
8163void Sema::CodeCompletePreprocessorMacroArgument(Scope *S,
8164 IdentifierInfo *Macro,
8165 MacroInfo *MacroInfo,
8166 unsigned Argument) {
8167 // FIXME: In the future, we could provide "overload" results, much like we
8168 // do for function calls.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008169
Argyrios Kyrtzidis75f6cd22011-08-18 19:41:28 +00008170 // Now just ignore this. There will be another code-completion callback
8171 // for the expanded tokens.
Douglas Gregorec00a262010-08-24 22:20:20 +00008172}
8173
Sam McCall3d8051a2018-09-18 08:40:41 +00008174// This handles completion inside an #include filename, e.g. #include <foo/ba
8175// We look for the directory "foo" under each directory on the include path,
8176// list its files, and reassemble the appropriate #include.
8177void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) {
8178 // RelDir should use /, but unescaped \ is possible on windows!
8179 // Our completions will normalize to / for simplicity, this case is rare.
8180 std::string RelDir = llvm::sys::path::convert_to_slash(Dir);
8181 // We need the native slashes for the actual file system interactions.
8182 SmallString<128> NativeRelDir = StringRef(RelDir);
8183 llvm::sys::path::native(NativeRelDir);
8184 auto FS = getSourceManager().getFileManager().getVirtualFileSystem();
8185
8186 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8187 CodeCompleter->getCodeCompletionTUInfo(),
8188 CodeCompletionContext::CCC_IncludedFile);
8189 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results.
8190
8191 // Helper: adds one file or directory completion result.
8192 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) {
8193 SmallString<64> TypedChunk = Filename;
8194 // Directory completion is up to the slash, e.g. <sys/
8195 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"');
8196 auto R = SeenResults.insert(TypedChunk);
8197 if (R.second) { // New completion
8198 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk);
8199 *R.first = InternedTyped; // Avoid dangling StringRef.
8200 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(),
8201 CodeCompleter->getCodeCompletionTUInfo());
8202 Builder.AddTypedTextChunk(InternedTyped);
8203 // The result is a "Pattern", which is pretty opaque.
8204 // We may want to include the real filename to allow smart ranking.
8205 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
8206 }
8207 };
8208
8209 // Helper: scans IncludeDir for nice files, and adds results for each.
8210 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, bool IsSystem) {
8211 llvm::SmallString<128> Dir = IncludeDir;
8212 if (!NativeRelDir.empty())
8213 llvm::sys::path::append(Dir, NativeRelDir);
8214
8215 std::error_code EC;
8216 unsigned Count = 0;
8217 for (auto It = FS->dir_begin(Dir, EC);
Jonas Devliegherefc514902018-10-10 13:27:25 +00008218 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008219 if (++Count == 2500) // If we happen to hit a huge directory,
8220 break; // bail out early so we're not too slow.
8221 StringRef Filename = llvm::sys::path::filename(It->path());
8222 switch (It->type()) {
8223 case llvm::sys::fs::file_type::directory_file:
8224 AddCompletion(Filename, /*IsDirectory=*/true);
8225 break;
8226 case llvm::sys::fs::file_type::regular_file:
8227 // Only files that really look like headers. (Except in system dirs).
8228 if (!IsSystem) {
8229 // Header extensions from Types.def, which we can't depend on here.
8230 if (!(Filename.endswith_lower(".h") ||
8231 Filename.endswith_lower(".hh") ||
8232 Filename.endswith_lower(".hpp") ||
8233 Filename.endswith_lower(".inc")))
8234 break;
8235 }
8236 AddCompletion(Filename, /*IsDirectory=*/false);
8237 break;
8238 default:
8239 break;
8240 }
8241 }
8242 };
8243
8244 // Helper: adds results relative to IncludeDir, if possible.
8245 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir,
8246 bool IsSystem) {
Sam McCall3d8051a2018-09-18 08:40:41 +00008247 switch (IncludeDir.getLookupType()) {
8248 case DirectoryLookup::LT_HeaderMap:
8249 // header maps are not (currently) enumerable.
8250 break;
8251 case DirectoryLookup::LT_NormalDir:
8252 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem);
8253 break;
8254 case DirectoryLookup::LT_Framework:
8255 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem);
8256 break;
8257 }
8258 };
8259
8260 // Finally with all our helpers, we can scan the include path.
8261 // Do this in standard order so deduplication keeps the right file.
8262 // (In case we decide to add more details to the results later).
8263 const auto &S = PP.getHeaderSearchInfo();
8264 using llvm::make_range;
8265 if (!Angled) {
8266 // The current directory is on the include path for "quoted" includes.
8267 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry();
8268 if (CurFile && CurFile->getDir())
8269 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false);
8270 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end()))
8271 AddFilesFromDirLookup(D, false);
8272 }
8273 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end()))
Sam McCall3e4f5eb2018-10-01 11:56:42 +00008274 AddFilesFromDirLookup(D, false);
Sam McCall3d8051a2018-09-18 08:40:41 +00008275 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end()))
8276 AddFilesFromDirLookup(D, true);
8277
8278 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8279 Results.data(), Results.size());
8280}
8281
Douglas Gregor11583702010-08-25 17:04:25 +00008282void Sema::CodeCompleteNaturalLanguage() {
Douglas Gregor11583702010-08-25 17:04:25 +00008283 HandleCodeCompleteResults(this, CodeCompleter,
Fangrui Song050229d2018-11-24 00:14:31 +00008284 CodeCompletionContext::CCC_NaturalLanguage, nullptr,
8285 0);
Douglas Gregor11583702010-08-25 17:04:25 +00008286}
8287
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008288void Sema::CodeCompleteAvailabilityPlatformName() {
8289 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
8290 CodeCompleter->getCodeCompletionTUInfo(),
8291 CodeCompletionContext::CCC_Other);
8292 Results.EnterNewScope();
8293 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"};
8294 for (const char *Platform : llvm::makeArrayRef(Platforms)) {
8295 Results.AddResult(CodeCompletionResult(Platform));
8296 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString(
8297 Twine(Platform) + "ApplicationExtension")));
8298 }
8299 Results.ExitScope();
Eric Liuf5ba09f2018-07-04 10:01:18 +00008300 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
8301 Results.data(), Results.size());
Alex Lorenzf7f6f822017-05-09 16:05:04 +00008302}
8303
Fangrui Song050229d2018-11-24 00:14:31 +00008304void Sema::GatherGlobalCodeCompletions(
8305 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
8306 SmallVectorImpl<CodeCompletionResult> &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00008307 ResultBuilder Builder(*this, Allocator, CCTUInfo,
8308 CodeCompletionContext::CCC_Recovery);
Douglas Gregor39982192010-08-15 06:18:01 +00008309 if (!CodeCompleter || CodeCompleter->includeGlobals()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008310 CodeCompletionDeclConsumer Consumer(Builder,
Douglas Gregor39982192010-08-15 06:18:01 +00008311 Context.getTranslationUnitDecl());
Sam McCallbb2cf632018-01-12 14:51:47 +00008312 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName,
8313 Consumer,
8314 !CodeCompleter || CodeCompleter->loadExternal());
Douglas Gregor39982192010-08-15 06:18:01 +00008315 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008316
Douglas Gregorb14904c2010-08-13 22:48:40 +00008317 if (!CodeCompleter || CodeCompleter->includeMacros())
Eric Liu88de9f62018-09-19 09:34:55 +00008318 AddMacroResults(PP, Builder,
8319 CodeCompleter ? CodeCompleter->loadExternal() : false,
8320 true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00008321
Douglas Gregorb14904c2010-08-13 22:48:40 +00008322 Results.clear();
Fangrui Song050229d2018-11-24 00:14:31 +00008323 Results.insert(Results.end(), Builder.data(),
8324 Builder.data() + Builder.size());
Douglas Gregorb14904c2010-08-13 22:48:40 +00008325}