blob: 7a8f31f0d1e655d6677ac427b209b4f0a555b30d [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 Nilsson90646732018-12-12 15:06:16 +00001031 Qualifiers MethodQuals =
1032 Qualifiers::fromCVRMask(Method->getTypeQualifiers());
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001033 if (ObjectTypeQualifiers == MethodQuals)
1034 R.Priority += CCD_ObjectQualifierMatch;
1035 else if (ObjectTypeQualifiers - MethodQuals) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001036 // The method cannot be invoked, because doing so would drop
Douglas Gregor9be0ed42010-08-26 16:36:48 +00001037 // qualifiers.
1038 return;
1039 }
1040 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001041
Douglas Gregorc580c522010-01-14 01:09:38 +00001042 // Insert this result into the set of results.
1043 Results.push_back(R);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001044
Douglas Gregor0212fd72010-09-21 16:06:22 +00001045 if (!AsNestedNameSpecifier)
1046 MaybeAddConstructorResults(R);
Douglas Gregorc580c522010-01-14 01:09:38 +00001047}
1048
Douglas Gregor78a21012010-01-14 16:01:26 +00001049void ResultBuilder::AddResult(Result R) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001050 assert(R.Kind != Result::RK_Declaration &&
Fangrui Song050229d2018-11-24 00:14:31 +00001051 "Declaration results need more context");
Douglas Gregor78a21012010-01-14 16:01:26 +00001052 Results.push_back(R);
1053}
1054
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001055/// Enter into a new scope.
Benjamin Kramer3204b152015-05-29 19:42:19 +00001056void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); }
Douglas Gregor3545ff42009-09-21 16:56:56 +00001057
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001058/// Exit from the current scope.
Douglas Gregor3545ff42009-09-21 16:56:56 +00001059void ResultBuilder::ExitScope() {
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001060 for (ShadowMap::iterator E = ShadowMaps.back().begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00001061 EEnd = ShadowMaps.back().end();
1062 E != EEnd; ++E)
Douglas Gregor05e7ca32009-12-06 20:23:50 +00001063 E->second.Destroy();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001064
Douglas Gregor3545ff42009-09-21 16:56:56 +00001065 ShadowMaps.pop_back();
1066}
1067
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001068/// Determines whether this given declaration will be found by
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001069/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001070bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001071 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001072
Richard Smith541b38b2013-09-20 01:15:31 +00001073 // If name lookup finds a local extern declaration, then we are in a
1074 // context where it behaves like an ordinary name.
1075 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001076 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001077 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001078 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001079 if (isa<ObjCIvarDecl>(ND))
1080 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001081 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001082
Douglas Gregor9d64c5e2009-09-21 20:51:25 +00001083 return ND->getIdentifierNamespace() & IDNS;
1084}
1085
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001086/// Determines whether this given declaration will be found by
Douglas Gregor70febae2010-05-28 00:49:12 +00001087/// ordinary name lookup but is not a type name.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001088bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001089 ND = ND->getUnderlyingDecl();
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001090 if (isa<TypeDecl>(ND))
Douglas Gregor70febae2010-05-28 00:49:12 +00001091 return false;
Alex Lorenzf3df1f72017-11-14 01:46:24 +00001092 // Objective-C interfaces names are not filtered by this method because they
1093 // can be used in a class property expression. We can still filter out
1094 // @class declarations though.
1095 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) {
1096 if (!ID->getDefinition())
1097 return false;
1098 }
1099
Richard Smith541b38b2013-09-20 01:15:31 +00001100 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001101 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregor9858ed52010-06-15 20:26:51 +00001102 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member;
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001103 else if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor05fcf842010-11-02 20:36:02 +00001104 if (isa<ObjCIvarDecl>(ND))
1105 return true;
Douglas Gregor05fcf842010-11-02 20:36:02 +00001106 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001107
Douglas Gregor70febae2010-05-28 00:49:12 +00001108 return ND->getIdentifierNamespace() & IDNS;
1109}
1110
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001111bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const {
Douglas Gregor85b50632010-07-28 21:50:18 +00001112 if (!IsOrdinaryNonTypeName(ND))
1113 return 0;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001114
Fangrui Song050229d2018-11-24 00:14:31 +00001115 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl()))
Douglas Gregor85b50632010-07-28 21:50:18 +00001116 if (VD->getType()->isIntegralOrEnumerationType())
1117 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001118
Douglas Gregor85b50632010-07-28 21:50:18 +00001119 return false;
1120}
1121
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001122/// Determines whether this given declaration will be found by
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001123/// ordinary name lookup.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001124bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const {
George Burgess IV00f70bd2018-03-01 05:43:23 +00001125 ND = ND->getUnderlyingDecl();
Douglas Gregor70febae2010-05-28 00:49:12 +00001126
Richard Smith541b38b2013-09-20 01:15:31 +00001127 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern;
David Blaikiebbafb8a2012-03-11 07:00:24 +00001128 if (SemaRef.getLangOpts().CPlusPlus)
John McCalle87beb22010-04-23 18:46:30 +00001129 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001130
Fangrui Song050229d2018-11-24 00:14:31 +00001131 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) &&
1132 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001133}
1134
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001135/// Determines whether the given declaration is suitable as the
Douglas Gregor3545ff42009-09-21 16:56:56 +00001136/// start of a C++ nested-name-specifier, e.g., a class or namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001137bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001138 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001139 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001140 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001141
Douglas Gregor3545ff42009-09-21 16:56:56 +00001142 return SemaRef.isAcceptableNestedNameSpecifier(ND);
1143}
1144
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001145/// Determines whether the given declaration is an enumeration.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001146bool ResultBuilder::IsEnum(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001147 return isa<EnumDecl>(ND);
1148}
1149
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001150/// Determines whether the given declaration is a class or struct.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001151bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001152 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001153 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001154 ND = ClassTemplate->getTemplatedDecl();
Joao Matosdc86f942012-08-31 18:45:21 +00001155
1156 // For purposes of this check, interfaces match too.
Fangrui Song050229d2018-11-24 00:14:31 +00001157 if (const auto *RD = dyn_cast<RecordDecl>(ND))
1158 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct ||
1159 RD->getTagKind() == TTK_Interface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001160
Douglas Gregor3545ff42009-09-21 16:56:56 +00001161 return false;
1162}
1163
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001164/// Determines whether the given declaration is a union.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001165bool ResultBuilder::IsUnion(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001166 // Allow us to find class templates, too.
Fangrui Song050229d2018-11-24 00:14:31 +00001167 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND))
Douglas Gregor3545ff42009-09-21 16:56:56 +00001168 ND = ClassTemplate->getTemplatedDecl();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001169
Fangrui Song050229d2018-11-24 00:14:31 +00001170 if (const auto *RD = dyn_cast<RecordDecl>(ND))
Abramo Bagnara6150c882010-05-11 21:36:43 +00001171 return RD->getTagKind() == TTK_Union;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001172
Douglas Gregor3545ff42009-09-21 16:56:56 +00001173 return false;
1174}
1175
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001176/// Determines whether the given declaration is a namespace.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001177bool ResultBuilder::IsNamespace(const NamedDecl *ND) const {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001178 return isa<NamespaceDecl>(ND);
1179}
1180
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001181/// Determines whether the given declaration is a namespace or
Douglas Gregor3545ff42009-09-21 16:56:56 +00001182/// namespace alias.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001183bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001184 return isa<NamespaceDecl>(ND->getUnderlyingDecl());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001185}
1186
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001187/// Determines whether the given declaration is a type.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001188bool ResultBuilder::IsType(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001189 ND = ND->getUnderlyingDecl();
Douglas Gregor99fa2642010-08-24 01:06:58 +00001190 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND);
Douglas Gregor3545ff42009-09-21 16:56:56 +00001191}
1192
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001193/// Determines which members of a class should be visible via
Douglas Gregor99fe2ad2009-12-11 17:31:05 +00001194/// "." or "->". Only value declarations, nested name specifiers, and
1195/// using declarations thereof should show up.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001196bool ResultBuilder::IsMember(const NamedDecl *ND) const {
Richard Smithf2005d32015-12-29 23:34:32 +00001197 ND = ND->getUnderlyingDecl();
Douglas Gregor70788392009-12-11 18:14:22 +00001198 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) ||
Richard Smithf2005d32015-12-29 23:34:32 +00001199 isa<ObjCPropertyDecl>(ND);
Douglas Gregore412a5a2009-09-23 22:26:46 +00001200}
1201
Douglas Gregora817a192010-05-27 23:06:34 +00001202static bool isObjCReceiverType(ASTContext &C, QualType T) {
1203 T = C.getCanonicalType(T);
1204 switch (T->getTypeClass()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001205 case Type::ObjCObject:
Douglas Gregora817a192010-05-27 23:06:34 +00001206 case Type::ObjCInterface:
1207 case Type::ObjCObjectPointer:
1208 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001209
Douglas Gregora817a192010-05-27 23:06:34 +00001210 case Type::Builtin:
1211 switch (cast<BuiltinType>(T)->getKind()) {
1212 case BuiltinType::ObjCId:
1213 case BuiltinType::ObjCClass:
1214 case BuiltinType::ObjCSel:
1215 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001216
Douglas Gregora817a192010-05-27 23:06:34 +00001217 default:
1218 break;
1219 }
1220 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001221
Douglas Gregora817a192010-05-27 23:06:34 +00001222 default:
1223 break;
1224 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001225
David Blaikiebbafb8a2012-03-11 07:00:24 +00001226 if (!C.getLangOpts().CPlusPlus)
Douglas Gregora817a192010-05-27 23:06:34 +00001227 return false;
1228
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001229 // FIXME: We could perform more analysis here to determine whether a
Douglas Gregora817a192010-05-27 23:06:34 +00001230 // particular class type has any conversions to Objective-C types. For now,
1231 // just accept all class types.
1232 return T->isDependentType() || T->isRecordType();
1233}
1234
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001235bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const {
Douglas Gregora817a192010-05-27 23:06:34 +00001236 QualType T = getDeclUsageType(SemaRef.Context, ND);
1237 if (T.isNull())
1238 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001239
Douglas Gregora817a192010-05-27 23:06:34 +00001240 T = SemaRef.Context.getBaseElementType(T);
1241 return isObjCReceiverType(SemaRef.Context, T);
1242}
1243
Fangrui Song050229d2018-11-24 00:14:31 +00001244bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture(
1245 const NamedDecl *ND) const {
Douglas Gregord8c61782012-02-15 15:34:24 +00001246 if (IsObjCMessageReceiver(ND))
1247 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001248
Fangrui Song050229d2018-11-24 00:14:31 +00001249 const auto *Var = dyn_cast<VarDecl>(ND);
Douglas Gregord8c61782012-02-15 15:34:24 +00001250 if (!Var)
1251 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001252
Douglas Gregord8c61782012-02-15 15:34:24 +00001253 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>();
1254}
1255
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001256bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const {
David Blaikiebbafb8a2012-03-11 07:00:24 +00001257 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) ||
1258 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND)))
Douglas Gregor68762e72010-08-23 21:17:50 +00001259 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001260
Douglas Gregor68762e72010-08-23 21:17:50 +00001261 QualType T = getDeclUsageType(SemaRef.Context, ND);
1262 if (T.isNull())
1263 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001264
Douglas Gregor68762e72010-08-23 21:17:50 +00001265 T = SemaRef.Context.getBaseElementType(T);
1266 return T->isObjCObjectType() || T->isObjCObjectPointerType() ||
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001267 T->isObjCIdType() ||
David Blaikiebbafb8a2012-03-11 07:00:24 +00001268 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType());
Douglas Gregor68762e72010-08-23 21:17:50 +00001269}
Douglas Gregora817a192010-05-27 23:06:34 +00001270
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001271bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const {
Douglas Gregor0ac41382010-09-23 23:01:17 +00001272 return false;
1273}
1274
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001275/// Determines whether the given declaration is an Objective-C
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001276/// instance variable.
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00001277bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const {
Douglas Gregor2b8162b2010-01-14 16:08:12 +00001278 return isa<ObjCIvarDecl>(ND);
1279}
1280
Douglas Gregorc580c522010-01-14 01:09:38 +00001281namespace {
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001282
Fangrui Song050229d2018-11-24 00:14:31 +00001283/// Visible declaration consumer that adds a code-completion result
1284/// for each visible declaration.
1285class CodeCompletionDeclConsumer : public VisibleDeclConsumer {
1286 ResultBuilder &Results;
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001287 DeclContext *InitialLookupCtx;
1288 // NamingClass and BaseType are used for access-checking. See
1289 // Sema::IsSimplyAccessible for details.
1290 CXXRecordDecl *NamingClass;
1291 QualType BaseType;
Fangrui Song050229d2018-11-24 00:14:31 +00001292 std::vector<FixItHint> FixIts;
Haojian Wu10d95c52018-01-17 14:29:25 +00001293
Fangrui Song050229d2018-11-24 00:14:31 +00001294public:
1295 CodeCompletionDeclConsumer(
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001296 ResultBuilder &Results, DeclContext *InitialLookupCtx,
1297 QualType BaseType = QualType(),
1298 std::vector<FixItHint> FixIts = std::vector<FixItHint>())
1299 : Results(Results), InitialLookupCtx(InitialLookupCtx),
1300 FixIts(std::move(FixIts)) {
1301 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx);
1302 // If BaseType was not provided explicitly, emulate implicit 'this->'.
1303 if (BaseType.isNull()) {
1304 auto ThisType = Results.getSema().getCurrentThisType();
1305 if (!ThisType.isNull()) {
1306 assert(ThisType->isPointerType());
1307 BaseType = ThisType->getPointeeType();
1308 if (!NamingClass)
1309 NamingClass = BaseType->getAsCXXRecordDecl();
1310 }
1311 }
1312 this->BaseType = BaseType;
1313 }
Craig Toppere14c0f82014-03-12 04:55:44 +00001314
Fangrui Song050229d2018-11-24 00:14:31 +00001315 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
1316 bool InBaseClass) override {
Fangrui Song050229d2018-11-24 00:14:31 +00001317 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr,
Ilya Biryukov98397552018-12-05 17:38:39 +00001318 false, IsAccessible(ND, Ctx), FixIts);
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00001319 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass);
Fangrui Song050229d2018-11-24 00:14:31 +00001320 }
Haojian Wu10d95c52018-01-17 14:29:25 +00001321
Fangrui Song050229d2018-11-24 00:14:31 +00001322 void EnteredContext(DeclContext *Ctx) override {
1323 Results.addVisitedContext(Ctx);
1324 }
Ilya Biryukov98397552018-12-05 17:38:39 +00001325
1326private:
1327 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) {
1328 // Naming class to use for access check. In most cases it was provided
1329 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)),
1330 // for unqualified lookup we fallback to the \p Ctx in which we found the
1331 // member.
1332 auto *NamingClass = this->NamingClass;
1333 QualType BaseType = this->BaseType;
1334 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) {
1335 if (!NamingClass)
1336 NamingClass = Cls;
1337 // When we emulate implicit 'this->' in an unqualified lookup, we might
1338 // end up with an invalid naming class. In that case, we avoid emulating
1339 // 'this->' qualifier to satisfy preconditions of the access checking.
1340 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() &&
1341 !NamingClass->isDerivedFrom(Cls)) {
1342 NamingClass = Cls;
1343 BaseType = QualType();
1344 }
1345 } else {
1346 // The decl was found outside the C++ class, so only ObjC access checks
1347 // apply. Those do not rely on NamingClass and BaseType, so we clear them
1348 // out.
1349 NamingClass = nullptr;
1350 BaseType = QualType();
1351 }
1352 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType);
1353 }
Fangrui Song050229d2018-11-24 00:14:31 +00001354};
1355} // namespace
Douglas Gregorc580c522010-01-14 01:09:38 +00001356
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001357/// Add type specifiers for the current language as keyword results.
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001358static void AddTypeSpecifierResults(const LangOptions &LangOpts,
Douglas Gregor3545ff42009-09-21 16:56:56 +00001359 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001360 typedef CodeCompletionResult Result;
Douglas Gregora2db7932010-05-26 22:00:08 +00001361 Results.AddResult(Result("short", CCP_Type));
1362 Results.AddResult(Result("long", CCP_Type));
1363 Results.AddResult(Result("signed", CCP_Type));
1364 Results.AddResult(Result("unsigned", CCP_Type));
1365 Results.AddResult(Result("void", CCP_Type));
1366 Results.AddResult(Result("char", CCP_Type));
1367 Results.AddResult(Result("int", CCP_Type));
1368 Results.AddResult(Result("float", CCP_Type));
1369 Results.AddResult(Result("double", CCP_Type));
1370 Results.AddResult(Result("enum", CCP_Type));
1371 Results.AddResult(Result("struct", CCP_Type));
1372 Results.AddResult(Result("union", CCP_Type));
1373 Results.AddResult(Result("const", CCP_Type));
1374 Results.AddResult(Result("volatile", CCP_Type));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001375
Douglas Gregor3545ff42009-09-21 16:56:56 +00001376 if (LangOpts.C99) {
1377 // C99-specific
Douglas Gregora2db7932010-05-26 22:00:08 +00001378 Results.AddResult(Result("_Complex", CCP_Type));
1379 Results.AddResult(Result("_Imaginary", CCP_Type));
1380 Results.AddResult(Result("_Bool", CCP_Type));
1381 Results.AddResult(Result("restrict", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001382 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001383
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001384 CodeCompletionBuilder Builder(Results.getAllocator(),
1385 Results.getCodeCompletionTUInfo());
Douglas Gregor3545ff42009-09-21 16:56:56 +00001386 if (LangOpts.CPlusPlus) {
1387 // C++-specific
Fangrui Song050229d2018-11-24 00:14:31 +00001388 Results.AddResult(
1389 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0)));
Douglas Gregora2db7932010-05-26 22:00:08 +00001390 Results.AddResult(Result("class", CCP_Type));
1391 Results.AddResult(Result("wchar_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001392
Douglas Gregorf4c33342010-05-28 00:22:41 +00001393 // typename qualified-id
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001394 Builder.AddTypedTextChunk("typename");
1395 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1396 Builder.AddPlaceholderChunk("qualifier");
1397 Builder.AddTextChunk("::");
1398 Builder.AddPlaceholderChunk("name");
1399 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001400
Richard Smith2bf7fdb2013-01-02 11:42:31 +00001401 if (LangOpts.CPlusPlus11) {
Douglas Gregora2db7932010-05-26 22:00:08 +00001402 Results.AddResult(Result("auto", CCP_Type));
1403 Results.AddResult(Result("char16_t", CCP_Type));
1404 Results.AddResult(Result("char32_t", CCP_Type));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001405
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001406 Builder.AddTypedTextChunk("decltype");
1407 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1408 Builder.AddPlaceholderChunk("expression");
1409 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1410 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001411 }
Alex Lorenz46eed9d2017-02-13 23:35:59 +00001412 } else
1413 Results.AddResult(Result("__auto_type", CCP_Type));
1414
Richard Smith7b301e22018-05-24 21:51:52 +00001415 // GNU keywords
1416 if (LangOpts.GNUKeywords) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00001417 // FIXME: Enable when we actually support decimal floating point.
Douglas Gregor78a21012010-01-14 16:01:26 +00001418 // Results.AddResult(Result("_Decimal32"));
1419 // Results.AddResult(Result("_Decimal64"));
1420 // Results.AddResult(Result("_Decimal128"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001421
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001422 Builder.AddTypedTextChunk("typeof");
1423 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1424 Builder.AddPlaceholderChunk("expression");
1425 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001426
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001427 Builder.AddTypedTextChunk("typeof");
1428 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1429 Builder.AddPlaceholderChunk("type");
1430 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1431 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001432 }
Douglas Gregor86b42682015-06-19 18:27:52 +00001433
1434 // Nullability
Douglas Gregoraea7afd2015-06-24 22:02:08 +00001435 Results.AddResult(Result("_Nonnull", CCP_Type));
1436 Results.AddResult(Result("_Null_unspecified", CCP_Type));
1437 Results.AddResult(Result("_Nullable", CCP_Type));
Douglas Gregor3545ff42009-09-21 16:56:56 +00001438}
1439
John McCallfaf5fb42010-08-26 23:41:50 +00001440static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001441 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001442 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001443 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001444 // Note: we don't suggest either "auto" or "register", because both
1445 // are pointless as storage specifiers. Elsewhere, we suggest "auto"
1446 // in C++0x as a type specifier.
Douglas Gregor78a21012010-01-14 16:01:26 +00001447 Results.AddResult(Result("extern"));
1448 Results.AddResult(Result("static"));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001449
1450 if (LangOpts.CPlusPlus11) {
1451 CodeCompletionAllocator &Allocator = Results.getAllocator();
1452 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
1453
1454 // alignas
1455 Builder.AddTypedTextChunk("alignas");
1456 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1457 Builder.AddPlaceholderChunk("expression");
1458 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1459 Results.AddResult(Result(Builder.TakeString()));
1460
1461 Results.AddResult(Result("constexpr"));
1462 Results.AddResult(Result("thread_local"));
1463 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001464}
1465
John McCallfaf5fb42010-08-26 23:41:50 +00001466static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC,
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001467 const LangOptions &LangOpts,
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001468 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00001469 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001470 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001471 case Sema::PCC_Class:
1472 case Sema::PCC_MemberTemplate:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001473 if (LangOpts.CPlusPlus) {
Douglas Gregor78a21012010-01-14 16:01:26 +00001474 Results.AddResult(Result("explicit"));
1475 Results.AddResult(Result("friend"));
1476 Results.AddResult(Result("mutable"));
1477 Results.AddResult(Result("virtual"));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001478 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001479 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001480
John McCallfaf5fb42010-08-26 23:41:50 +00001481 case Sema::PCC_ObjCInterface:
1482 case Sema::PCC_ObjCImplementation:
1483 case Sema::PCC_Namespace:
1484 case Sema::PCC_Template:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001485 if (LangOpts.CPlusPlus || LangOpts.C99)
Douglas Gregor78a21012010-01-14 16:01:26 +00001486 Results.AddResult(Result("inline"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001487 break;
1488
John McCallfaf5fb42010-08-26 23:41:50 +00001489 case Sema::PCC_ObjCInstanceVariableList:
1490 case Sema::PCC_Expression:
1491 case Sema::PCC_Statement:
1492 case Sema::PCC_ForInit:
1493 case Sema::PCC_Condition:
1494 case Sema::PCC_RecoveryInFunction:
1495 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001496 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001497 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001498 break;
1499 }
1500}
1501
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001502static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt);
1503static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt);
1504static void AddObjCVisibilityResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001505 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001506static void AddObjCImplementationResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001507 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001508static void AddObjCInterfaceResults(const LangOptions &LangOpts,
Fangrui Song050229d2018-11-24 00:14:31 +00001509 ResultBuilder &Results, bool NeedAt);
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001510static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt);
Douglas Gregorf1934162010-01-13 21:24:21 +00001511
Douglas Gregorf4c33342010-05-28 00:22:41 +00001512static void AddTypedefResult(ResultBuilder &Results) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001513 CodeCompletionBuilder Builder(Results.getAllocator(),
1514 Results.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001515 Builder.AddTypedTextChunk("typedef");
1516 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1517 Builder.AddPlaceholderChunk("type");
1518 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1519 Builder.AddPlaceholderChunk("name");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001520 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001521}
1522
John McCallfaf5fb42010-08-26 23:41:50 +00001523static bool WantTypesInContext(Sema::ParserCompletionContext CCC,
Douglas Gregor70febae2010-05-28 00:49:12 +00001524 const LangOptions &LangOpts) {
Douglas Gregor70febae2010-05-28 00:49:12 +00001525 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001526 case Sema::PCC_Namespace:
1527 case Sema::PCC_Class:
1528 case Sema::PCC_ObjCInstanceVariableList:
1529 case Sema::PCC_Template:
1530 case Sema::PCC_MemberTemplate:
1531 case Sema::PCC_Statement:
1532 case Sema::PCC_RecoveryInFunction:
1533 case Sema::PCC_Type:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001534 case Sema::PCC_ParenthesizedExpression:
Douglas Gregor80039242011-02-15 20:33:25 +00001535 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor70febae2010-05-28 00:49:12 +00001536 return true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001537
John McCallfaf5fb42010-08-26 23:41:50 +00001538 case Sema::PCC_Expression:
1539 case Sema::PCC_Condition:
Douglas Gregor5e35d592010-09-14 23:59:36 +00001540 return LangOpts.CPlusPlus;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001541
Douglas Gregor5e35d592010-09-14 23:59:36 +00001542 case Sema::PCC_ObjCInterface:
1543 case Sema::PCC_ObjCImplementation:
Douglas Gregor70febae2010-05-28 00:49:12 +00001544 return false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001545
John McCallfaf5fb42010-08-26 23:41:50 +00001546 case Sema::PCC_ForInit:
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001547 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99;
Douglas Gregor70febae2010-05-28 00:49:12 +00001548 }
David Blaikie8a40f702012-01-17 06:56:22 +00001549
1550 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor70febae2010-05-28 00:49:12 +00001551}
1552
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001553static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context,
1554 const Preprocessor &PP) {
1555 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP);
Douglas Gregore5c79d52011-10-18 21:20:17 +00001556 Policy.AnonymousTagLocations = false;
1557 Policy.SuppressStrongLifetime = true;
Douglas Gregor2e10cf92011-11-03 00:16:13 +00001558 Policy.SuppressUnwrittenScope = true;
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00001559 Policy.SuppressScope = true;
Douglas Gregore5c79d52011-10-18 21:20:17 +00001560 return Policy;
1561}
1562
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001563/// Retrieve a printing policy suitable for code completion.
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00001564static PrintingPolicy getCompletionPrintingPolicy(Sema &S) {
1565 return getCompletionPrintingPolicy(S.Context, S.PP);
1566}
1567
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001568/// Retrieve the string representation of the given type as a string
Douglas Gregore5c79d52011-10-18 21:20:17 +00001569/// that has the appropriate lifetime for code completion.
1570///
1571/// This routine provides a fast path where we provide constant strings for
1572/// common type names.
Fangrui Song050229d2018-11-24 00:14:31 +00001573static const char *GetCompletionTypeString(QualType T, ASTContext &Context,
Douglas Gregore5c79d52011-10-18 21:20:17 +00001574 const PrintingPolicy &Policy,
1575 CodeCompletionAllocator &Allocator) {
1576 if (!T.getLocalQualifiers()) {
1577 // Built-in type names are constant strings.
1578 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T))
Argyrios Kyrtzidisbbff3da2012-05-05 04:20:28 +00001579 return BT->getNameAsCString(Policy);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001580
Douglas Gregore5c79d52011-10-18 21:20:17 +00001581 // Anonymous tag types are constant strings.
1582 if (const TagType *TagT = dyn_cast<TagType>(T))
1583 if (TagDecl *Tag = TagT->getDecl())
John McCall5ea95772013-03-09 00:54:27 +00001584 if (!Tag->hasNameForLinkage()) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001585 switch (Tag->getTagKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00001586 case TTK_Struct:
1587 return "struct <anonymous>";
1588 case TTK_Interface:
1589 return "__interface <anonymous>";
1590 case TTK_Class:
1591 return "class <anonymous>";
1592 case TTK_Union:
1593 return "union <anonymous>";
1594 case TTK_Enum:
1595 return "enum <anonymous>";
Douglas Gregore5c79d52011-10-18 21:20:17 +00001596 }
1597 }
1598 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001599
Douglas Gregore5c79d52011-10-18 21:20:17 +00001600 // Slow path: format the type as a string.
1601 std::string Result;
1602 T.getAsStringInternal(Result, Policy);
1603 return Allocator.CopyString(Result);
1604}
1605
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001606/// Add a completion for "this", if we're in a member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00001607static void addThisCompletion(Sema &S, ResultBuilder &Results) {
1608 QualType ThisTy = S.getCurrentThisType();
1609 if (ThisTy.isNull())
1610 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001611
Douglas Gregord8c61782012-02-15 15:34:24 +00001612 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001613 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregord8c61782012-02-15 15:34:24 +00001614 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Fangrui Song050229d2018-11-24 00:14:31 +00001615 Builder.AddResultTypeChunk(
1616 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator));
Douglas Gregord8c61782012-02-15 15:34:24 +00001617 Builder.AddTypedTextChunk("this");
Joao Matosdc86f942012-08-31 18:45:21 +00001618 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
Douglas Gregord8c61782012-02-15 15:34:24 +00001619}
1620
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001621static void AddStaticAssertResult(CodeCompletionBuilder &Builder,
1622 ResultBuilder &Results,
1623 const LangOptions &LangOpts) {
1624 if (!LangOpts.CPlusPlus11)
1625 return;
1626
1627 Builder.AddTypedTextChunk("static_assert");
1628 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1629 Builder.AddPlaceholderChunk("expression");
1630 Builder.AddChunk(CodeCompletionString::CK_Comma);
1631 Builder.AddPlaceholderChunk("message");
1632 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1633 Results.AddResult(CodeCompletionResult(Builder.TakeString()));
1634}
1635
Fangrui Song050229d2018-11-24 00:14:31 +00001636static void printOverrideString(llvm::raw_ostream &OS,
1637 CodeCompletionString *CCS) {
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001638 for (const auto &C : *CCS) {
1639 if (C.Kind == CodeCompletionString::CK_Optional)
1640 printOverrideString(OS, C.Optional);
1641 else
1642 OS << C.Text;
1643 // Add a space after return type.
1644 if (C.Kind == CodeCompletionString::CK_ResultType)
1645 OS << ' ';
1646 }
1647}
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001648
1649static void AddOverrideResults(ResultBuilder &Results,
1650 const CodeCompletionContext &CCContext,
1651 CodeCompletionBuilder &Builder) {
1652 Sema &S = Results.getSema();
1653 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext);
1654 // If not inside a class/struct/union return empty.
1655 if (!CR)
1656 return;
1657 // First store overrides within current class.
1658 // These are stored by name to make querying fast in the later step.
1659 llvm::StringMap<std::vector<FunctionDecl *>> Overrides;
1660 for (auto *Method : CR->methods()) {
1661 if (!Method->isVirtual() || !Method->getIdentifier())
1662 continue;
1663 Overrides[Method->getName()].push_back(Method);
1664 }
1665
1666 for (const auto &Base : CR->bases()) {
1667 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl();
1668 if (!BR)
1669 continue;
1670 for (auto *Method : BR->methods()) {
1671 if (!Method->isVirtual() || !Method->getIdentifier())
1672 continue;
1673 const auto it = Overrides.find(Method->getName());
1674 bool IsOverriden = false;
1675 if (it != Overrides.end()) {
1676 for (auto *MD : it->second) {
1677 // If the method in current body is not an overload of this virtual
1678 // function, then it overrides this one.
1679 if (!S.IsOverload(MD, Method, false)) {
1680 IsOverriden = true;
1681 break;
1682 }
1683 }
1684 }
1685 if (!IsOverriden) {
1686 // Generates a new CodeCompletionResult by taking this function and
1687 // converting it into an override declaration with only one chunk in the
1688 // final CodeCompletionString as a TypedTextChunk.
1689 std::string OverrideSignature;
1690 llvm::raw_string_ostream OS(OverrideSignature);
1691 CodeCompletionResult CCR(Method, 0);
1692 PrintingPolicy Policy =
1693 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor());
1694 auto *CCS = CCR.createCodeCompletionStringForOverride(
1695 S.getPreprocessor(), S.getASTContext(), Builder,
1696 /*IncludeBriefComments=*/false, CCContext, Policy);
1697 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern));
1698 }
1699 }
1700 }
1701}
1702
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00001703/// Add language constructs that show up for "ordinary" names.
Fangrui Song050229d2018-11-24 00:14:31 +00001704static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S,
1705 Sema &SemaRef, ResultBuilder &Results) {
Douglas Gregore5c79d52011-10-18 21:20:17 +00001706 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00001707 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001708
John McCall276321a2010-08-25 06:19:51 +00001709 typedef CodeCompletionResult Result;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001710 switch (CCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00001711 case Sema::PCC_Namespace:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001712 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001713 if (Results.includeCodePatterns()) {
1714 // namespace <identifier> { declarations }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001715 Builder.AddTypedTextChunk("namespace");
1716 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1717 Builder.AddPlaceholderChunk("identifier");
1718 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1719 Builder.AddPlaceholderChunk("declarations");
1720 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1721 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1722 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001723 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001724
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001725 // namespace identifier = identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001726 Builder.AddTypedTextChunk("namespace");
1727 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1728 Builder.AddPlaceholderChunk("name");
1729 Builder.AddChunk(CodeCompletionString::CK_Equal);
1730 Builder.AddPlaceholderChunk("namespace");
1731 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001732
1733 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001734 Builder.AddTypedTextChunk("using");
1735 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1736 Builder.AddTextChunk("namespace");
1737 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1738 Builder.AddPlaceholderChunk("identifier");
1739 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001740
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001741 // asm(string-literal)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001742 Builder.AddTypedTextChunk("asm");
1743 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1744 Builder.AddPlaceholderChunk("string-literal");
1745 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1746 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001747
Douglas Gregorf4c33342010-05-28 00:22:41 +00001748 if (Results.includeCodePatterns()) {
1749 // Explicit template instantiation
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001750 Builder.AddTypedTextChunk("template");
1751 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1752 Builder.AddPlaceholderChunk("declaration");
1753 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001754 } else {
1755 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregorf4c33342010-05-28 00:22:41 +00001756 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001757 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001758
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001759 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001760 AddObjCTopLevelResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001761
Douglas Gregorf4c33342010-05-28 00:22:41 +00001762 AddTypedefResult(Results);
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001763 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001764
John McCallfaf5fb42010-08-26 23:41:50 +00001765 case Sema::PCC_Class:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001766 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001767 // Using declaration
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001768 Builder.AddTypedTextChunk("using");
1769 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1770 Builder.AddPlaceholderChunk("qualifier");
1771 Builder.AddTextChunk("::");
1772 Builder.AddPlaceholderChunk("name");
1773 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001774
Douglas Gregorf4c33342010-05-28 00:22:41 +00001775 // using typename qualifier::name (only in a dependent context)
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001776 if (SemaRef.CurContext->isDependentContext()) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001777 Builder.AddTypedTextChunk("using");
1778 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1779 Builder.AddTextChunk("typename");
1780 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1781 Builder.AddPlaceholderChunk("qualifier");
1782 Builder.AddTextChunk("::");
1783 Builder.AddPlaceholderChunk("name");
1784 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001785 }
1786
Alex Lorenz8f4d3992017-02-13 23:19:40 +00001787 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
1788
John McCallfaf5fb42010-08-26 23:41:50 +00001789 if (CCC == Sema::PCC_Class) {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001790 AddTypedefResult(Results);
1791
Erik Verbruggen6524c052017-10-24 13:46:58 +00001792 bool IsNotInheritanceScope =
1793 !(S->getFlags() & Scope::ClassInheritanceScope);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001794 // public:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001795 Builder.AddTypedTextChunk("public");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001796 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001797 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001798 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001799
1800 // protected:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001801 Builder.AddTypedTextChunk("protected");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001802 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001803 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001804 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001805
1806 // private:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001807 Builder.AddTypedTextChunk("private");
Erik Verbruggen6524c052017-10-24 13:46:58 +00001808 if (IsNotInheritanceScope && Results.includeCodePatterns())
Douglas Gregor9489cdf2012-04-10 17:56:28 +00001809 Builder.AddChunk(CodeCompletionString::CK_Colon);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001810 Results.AddResult(Result(Builder.TakeString()));
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00001811
1812 // FIXME: This adds override results only if we are at the first word of
1813 // the declaration/definition. Also call this from other sides to have
1814 // more use-cases.
1815 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion,
1816 Builder);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001817 }
1818 }
Adrian Prantlf3b3ccd2017-12-19 22:06:11 +00001819 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001820
John McCallfaf5fb42010-08-26 23:41:50 +00001821 case Sema::PCC_Template:
1822 case Sema::PCC_MemberTemplate:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001823 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001824 // template < parameters >
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001825 Builder.AddTypedTextChunk("template");
1826 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
1827 Builder.AddPlaceholderChunk("parameters");
1828 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
1829 Results.AddResult(Result(Builder.TakeString()));
Eric Liub87c6eb2018-10-15 12:37:23 +00001830 } else {
1831 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001832 }
1833
David Blaikiebbafb8a2012-03-11 07:00:24 +00001834 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1835 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001836 break;
1837
John McCallfaf5fb42010-08-26 23:41:50 +00001838 case Sema::PCC_ObjCInterface:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001839 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true);
1840 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1841 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001842 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001843
John McCallfaf5fb42010-08-26 23:41:50 +00001844 case Sema::PCC_ObjCImplementation:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001845 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true);
1846 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
1847 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregorf1934162010-01-13 21:24:21 +00001848 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001849
John McCallfaf5fb42010-08-26 23:41:50 +00001850 case Sema::PCC_ObjCInstanceVariableList:
David Blaikiebbafb8a2012-03-11 07:00:24 +00001851 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true);
Douglas Gregor48d46252010-01-13 21:54:15 +00001852 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001853
John McCallfaf5fb42010-08-26 23:41:50 +00001854 case Sema::PCC_RecoveryInFunction:
1855 case Sema::PCC_Statement: {
Douglas Gregorf4c33342010-05-28 00:22:41 +00001856 AddTypedefResult(Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001857
David Blaikiebbafb8a2012-03-11 07:00:24 +00001858 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() &&
1859 SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001860 Builder.AddTypedTextChunk("try");
1861 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1862 Builder.AddPlaceholderChunk("statements");
1863 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1864 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1865 Builder.AddTextChunk("catch");
1866 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1867 Builder.AddPlaceholderChunk("declaration");
1868 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1869 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1870 Builder.AddPlaceholderChunk("statements");
1871 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1872 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1873 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001874 }
Erik Pilkingtonfa983902018-10-30 20:31:30 +00001875 if (SemaRef.getLangOpts().ObjC)
Douglas Gregorf98e6a22010-01-13 23:51:12 +00001876 AddObjCStatementResults(Results, true);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001877
Douglas Gregorf64acca2010-05-25 21:41:55 +00001878 if (Results.includeCodePatterns()) {
1879 // if (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001880 Builder.AddTypedTextChunk("if");
1881 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001882 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001883 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001884 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001885 Builder.AddPlaceholderChunk("expression");
1886 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1887 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1888 Builder.AddPlaceholderChunk("statements");
1889 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1890 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1891 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001892
Douglas Gregorf64acca2010-05-25 21:41:55 +00001893 // switch (condition) { }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001894 Builder.AddTypedTextChunk("switch");
1895 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001896 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001897 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001898 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001899 Builder.AddPlaceholderChunk("expression");
1900 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1901 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1902 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1903 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1904 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001905 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001906
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001907 // Switch-specific statements.
Sam McCallaeb4b3e2018-10-10 10:51:48 +00001908 if (SemaRef.getCurFunction() &&
1909 !SemaRef.getCurFunction()->SwitchStack.empty()) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001910 // case expression:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001911 Builder.AddTypedTextChunk("case");
1912 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1913 Builder.AddPlaceholderChunk("expression");
1914 Builder.AddChunk(CodeCompletionString::CK_Colon);
1915 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001916
1917 // default:
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001918 Builder.AddTypedTextChunk("default");
1919 Builder.AddChunk(CodeCompletionString::CK_Colon);
1920 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001921 }
1922
Douglas Gregorf64acca2010-05-25 21:41:55 +00001923 if (Results.includeCodePatterns()) {
1924 /// while (condition) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001925 Builder.AddTypedTextChunk("while");
1926 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001927 if (SemaRef.getLangOpts().CPlusPlus)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001928 Builder.AddPlaceholderChunk("condition");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001929 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001930 Builder.AddPlaceholderChunk("expression");
1931 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1932 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1933 Builder.AddPlaceholderChunk("statements");
1934 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1935 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1936 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001937
1938 // do { statements } while ( expression );
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001939 Builder.AddTypedTextChunk("do");
1940 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1941 Builder.AddPlaceholderChunk("statements");
1942 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1943 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1944 Builder.AddTextChunk("while");
1945 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
1946 Builder.AddPlaceholderChunk("expression");
1947 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1948 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001949
Douglas Gregorf64acca2010-05-25 21:41:55 +00001950 // for ( for-init-statement ; condition ; expression ) { statements }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001951 Builder.AddTypedTextChunk("for");
1952 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
David Blaikiebbafb8a2012-03-11 07:00:24 +00001953 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001954 Builder.AddPlaceholderChunk("init-statement");
Douglas Gregorf64acca2010-05-25 21:41:55 +00001955 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001956 Builder.AddPlaceholderChunk("init-expression");
1957 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1958 Builder.AddPlaceholderChunk("condition");
1959 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
1960 Builder.AddPlaceholderChunk("inc-expression");
1961 Builder.AddChunk(CodeCompletionString::CK_RightParen);
1962 Builder.AddChunk(CodeCompletionString::CK_LeftBrace);
1963 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1964 Builder.AddPlaceholderChunk("statements");
1965 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace);
1966 Builder.AddChunk(CodeCompletionString::CK_RightBrace);
1967 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorf64acca2010-05-25 21:41:55 +00001968 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001969
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001970 if (S->getContinueParent()) {
1971 // continue ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001972 Builder.AddTypedTextChunk("continue");
1973 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001974 }
1975
1976 if (S->getBreakParent()) {
1977 // break ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001978 Builder.AddTypedTextChunk("break");
1979 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001980 }
1981
1982 // "return expression ;" or "return ;", depending on whether we
1983 // know the function is void or not.
1984 bool isVoid = false;
Fangrui Song050229d2018-11-24 00:14:31 +00001985 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001986 isVoid = Function->getReturnType()->isVoidType();
Fangrui Song050229d2018-11-24 00:14:31 +00001987 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext))
Alp Toker314cc812014-01-25 16:55:45 +00001988 isVoid = Method->getReturnType()->isVoidType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00001989 else if (SemaRef.getCurBlock() &&
Douglas Gregor9a28e842010-03-01 23:15:13 +00001990 !SemaRef.getCurBlock()->ReturnType.isNull())
1991 isVoid = SemaRef.getCurBlock()->ReturnType->isVoidType();
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001992 Builder.AddTypedTextChunk("return");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001993 if (!isVoid) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001994 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
1995 Builder.AddPlaceholderChunk("expression");
Douglas Gregor44272ca2010-02-18 04:06:48 +00001996 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00001997 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00001998
Douglas Gregorf4c33342010-05-28 00:22:41 +00001999 // goto identifier ;
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002000 Builder.AddTypedTextChunk("goto");
2001 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2002 Builder.AddPlaceholderChunk("label");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002003 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002004
Douglas Gregorf4c33342010-05-28 00:22:41 +00002005 // Using directives
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002006 Builder.AddTypedTextChunk("using");
2007 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2008 Builder.AddTextChunk("namespace");
2009 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2010 Builder.AddPlaceholderChunk("identifier");
2011 Results.AddResult(Result(Builder.TakeString()));
Alex Lorenz8f4d3992017-02-13 23:19:40 +00002012
2013 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts());
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002014 }
Fangrui Song050229d2018-11-24 00:14:31 +00002015 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002016
2017 // Fall through (for statement expressions).
John McCallfaf5fb42010-08-26 23:41:50 +00002018 case Sema::PCC_ForInit:
2019 case Sema::PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002020 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002021 // Fall through: conditions and statements can have expressions.
Galina Kistanova33399112017-06-03 06:35:06 +00002022 LLVM_FALLTHROUGH;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002023
Douglas Gregor5e35d592010-09-14 23:59:36 +00002024 case Sema::PCC_ParenthesizedExpression:
David Blaikiebbafb8a2012-03-11 07:00:24 +00002025 if (SemaRef.getLangOpts().ObjCAutoRefCount &&
John McCall31168b02011-06-15 23:02:42 +00002026 CCC == Sema::PCC_ParenthesizedExpression) {
2027 // (__bridge <type>)<expression>
2028 Builder.AddTypedTextChunk("__bridge");
2029 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2030 Builder.AddPlaceholderChunk("type");
2031 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2032 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002033 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002034
2035 // (__bridge_transfer <Objective-C type>)<expression>
2036 Builder.AddTypedTextChunk("__bridge_transfer");
2037 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2038 Builder.AddPlaceholderChunk("Objective-C type");
2039 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2040 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002041 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002042
2043 // (__bridge_retained <CF type>)<expression>
2044 Builder.AddTypedTextChunk("__bridge_retained");
2045 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2046 Builder.AddPlaceholderChunk("CF type");
2047 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2048 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002049 Results.AddResult(Result(Builder.TakeString()));
John McCall31168b02011-06-15 23:02:42 +00002050 }
2051 // Fall through
Galina Kistanova33399112017-06-03 06:35:06 +00002052 LLVM_FALLTHROUGH;
John McCall31168b02011-06-15 23:02:42 +00002053
John McCallfaf5fb42010-08-26 23:41:50 +00002054 case Sema::PCC_Expression: {
David Blaikiebbafb8a2012-03-11 07:00:24 +00002055 if (SemaRef.getLangOpts().CPlusPlus) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002056 // 'this', if we're in a non-static member function.
Douglas Gregord8c61782012-02-15 15:34:24 +00002057 addThisCompletion(SemaRef, Results);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002058
Douglas Gregore5c79d52011-10-18 21:20:17 +00002059 // true
2060 Builder.AddResultTypeChunk("bool");
2061 Builder.AddTypedTextChunk("true");
2062 Results.AddResult(Result(Builder.TakeString()));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002063
Douglas Gregore5c79d52011-10-18 21:20:17 +00002064 // false
2065 Builder.AddResultTypeChunk("bool");
2066 Builder.AddTypedTextChunk("false");
2067 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002068
David Blaikiebbafb8a2012-03-11 07:00:24 +00002069 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002070 // dynamic_cast < type-id > ( expression )
2071 Builder.AddTypedTextChunk("dynamic_cast");
2072 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2073 Builder.AddPlaceholderChunk("type");
2074 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2075 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2076 Builder.AddPlaceholderChunk("expression");
2077 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002078 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002079 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002080
Douglas Gregorf4c33342010-05-28 00:22:41 +00002081 // static_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002082 Builder.AddTypedTextChunk("static_cast");
2083 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2084 Builder.AddPlaceholderChunk("type");
2085 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2086 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2087 Builder.AddPlaceholderChunk("expression");
2088 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002089 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002090
Douglas Gregorf4c33342010-05-28 00:22:41 +00002091 // reinterpret_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002092 Builder.AddTypedTextChunk("reinterpret_cast");
2093 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2094 Builder.AddPlaceholderChunk("type");
2095 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2096 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2097 Builder.AddPlaceholderChunk("expression");
2098 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002099 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002100
Douglas Gregorf4c33342010-05-28 00:22:41 +00002101 // const_cast < type-id > ( expression )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002102 Builder.AddTypedTextChunk("const_cast");
2103 Builder.AddChunk(CodeCompletionString::CK_LeftAngle);
2104 Builder.AddPlaceholderChunk("type");
2105 Builder.AddChunk(CodeCompletionString::CK_RightAngle);
2106 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2107 Builder.AddPlaceholderChunk("expression");
2108 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002109 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002110
David Blaikiebbafb8a2012-03-11 07:00:24 +00002111 if (SemaRef.getLangOpts().RTTI) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002112 // typeid ( expression-or-type )
Douglas Gregore5c79d52011-10-18 21:20:17 +00002113 Builder.AddResultTypeChunk("std::type_info");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002114 Builder.AddTypedTextChunk("typeid");
2115 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2116 Builder.AddPlaceholderChunk("expression-or-type");
2117 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002118 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregorc05f6572011-04-12 02:47:21 +00002119 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002120
Douglas Gregorf4c33342010-05-28 00:22:41 +00002121 // new T ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002122 Builder.AddTypedTextChunk("new");
2123 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2124 Builder.AddPlaceholderChunk("type");
2125 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2126 Builder.AddPlaceholderChunk("expressions");
2127 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002128 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002129
Douglas Gregorf4c33342010-05-28 00:22:41 +00002130 // new T [ ] ( ... )
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002131 Builder.AddTypedTextChunk("new");
2132 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2133 Builder.AddPlaceholderChunk("type");
2134 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2135 Builder.AddPlaceholderChunk("size");
2136 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2137 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2138 Builder.AddPlaceholderChunk("expressions");
2139 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002140 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002141
Douglas Gregorf4c33342010-05-28 00:22:41 +00002142 // delete expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002143 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002144 Builder.AddTypedTextChunk("delete");
2145 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2146 Builder.AddPlaceholderChunk("expression");
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002147 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002148
Douglas Gregorf4c33342010-05-28 00:22:41 +00002149 // delete [] expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002150 Builder.AddResultTypeChunk("void");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002151 Builder.AddTypedTextChunk("delete");
2152 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2153 Builder.AddChunk(CodeCompletionString::CK_LeftBracket);
2154 Builder.AddChunk(CodeCompletionString::CK_RightBracket);
2155 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2156 Builder.AddPlaceholderChunk("expression");
2157 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002158
David Blaikiebbafb8a2012-03-11 07:00:24 +00002159 if (SemaRef.getLangOpts().CXXExceptions) {
Douglas Gregorc05f6572011-04-12 02:47:21 +00002160 // throw expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002161 Builder.AddResultTypeChunk("void");
Douglas Gregorc05f6572011-04-12 02:47:21 +00002162 Builder.AddTypedTextChunk("throw");
2163 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
2164 Builder.AddPlaceholderChunk("expression");
2165 Results.AddResult(Result(Builder.TakeString()));
2166 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002167
Douglas Gregora2db7932010-05-26 22:00:08 +00002168 // FIXME: Rethrow?
Douglas Gregor4205fef2011-10-18 16:29:03 +00002169
Richard Smith2bf7fdb2013-01-02 11:42:31 +00002170 if (SemaRef.getLangOpts().CPlusPlus11) {
Douglas Gregor4205fef2011-10-18 16:29:03 +00002171 // nullptr
Douglas Gregore5c79d52011-10-18 21:20:17 +00002172 Builder.AddResultTypeChunk("std::nullptr_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002173 Builder.AddTypedTextChunk("nullptr");
2174 Results.AddResult(Result(Builder.TakeString()));
2175
2176 // alignof
Douglas Gregore5c79d52011-10-18 21:20:17 +00002177 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002178 Builder.AddTypedTextChunk("alignof");
2179 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2180 Builder.AddPlaceholderChunk("type");
2181 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2182 Results.AddResult(Result(Builder.TakeString()));
2183
2184 // noexcept
Douglas Gregore5c79d52011-10-18 21:20:17 +00002185 Builder.AddResultTypeChunk("bool");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002186 Builder.AddTypedTextChunk("noexcept");
2187 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2188 Builder.AddPlaceholderChunk("expression");
2189 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2190 Results.AddResult(Result(Builder.TakeString()));
2191
2192 // sizeof... expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002193 Builder.AddResultTypeChunk("size_t");
Douglas Gregor4205fef2011-10-18 16:29:03 +00002194 Builder.AddTypedTextChunk("sizeof...");
2195 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2196 Builder.AddPlaceholderChunk("parameter-pack");
2197 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2198 Results.AddResult(Result(Builder.TakeString()));
2199 }
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002200 }
2201
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002202 if (SemaRef.getLangOpts().ObjC) {
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002203 // Add "super", if we're in an Objective-C class with a superclass.
Ted Kremenek305a0a72010-05-31 21:43:10 +00002204 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) {
2205 // The interface can be NULL.
2206 if (ObjCInterfaceDecl *ID = Method->getClassInterface())
Douglas Gregore5c79d52011-10-18 21:20:17 +00002207 if (ID->getSuperClass()) {
2208 std::string SuperType;
2209 SuperType = ID->getSuperClass()->getNameAsString();
2210 if (Method->isInstanceMethod())
2211 SuperType += " *";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002212
Douglas Gregore5c79d52011-10-18 21:20:17 +00002213 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType));
2214 Builder.AddTypedTextChunk("super");
2215 Results.AddResult(Result(Builder.TakeString()));
2216 }
Ted Kremenek305a0a72010-05-31 21:43:10 +00002217 }
2218
Douglas Gregorf98e6a22010-01-13 23:51:12 +00002219 AddObjCExpressionResults(Results, true);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002220 }
2221
Jordan Rose58d54722012-06-30 21:33:57 +00002222 if (SemaRef.getLangOpts().C11) {
2223 // _Alignof
2224 Builder.AddResultTypeChunk("size_t");
Richard Smith20e883e2015-04-29 23:20:19 +00002225 if (SemaRef.PP.isMacroDefined("alignof"))
Jordan Rose58d54722012-06-30 21:33:57 +00002226 Builder.AddTypedTextChunk("alignof");
2227 else
2228 Builder.AddTypedTextChunk("_Alignof");
2229 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2230 Builder.AddPlaceholderChunk("type");
2231 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2232 Results.AddResult(Result(Builder.TakeString()));
2233 }
2234
Douglas Gregorf4c33342010-05-28 00:22:41 +00002235 // sizeof expression
Douglas Gregore5c79d52011-10-18 21:20:17 +00002236 Builder.AddResultTypeChunk("size_t");
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002237 Builder.AddTypedTextChunk("sizeof");
2238 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
2239 Builder.AddPlaceholderChunk("expression-or-type");
2240 Builder.AddChunk(CodeCompletionString::CK_RightParen);
2241 Results.AddResult(Result(Builder.TakeString()));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002242 break;
2243 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002244
John McCallfaf5fb42010-08-26 23:41:50 +00002245 case Sema::PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00002246 case Sema::PCC_LocalDeclarationSpecifiers:
Douglas Gregor99fa2642010-08-24 01:06:58 +00002247 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002248 }
2249
David Blaikiebbafb8a2012-03-11 07:00:24 +00002250 if (WantTypesInContext(CCC, SemaRef.getLangOpts()))
2251 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002252
David Blaikiebbafb8a2012-03-11 07:00:24 +00002253 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type)
Douglas Gregor78a21012010-01-14 16:01:26 +00002254 Results.AddResult(Result("operator"));
Douglas Gregor504a6ae2010-01-10 23:08:15 +00002255}
2256
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002257/// If the given declaration has an associated type, add it as a result
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002258/// type chunk.
2259static void AddResultTypeChunk(ASTContext &Context,
Douglas Gregor75acd922011-09-27 23:30:47 +00002260 const PrintingPolicy &Policy,
Fangrui Song050229d2018-11-24 00:14:31 +00002261 const NamedDecl *ND, QualType BaseType,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002262 CodeCompletionBuilder &Result) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002263 if (!ND)
2264 return;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002265
2266 // Skip constructors and conversion functions, which have their return types
2267 // built into their names.
Sam McCall63c59722018-01-22 20:44:47 +00002268 if (isConstructor(ND) || isa<CXXConversionDecl>(ND))
Douglas Gregor0212fd72010-09-21 16:06:22 +00002269 return;
2270
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002271 // Determine the type of the declaration (if it has a type).
Alp Tokera2794f92014-01-22 07:29:52 +00002272 QualType T;
2273 if (const FunctionDecl *Function = ND->getAsFunction())
Alp Toker314cc812014-01-25 16:55:45 +00002274 T = Function->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002275 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002276 if (!BaseType.isNull())
2277 T = Method->getSendResultType(BaseType);
2278 else
2279 T = Method->getReturnType();
Fangrui Song050229d2018-11-24 00:14:31 +00002280 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002281 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext()));
Ilya Biryukovb5da91c2017-11-08 10:39:09 +00002282 T = clang::TypeName::getFullyQualifiedType(T, Context);
2283 } else if (isa<UnresolvedUsingValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002284 /* Do nothing: ignore unresolved using declarations*/
Fangrui Song050229d2018-11-24 00:14:31 +00002285 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002286 if (!BaseType.isNull())
2287 T = Ivar->getUsageType(BaseType);
2288 else
2289 T = Ivar->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002290 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) {
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002291 T = Value->getType();
Fangrui Song050229d2018-11-24 00:14:31 +00002292 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002293 if (!BaseType.isNull())
2294 T = Property->getUsageType(BaseType);
2295 else
2296 T = Property->getType();
2297 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002298
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002299 if (T.isNull() || Context.hasSameType(T, Context.DependentTy))
2300 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002301
Fangrui Song050229d2018-11-24 00:14:31 +00002302 Result.AddResultTypeChunk(
2303 GetCompletionTypeString(T, Context, Policy, Result.getAllocator()));
Douglas Gregorb3fa9192009-12-18 18:53:37 +00002304}
2305
Richard Smith20e883e2015-04-29 23:20:19 +00002306static void MaybeAddSentinel(Preprocessor &PP,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002307 const NamedDecl *FunctionOrMethod,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002308 CodeCompletionBuilder &Result) {
Douglas Gregordbb71db2010-08-23 23:51:41 +00002309 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>())
2310 if (Sentinel->getSentinel() == 0) {
Erik Pilkingtonfa983902018-10-30 20:31:30 +00002311 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002312 Result.AddTextChunk(", nil");
Richard Smith20e883e2015-04-29 23:20:19 +00002313 else if (PP.isMacroDefined("NULL"))
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002314 Result.AddTextChunk(", NULL");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002315 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002316 Result.AddTextChunk(", (void*)0");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002317 }
2318}
2319
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002320static std::string formatObjCParamQualifiers(unsigned ObjCQuals,
Douglas Gregor86b42682015-06-19 18:27:52 +00002321 QualType &Type) {
Douglas Gregor8f08d742011-07-30 07:55:26 +00002322 std::string Result;
2323 if (ObjCQuals & Decl::OBJC_TQ_In)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002324 Result += "in ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002325 else if (ObjCQuals & Decl::OBJC_TQ_Inout)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002326 Result += "inout ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002327 else if (ObjCQuals & Decl::OBJC_TQ_Out)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002328 Result += "out ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002329 if (ObjCQuals & Decl::OBJC_TQ_Bycopy)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002330 Result += "bycopy ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002331 else if (ObjCQuals & Decl::OBJC_TQ_Byref)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002332 Result += "byref ";
Douglas Gregor8f08d742011-07-30 07:55:26 +00002333 if (ObjCQuals & Decl::OBJC_TQ_Oneway)
Douglas Gregor407d1f92011-11-09 02:13:45 +00002334 Result += "oneway ";
Douglas Gregor86b42682015-06-19 18:27:52 +00002335 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) {
2336 if (auto nullability = AttributedType::stripOuterNullability(Type)) {
2337 switch (*nullability) {
2338 case NullabilityKind::NonNull:
2339 Result += "nonnull ";
2340 break;
2341
2342 case NullabilityKind::Nullable:
2343 Result += "nullable ";
2344 break;
2345
2346 case NullabilityKind::Unspecified:
2347 Result += "null_unspecified ";
2348 break;
2349 }
2350 }
2351 }
Douglas Gregor8f08d742011-07-30 07:55:26 +00002352 return Result;
2353}
2354
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002355/// Tries to find the most appropriate type location for an Objective-C
Alex Lorenza1951202016-10-18 10:35:27 +00002356/// block placeholder.
2357///
2358/// This function ignores things like typedefs and qualifiers in order to
2359/// present the most relevant and accurate block placeholders in code completion
2360/// results.
2361static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo,
2362 FunctionTypeLoc &Block,
2363 FunctionProtoTypeLoc &BlockProto,
2364 bool SuppressBlock = false) {
2365 if (!TSInfo)
2366 return;
2367 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
2368 while (true) {
2369 // Look through typedefs.
2370 if (!SuppressBlock) {
2371 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) {
2372 if (TypeSourceInfo *InnerTSInfo =
2373 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) {
2374 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc();
2375 continue;
2376 }
2377 }
2378
2379 // Look through qualified types
2380 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) {
2381 TL = QualifiedTL.getUnqualifiedLoc();
2382 continue;
2383 }
2384
2385 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) {
2386 TL = AttrTL.getModifiedLoc();
2387 continue;
2388 }
2389 }
2390
2391 // Try to get the function prototype behind the block pointer type,
2392 // then we're done.
2393 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) {
2394 TL = BlockPtr.getPointeeLoc().IgnoreParens();
2395 Block = TL.getAs<FunctionTypeLoc>();
2396 BlockProto = TL.getAs<FunctionProtoTypeLoc>();
2397 }
2398 break;
2399 }
2400}
2401
Alex Lorenz920ae142016-10-18 10:38:58 +00002402static std::string
2403formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2404 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002405 bool SuppressBlockName = false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002406 bool SuppressBlock = false,
2407 Optional<ArrayRef<QualType>> ObjCSubsts = None);
2408
Fangrui Song050229d2018-11-24 00:14:31 +00002409static std::string
2410FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param,
2411 bool SuppressName = false, bool SuppressBlock = false,
2412 Optional<ArrayRef<QualType>> ObjCSubsts = None) {
Douglas Gregore90dd002010-08-24 16:15:59 +00002413 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext());
2414 if (Param->getType()->isDependentType() ||
2415 !Param->getType()->isBlockPointerType()) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002416 // The argument for a dependent or non-block parameter is a placeholder
Douglas Gregore90dd002010-08-24 16:15:59 +00002417 // containing that parameter's type.
2418 std::string Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002419
Douglas Gregor981a0c42010-08-29 19:47:46 +00002420 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002421 Result = Param->getIdentifier()->getName();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002422
Douglas Gregor86b42682015-06-19 18:27:52 +00002423 QualType Type = Param->getType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002424 if (ObjCSubsts)
2425 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts,
2426 ObjCSubstitutionContext::Parameter);
Douglas Gregore90dd002010-08-24 16:15:59 +00002427 if (ObjCMethodParam) {
Fangrui Song050229d2018-11-24 00:14:31 +00002428 Result =
2429 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
Douglas Gregor86b42682015-06-19 18:27:52 +00002430 Result += Type.getAsString(Policy) + ")";
Douglas Gregor981a0c42010-08-29 19:47:46 +00002431 if (Param->getIdentifier() && !SuppressName)
Douglas Gregore90dd002010-08-24 16:15:59 +00002432 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002433 } else {
2434 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002435 }
2436 return Result;
2437 }
Alex Lorenza1951202016-10-18 10:35:27 +00002438
Douglas Gregore90dd002010-08-24 16:15:59 +00002439 // The argument for a block pointer parameter is a block literal with
2440 // the appropriate type.
David Blaikie6adc78e2013-02-18 22:06:02 +00002441 FunctionTypeLoc Block;
2442 FunctionProtoTypeLoc BlockProto;
Alex Lorenza1951202016-10-18 10:35:27 +00002443 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto,
2444 SuppressBlock);
Alex Lorenz6bf4a582017-03-13 15:43:42 +00002445 // Try to retrieve the block type information from the property if this is a
2446 // parameter in a setter.
2447 if (!Block && ObjCMethodParam &&
2448 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) {
2449 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext())
2450 ->findPropertyDecl(/*CheckOverrides=*/false))
2451 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto,
2452 SuppressBlock);
2453 }
Douglas Gregore90dd002010-08-24 16:15:59 +00002454
2455 if (!Block) {
2456 // We were unable to find a FunctionProtoTypeLoc with parameter names
2457 // for the block; just use the parameter type as a placeholder.
2458 std::string Result;
Douglas Gregord793e7c2011-10-18 04:23:19 +00002459 if (!ObjCMethodParam && Param->getIdentifier())
2460 Result = Param->getIdentifier()->getName();
2461
Douglas Gregor86b42682015-06-19 18:27:52 +00002462 QualType Type = Param->getType().getUnqualifiedType();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002463
Douglas Gregore90dd002010-08-24 16:15:59 +00002464 if (ObjCMethodParam) {
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002465 Result = Type.getAsString(Policy);
2466 std::string Quals =
2467 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type);
2468 if (!Quals.empty())
2469 Result = "(" + Quals + " " + Result + ")";
2470 if (Result.back() != ')')
2471 Result += " ";
Douglas Gregore90dd002010-08-24 16:15:59 +00002472 if (Param->getIdentifier())
2473 Result += Param->getIdentifier()->getName();
Douglas Gregor86b42682015-06-19 18:27:52 +00002474 } else {
2475 Type.getAsStringInternal(Result, Policy);
Douglas Gregore90dd002010-08-24 16:15:59 +00002476 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002477
Douglas Gregore90dd002010-08-24 16:15:59 +00002478 return Result;
2479 }
Alex Lorenz01bcfc12016-11-23 16:28:34 +00002480
Douglas Gregore90dd002010-08-24 16:15:59 +00002481 // We have the function prototype behind the block pointer type, as it was
2482 // written in the source.
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002483 return formatBlockPlaceholder(Policy, Param, Block, BlockProto,
2484 /*SuppressBlockName=*/false, SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002485 ObjCSubsts);
2486}
2487
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002488/// Returns a placeholder string that corresponds to an Objective-C block
Alex Lorenz920ae142016-10-18 10:38:58 +00002489/// declaration.
2490///
2491/// \param BlockDecl A declaration with an Objective-C block type.
2492///
2493/// \param Block The most relevant type location for that block type.
2494///
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002495/// \param SuppressBlockName Determines whether or not the name of the block
Alex Lorenz920ae142016-10-18 10:38:58 +00002496/// declaration is included in the resulting string.
2497static std::string
2498formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl,
2499 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto,
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002500 bool SuppressBlockName, bool SuppressBlock,
Alex Lorenz920ae142016-10-18 10:38:58 +00002501 Optional<ArrayRef<QualType>> ObjCSubsts) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002502 std::string Result;
Alp Toker314cc812014-01-25 16:55:45 +00002503 QualType ResultType = Block.getTypePtr()->getReturnType();
Douglas Gregorc3425b12015-07-07 06:20:19 +00002504 if (ObjCSubsts)
Alex Lorenz920ae142016-10-18 10:38:58 +00002505 ResultType =
2506 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts,
2507 ObjCSubstitutionContext::Result);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002508 if (!ResultType->isVoidType() || SuppressBlock)
John McCall31168b02011-06-15 23:02:42 +00002509 ResultType.getAsStringInternal(Result, Policy);
Douglas Gregord793e7c2011-10-18 04:23:19 +00002510
2511 // Format the parameter list.
2512 std::string Params;
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002513 if (!BlockProto || Block.getNumParams() == 0) {
David Blaikie6adc78e2013-02-18 22:06:02 +00002514 if (BlockProto && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002515 Params = "(...)";
Douglas Gregoraf25cfa2010-10-02 23:49:58 +00002516 else
Douglas Gregord793e7c2011-10-18 04:23:19 +00002517 Params = "(void)";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002518 } else {
Douglas Gregord793e7c2011-10-18 04:23:19 +00002519 Params += "(";
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002520 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) {
Douglas Gregor67da50e2010-09-08 22:47:51 +00002521 if (I)
Douglas Gregord793e7c2011-10-18 04:23:19 +00002522 Params += ", ";
Richard Smith20e883e2015-04-29 23:20:19 +00002523 Params += FormatFunctionParameter(Policy, Block.getParam(I),
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002524 /*SuppressName=*/false,
Alex Lorenz920ae142016-10-18 10:38:58 +00002525 /*SuppressBlock=*/true, ObjCSubsts);
Alp Tokerb3fd5cf2014-01-21 00:32:38 +00002526
David Blaikie6adc78e2013-02-18 22:06:02 +00002527 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic())
Douglas Gregord793e7c2011-10-18 04:23:19 +00002528 Params += ", ...";
Douglas Gregor67da50e2010-09-08 22:47:51 +00002529 }
Douglas Gregord793e7c2011-10-18 04:23:19 +00002530 Params += ")";
Douglas Gregor400f5972010-08-31 05:13:43 +00002531 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002532
Douglas Gregord793e7c2011-10-18 04:23:19 +00002533 if (SuppressBlock) {
2534 // Format as a parameter.
2535 Result = Result + " (^";
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002536 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002537 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002538 Result += ")";
2539 Result += Params;
2540 } else {
2541 // Format as a block literal argument.
2542 Result = '^' + Result;
2543 Result += Params;
Alex Lorenz920ae142016-10-18 10:38:58 +00002544
Alex Lorenzf0b4e5d2016-10-18 10:55:01 +00002545 if (!SuppressBlockName && BlockDecl->getIdentifier())
Alex Lorenz920ae142016-10-18 10:38:58 +00002546 Result += BlockDecl->getIdentifier()->getName();
Douglas Gregord793e7c2011-10-18 04:23:19 +00002547 }
Alex Lorenz920ae142016-10-18 10:38:58 +00002548
Douglas Gregore90dd002010-08-24 16:15:59 +00002549 return Result;
2550}
2551
Erik Verbruggen11338c52017-07-19 10:45:40 +00002552static std::string GetDefaultValueString(const ParmVarDecl *Param,
2553 const SourceManager &SM,
2554 const LangOptions &LangOpts) {
Ilya Biryukovb6d1ec82017-07-21 09:24:00 +00002555 const SourceRange SrcRange = Param->getDefaultArgRange();
Erik Verbruggen11338c52017-07-19 10:45:40 +00002556 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange);
2557 bool Invalid = CharSrcRange.isInvalid();
2558 if (Invalid)
2559 return "";
Fangrui Song050229d2018-11-24 00:14:31 +00002560 StringRef srcText =
2561 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002562 if (Invalid)
2563 return "";
2564
2565 if (srcText.empty() || srcText == "=") {
2566 // Lexer can't determine the value.
Fangrui Song050229d2018-11-24 00:14:31 +00002567 // This happens if the code is incorrect (for example class is forward
2568 // declared).
Erik Verbruggen11338c52017-07-19 10:45:40 +00002569 return "";
2570 }
Erik Verbruggen797980e2017-07-19 11:15:36 +00002571 std::string DefValue(srcText.str());
Erik Verbruggen11338c52017-07-19 10:45:40 +00002572 // FIXME: remove this check if the Lexer::getSourceText value is fixed and
2573 // this value always has (or always does not have) '=' in front of it
2574 if (DefValue.at(0) != '=') {
2575 // If we don't have '=' in front of value.
Fangrui Song050229d2018-11-24 00:14:31 +00002576 // Lexer returns built-in types values without '=' and user-defined types
2577 // values with it.
Erik Verbruggen11338c52017-07-19 10:45:40 +00002578 return " = " + DefValue;
2579 }
2580 return " " + DefValue;
2581}
2582
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002583/// Add function parameter chunks to the given code completion string.
Richard Smith20e883e2015-04-29 23:20:19 +00002584static void AddFunctionParameterChunks(Preprocessor &PP,
Douglas Gregor75acd922011-09-27 23:30:47 +00002585 const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002586 const FunctionDecl *Function,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002587 CodeCompletionBuilder &Result,
2588 unsigned Start = 0,
2589 bool InOptional = false) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002590 bool FirstParameter = true;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002591
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002592 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002593 const ParmVarDecl *Param = Function->getParamDecl(P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002594
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002595 if (Param->hasDefaultArg() && !InOptional) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002596 // When we see an optional default argument, put that argument and
2597 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002598 CodeCompletionBuilder Opt(Result.getAllocator(),
2599 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002600 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002601 Opt.AddChunk(CodeCompletionString::CK_Comma);
Richard Smith20e883e2015-04-29 23:20:19 +00002602 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002603 Result.AddOptionalChunk(Opt.TakeString());
2604 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002605 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002606
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002607 if (FirstParameter)
2608 FirstParameter = false;
2609 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002610 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002611
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002612 InOptional = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002613
Douglas Gregor3545ff42009-09-21 16:56:56 +00002614 // Format the placeholder string.
Richard Smith20e883e2015-04-29 23:20:19 +00002615 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param);
Erik Verbruggen11338c52017-07-19 10:45:40 +00002616 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00002617 PlaceholderStr +=
2618 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts());
Richard Smith20e883e2015-04-29 23:20:19 +00002619
Douglas Gregor400f5972010-08-31 05:13:43 +00002620 if (Function->isVariadic() && P == N - 1)
2621 PlaceholderStr += ", ...";
2622
Douglas Gregor3545ff42009-09-21 16:56:56 +00002623 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002624 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002625 Result.getAllocator().CopyString(PlaceholderStr));
Douglas Gregor3545ff42009-09-21 16:56:56 +00002626 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002627
Fangrui Song050229d2018-11-24 00:14:31 +00002628 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>())
Douglas Gregordbb71db2010-08-23 23:51:41 +00002629 if (Proto->isVariadic()) {
Alp Toker9cacbab2014-01-20 20:26:09 +00002630 if (Proto->getNumParams() == 0)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002631 Result.AddPlaceholderChunk("...");
Douglas Gregordbb71db2010-08-23 23:51:41 +00002632
Richard Smith20e883e2015-04-29 23:20:19 +00002633 MaybeAddSentinel(PP, Function, Result);
Douglas Gregordbb71db2010-08-23 23:51:41 +00002634 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002635}
2636
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002637/// Add template parameter chunks to the given code completion string.
Fangrui Song050229d2018-11-24 00:14:31 +00002638static void AddTemplateParameterChunks(
2639 ASTContext &Context, const PrintingPolicy &Policy,
2640 const TemplateDecl *Template, CodeCompletionBuilder &Result,
2641 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002642 bool FirstParameter = true;
Richard Smith6eece292015-01-15 02:27:20 +00002643
2644 // Prefer to take the template parameter names from the first declaration of
2645 // the template.
2646 Template = cast<TemplateDecl>(Template->getCanonicalDecl());
2647
Douglas Gregor3545ff42009-09-21 16:56:56 +00002648 TemplateParameterList *Params = Template->getTemplateParameters();
2649 TemplateParameterList::iterator PEnd = Params->end();
2650 if (MaxParameters)
2651 PEnd = Params->begin() + MaxParameters;
Fangrui Song050229d2018-11-24 00:14:31 +00002652 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd;
2653 ++P) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002654 bool HasDefaultArg = false;
2655 std::string PlaceholderStr;
2656 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) {
2657 if (TTP->wasDeclaredWithTypename())
2658 PlaceholderStr = "typename";
2659 else
2660 PlaceholderStr = "class";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002661
Douglas Gregor3545ff42009-09-21 16:56:56 +00002662 if (TTP->getIdentifier()) {
2663 PlaceholderStr += ' ';
2664 PlaceholderStr += TTP->getIdentifier()->getName();
2665 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002666
Douglas Gregor3545ff42009-09-21 16:56:56 +00002667 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00002668 } else if (NonTypeTemplateParmDecl *NTTP =
2669 dyn_cast<NonTypeTemplateParmDecl>(*P)) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002670 if (NTTP->getIdentifier())
2671 PlaceholderStr = NTTP->getIdentifier()->getName();
John McCall31168b02011-06-15 23:02:42 +00002672 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00002673 HasDefaultArg = NTTP->hasDefaultArgument();
2674 } else {
2675 assert(isa<TemplateTemplateParmDecl>(*P));
2676 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002677
Douglas Gregor3545ff42009-09-21 16:56:56 +00002678 // Since putting the template argument list into the placeholder would
2679 // be very, very long, we just use an abbreviation.
2680 PlaceholderStr = "template<...> class";
2681 if (TTP->getIdentifier()) {
2682 PlaceholderStr += ' ';
2683 PlaceholderStr += TTP->getIdentifier()->getName();
2684 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002685
Douglas Gregor3545ff42009-09-21 16:56:56 +00002686 HasDefaultArg = TTP->hasDefaultArgument();
2687 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002688
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002689 if (HasDefaultArg && !InDefaultArg) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00002690 // When we see an optional default argument, put that argument and
2691 // the remaining default arguments into a new, optional string.
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002692 CodeCompletionBuilder Opt(Result.getAllocator(),
2693 Result.getCodeCompletionTUInfo());
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002694 if (!FirstParameter)
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002695 Opt.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregor75acd922011-09-27 23:30:47 +00002696 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters,
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002697 P - Params->begin(), true);
2698 Result.AddOptionalChunk(Opt.TakeString());
2699 break;
Douglas Gregor3545ff42009-09-21 16:56:56 +00002700 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002701
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002702 InDefaultArg = false;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002703
Douglas Gregor3545ff42009-09-21 16:56:56 +00002704 if (FirstParameter)
2705 FirstParameter = false;
2706 else
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002707 Result.AddChunk(CodeCompletionString::CK_Comma);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002708
Douglas Gregor3545ff42009-09-21 16:56:56 +00002709 // Add the placeholder string.
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002710 Result.AddPlaceholderChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002711 Result.getAllocator().CopyString(PlaceholderStr));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002712 }
Douglas Gregor3545ff42009-09-21 16:56:56 +00002713}
2714
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002715/// Add a qualifier to the given code-completion string, if the
Douglas Gregorf2510672009-09-21 19:57:38 +00002716/// provided nested-name-specifier is non-NULL.
Fangrui Song050229d2018-11-24 00:14:31 +00002717static void AddQualifierToCompletionString(CodeCompletionBuilder &Result,
2718 NestedNameSpecifier *Qualifier,
2719 bool QualifierIsInformative,
2720 ASTContext &Context,
2721 const PrintingPolicy &Policy) {
Douglas Gregorf2510672009-09-21 19:57:38 +00002722 if (!Qualifier)
2723 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002724
Douglas Gregorf2510672009-09-21 19:57:38 +00002725 std::string PrintedNNS;
2726 {
2727 llvm::raw_string_ostream OS(PrintedNNS);
Douglas Gregor75acd922011-09-27 23:30:47 +00002728 Qualifier->print(OS, Policy);
Douglas Gregorf2510672009-09-21 19:57:38 +00002729 }
Douglas Gregor5bf52692009-09-22 23:15:58 +00002730 if (QualifierIsInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002731 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregor5bf52692009-09-22 23:15:58 +00002732 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002733 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS));
Douglas Gregorf2510672009-09-21 19:57:38 +00002734}
2735
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002736static void
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002737AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002738 const FunctionDecl *Function) {
Fangrui Song050229d2018-11-24 00:14:31 +00002739 const auto *Proto = Function->getType()->getAs<FunctionProtoType>();
Douglas Gregor0f622362009-12-11 18:44:16 +00002740 if (!Proto || !Proto->getTypeQuals())
2741 return;
2742
Douglas Gregor304f9b02011-02-01 21:15:40 +00002743 // FIXME: Add ref-qualifier!
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002744
Douglas Gregor304f9b02011-02-01 21:15:40 +00002745 // Handle single qualifiers without copying
Mikael Nilsson90646732018-12-12 15:06:16 +00002746 if (Proto->getTypeQuals() == Qualifiers::Const) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002747 Result.AddInformativeChunk(" const");
2748 return;
2749 }
2750
Mikael Nilsson90646732018-12-12 15:06:16 +00002751 if (Proto->getTypeQuals() == Qualifiers::Volatile) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002752 Result.AddInformativeChunk(" volatile");
2753 return;
2754 }
2755
Mikael Nilsson90646732018-12-12 15:06:16 +00002756 if (Proto->getTypeQuals() == Qualifiers::Restrict) {
Douglas Gregor304f9b02011-02-01 21:15:40 +00002757 Result.AddInformativeChunk(" restrict");
2758 return;
2759 }
2760
2761 // Handle multiple qualifiers.
Douglas Gregor0f622362009-12-11 18:44:16 +00002762 std::string QualsStr;
David Blaikief5697e52012-08-10 00:55:35 +00002763 if (Proto->isConst())
Douglas Gregor0f622362009-12-11 18:44:16 +00002764 QualsStr += " const";
David Blaikief5697e52012-08-10 00:55:35 +00002765 if (Proto->isVolatile())
Douglas Gregor0f622362009-12-11 18:44:16 +00002766 QualsStr += " volatile";
David Blaikief5697e52012-08-10 00:55:35 +00002767 if (Proto->isRestrict())
Douglas Gregor0f622362009-12-11 18:44:16 +00002768 QualsStr += " restrict";
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002769 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr));
Douglas Gregor0f622362009-12-11 18:44:16 +00002770}
2771
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002772/// Add the name of the given declaration
Douglas Gregor75acd922011-09-27 23:30:47 +00002773static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy,
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002774 const NamedDecl *ND,
2775 CodeCompletionBuilder &Result) {
Douglas Gregor0212fd72010-09-21 16:06:22 +00002776 DeclarationName Name = ND->getDeclName();
2777 if (!Name)
2778 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002779
Douglas Gregor0212fd72010-09-21 16:06:22 +00002780 switch (Name.getNameKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00002781 case DeclarationName::CXXOperatorName: {
2782 const char *OperatorName = nullptr;
2783 switch (Name.getCXXOverloadedOperator()) {
2784 case OO_None:
2785 case OO_Conditional:
2786 case NUM_OVERLOADED_OPERATORS:
2787 OperatorName = "operator";
2788 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002789
Fangrui Song050229d2018-11-24 00:14:31 +00002790#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
2791 case OO_##Name: \
2792 OperatorName = "operator" Spelling; \
2793 break;
2794#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
Douglas Gregor304f9b02011-02-01 21:15:40 +00002795#include "clang/Basic/OperatorKinds.def"
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002796
Fangrui Song050229d2018-11-24 00:14:31 +00002797 case OO_New:
2798 OperatorName = "operator new";
2799 break;
2800 case OO_Delete:
2801 OperatorName = "operator delete";
2802 break;
2803 case OO_Array_New:
2804 OperatorName = "operator new[]";
2805 break;
2806 case OO_Array_Delete:
2807 OperatorName = "operator delete[]";
2808 break;
2809 case OO_Call:
2810 OperatorName = "operator()";
2811 break;
2812 case OO_Subscript:
2813 OperatorName = "operator[]";
Douglas Gregor304f9b02011-02-01 21:15:40 +00002814 break;
2815 }
Fangrui Song050229d2018-11-24 00:14:31 +00002816 Result.AddTypedTextChunk(OperatorName);
2817 break;
2818 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002819
Douglas Gregor0212fd72010-09-21 16:06:22 +00002820 case DeclarationName::Identifier:
2821 case DeclarationName::CXXConversionFunctionName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002822 case DeclarationName::CXXDestructorName:
2823 case DeclarationName::CXXLiteralOperatorName:
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002824 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002825 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002826 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002827
Richard Smith35845152017-02-07 01:37:30 +00002828 case DeclarationName::CXXDeductionGuideName:
Douglas Gregor0212fd72010-09-21 16:06:22 +00002829 case DeclarationName::CXXUsingDirective:
2830 case DeclarationName::ObjCZeroArgSelector:
2831 case DeclarationName::ObjCOneArgSelector:
2832 case DeclarationName::ObjCMultiArgSelector:
2833 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002834
Douglas Gregor0212fd72010-09-21 16:06:22 +00002835 case DeclarationName::CXXConstructorName: {
Craig Topperc3ec1492014-05-26 06:22:03 +00002836 CXXRecordDecl *Record = nullptr;
Douglas Gregor0212fd72010-09-21 16:06:22 +00002837 QualType Ty = Name.getCXXNameType();
Fangrui Song050229d2018-11-24 00:14:31 +00002838 if (const auto *RecordTy = Ty->getAs<RecordType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00002839 Record = cast<CXXRecordDecl>(RecordTy->getDecl());
Fangrui Song050229d2018-11-24 00:14:31 +00002840 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>())
Douglas Gregor0212fd72010-09-21 16:06:22 +00002841 Record = InjectedTy->getDecl();
2842 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002843 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002844 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002845 break;
2846 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002847
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002848 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002849 Result.getAllocator().CopyString(Record->getNameAsString()));
Douglas Gregor0212fd72010-09-21 16:06:22 +00002850 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) {
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002851 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Douglas Gregor75acd922011-09-27 23:30:47 +00002852 AddTemplateParameterChunks(Context, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00002853 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor0212fd72010-09-21 16:06:22 +00002854 }
2855 break;
2856 }
2857 }
2858}
2859
Fangrui Song050229d2018-11-24 00:14:31 +00002860CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
2861 Sema &S, const CodeCompletionContext &CCContext,
2862 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
2863 bool IncludeBriefComments) {
Douglas Gregorc3425b12015-07-07 06:20:19 +00002864 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator,
2865 CCTUInfo, IncludeBriefComments);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002866}
2867
Eric Liu00f43c92018-07-06 09:43:57 +00002868CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro(
2869 Preprocessor &PP, CodeCompletionAllocator &Allocator,
2870 CodeCompletionTUInfo &CCTUInfo) {
2871 assert(Kind == RK_Macro);
2872 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
2873 const MacroInfo *MI = PP.getMacroInfo(Macro);
2874 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName()));
2875
2876 if (!MI || !MI->isFunctionLike())
2877 return Result.TakeString();
2878
2879 // Format a function-like macro with placeholders for the arguments.
2880 Result.AddChunk(CodeCompletionString::CK_LeftParen);
2881 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end();
2882
2883 // C99 variadic macros add __VA_ARGS__ at the end. Skip it.
2884 if (MI->isC99Varargs()) {
2885 --AEnd;
2886
2887 if (A == AEnd) {
2888 Result.AddPlaceholderChunk("...");
2889 }
2890 }
2891
2892 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) {
2893 if (A != MI->param_begin())
2894 Result.AddChunk(CodeCompletionString::CK_Comma);
2895
2896 if (MI->isVariadic() && (A + 1) == AEnd) {
2897 SmallString<32> Arg = (*A)->getName();
2898 if (MI->isC99Varargs())
2899 Arg += ", ...";
2900 else
2901 Arg += "...";
2902 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
2903 break;
2904 }
2905
2906 // Non-variadic macros are simple.
2907 Result.AddPlaceholderChunk(
2908 Result.getAllocator().CopyString((*A)->getName()));
2909 }
2910 Result.AddChunk(CodeCompletionString::CK_RightParen);
2911 return Result.TakeString();
2912}
2913
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002914/// If possible, create a new code completion string for the given
Douglas Gregor3545ff42009-09-21 16:56:56 +00002915/// result.
2916///
2917/// \returns Either a new, heap-allocated code completion string describing
2918/// how to use this result, or NULL to indicate that the string or name of the
2919/// result is all that is needed.
Fangrui Song050229d2018-11-24 00:14:31 +00002920CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString(
2921 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext,
2922 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo,
2923 bool IncludeBriefComments) {
Eric Liu00f43c92018-07-06 09:43:57 +00002924 if (Kind == RK_Macro)
2925 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo);
2926
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00002927 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002928
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00002929 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002930 if (Kind == RK_Pattern) {
2931 Pattern->Priority = Priority;
2932 Pattern->Availability = Availability;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002933
Douglas Gregor78254c82012-03-27 23:34:16 +00002934 if (Declaration) {
2935 Result.addParentContext(Declaration->getDeclContext());
Douglas Gregor78254c82012-03-27 23:34:16 +00002936 Pattern->ParentName = Result.getParentName();
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002937 if (const RawComment *RC =
2938 getPatternCompletionComment(Ctx, Declaration)) {
2939 Result.addBriefComment(RC->getBriefText(Ctx));
2940 Pattern->BriefComment = Result.getBriefComment();
2941 }
Douglas Gregor78254c82012-03-27 23:34:16 +00002942 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002943
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002944 return Pattern;
2945 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002946
Douglas Gregorf09935f2009-12-01 05:55:20 +00002947 if (Kind == RK_Keyword) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002948 Result.AddTypedTextChunk(Keyword);
2949 return Result.TakeString();
Douglas Gregorf09935f2009-12-01 05:55:20 +00002950 }
Douglas Gregorf64acca2010-05-25 21:41:55 +00002951 assert(Kind == RK_Declaration && "Missed a result kind?");
Fangrui Song050229d2018-11-24 00:14:31 +00002952 return createCodeCompletionStringForDecl(
2953 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy);
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00002954}
2955
2956CodeCompletionString *
2957CodeCompletionResult::createCodeCompletionStringForOverride(
2958 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2959 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2960 PrintingPolicy &Policy) {
2961 std::string OverrideSignature;
2962 llvm::raw_string_ostream OS(OverrideSignature);
2963 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result,
2964 /*IncludeBriefComments=*/false,
2965 CCContext, Policy);
2966 printOverrideString(OS, CCS);
2967 OS << " override";
2968 Result.AddTypedTextChunk(Result.getAllocator().CopyString(OS.str()));
2969 return Result.TakeString();
2970}
2971
2972CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl(
2973 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result,
2974 bool IncludeBriefComments, const CodeCompletionContext &CCContext,
2975 PrintingPolicy &Policy) {
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00002976 const NamedDecl *ND = Declaration;
Douglas Gregor78254c82012-03-27 23:34:16 +00002977 Result.addParentContext(ND->getDeclContext());
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002978
2979 if (IncludeBriefComments) {
2980 // Add documentation comment, if it exists.
Ilya Biryukova3f955b2018-05-16 12:30:01 +00002981 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) {
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002982 Result.addBriefComment(RC->getBriefText(Ctx));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002983 }
Dmitri Gribenko3292d062012-07-02 17:35:10 +00002984 }
2985
Douglas Gregor9eb77012009-11-07 00:00:49 +00002986 if (StartsNestedNameSpecifier) {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00002987 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00002988 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00002989 Result.AddTextChunk("::");
2990 return Result.TakeString();
Douglas Gregor9eb77012009-11-07 00:00:49 +00002991 }
Erik Verbruggen98ea7f62011-10-14 15:31:08 +00002992
Aaron Ballmanbe22bcb2014-03-10 17:08:28 +00002993 for (const auto *I : ND->specific_attrs<AnnotateAttr>())
2994 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation()));
Aaron Ballmanb97112e2014-03-08 22:19:01 +00002995
Douglas Gregorc3425b12015-07-07 06:20:19 +00002996 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002997
Fangrui Song050229d2018-11-24 00:14:31 +00002998 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00002999 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003000 Ctx, Policy);
3001 AddTypedNameChunk(Ctx, Policy, ND, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003002 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003003 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003004 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003005 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003006 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003007 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003008
Fangrui Song050229d2018-11-24 00:14:31 +00003009 if (const FunctionTemplateDecl *FunTmpl =
3010 dyn_cast<FunctionTemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003011 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003012 Ctx, Policy);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003013 FunctionDecl *Function = FunTmpl->getTemplatedDecl();
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003014 AddTypedNameChunk(Ctx, Policy, Function, Result);
Douglas Gregor0212fd72010-09-21 16:06:22 +00003015
Douglas Gregor3545ff42009-09-21 16:56:56 +00003016 // Figure out which template parameters are deduced (or have default
3017 // arguments).
Benjamin Kramere0513cb2012-01-30 16:17:39 +00003018 llvm::SmallBitVector Deduced;
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003019 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003020 unsigned LastDeducibleArgument;
3021 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0;
3022 --LastDeducibleArgument) {
3023 if (!Deduced[LastDeducibleArgument - 1]) {
3024 // C++0x: Figure out if the template argument has a default. If so,
3025 // the user doesn't need to type this argument.
3026 // FIXME: We need to abstract template parameters better!
3027 bool HasDefaultArg = false;
3028 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam(
Fangrui Song050229d2018-11-24 00:14:31 +00003029 LastDeducibleArgument - 1);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003030 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param))
3031 HasDefaultArg = TTP->hasDefaultArgument();
Fangrui Song050229d2018-11-24 00:14:31 +00003032 else if (NonTypeTemplateParmDecl *NTTP =
3033 dyn_cast<NonTypeTemplateParmDecl>(Param))
Douglas Gregor3545ff42009-09-21 16:56:56 +00003034 HasDefaultArg = NTTP->hasDefaultArgument();
3035 else {
3036 assert(isa<TemplateTemplateParmDecl>(Param));
Fangrui Song050229d2018-11-24 00:14:31 +00003037 HasDefaultArg =
3038 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003039 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003040
Douglas Gregor3545ff42009-09-21 16:56:56 +00003041 if (!HasDefaultArg)
3042 break;
3043 }
3044 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003045
Douglas Gregor3545ff42009-09-21 16:56:56 +00003046 if (LastDeducibleArgument) {
3047 // Some of the function template arguments cannot be deduced from a
3048 // function call, so we introduce an explicit template argument list
3049 // containing all of the arguments up to the first deducible argument.
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003050 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003051 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result,
Douglas Gregor3545ff42009-09-21 16:56:56 +00003052 LastDeducibleArgument);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003053 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003054 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003055
Douglas Gregor3545ff42009-09-21 16:56:56 +00003056 // Add the function parameters
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003057 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Richard Smith20e883e2015-04-29 23:20:19 +00003058 AddFunctionParameterChunks(PP, Policy, Function, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003059 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregor0f622362009-12-11 18:44:16 +00003060 AddFunctionTypeQualsToCompletionString(Result, Function);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003061 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003062 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003063
Fangrui Song050229d2018-11-24 00:14:31 +00003064 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003065 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003066 Ctx, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003067 Result.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003068 Result.getAllocator().CopyString(Template->getNameAsString()));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003069 Result.AddChunk(CodeCompletionString::CK_LeftAngle);
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003070 AddTemplateParameterChunks(Ctx, Policy, Template, Result);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003071 Result.AddChunk(CodeCompletionString::CK_RightAngle);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003072 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003073 }
Fangrui Song050229d2018-11-24 00:14:31 +00003074 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) {
Douglas Gregord3c5d792009-11-17 16:44:22 +00003075 Selector Sel = Method->getSelector();
3076 if (Sel.isUnarySelector()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003077 Result.AddTypedTextChunk(
3078 Result.getAllocator().CopyString(Sel.getNameForSlot(0)));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003079 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003080 }
3081
Douglas Gregoraf2a6ae2011-02-18 22:29:55 +00003082 std::string SelName = Sel.getNameForSlot(0).str();
Douglas Gregor1b605f72009-11-19 01:08:35 +00003083 SelName += ':';
3084 if (StartParameter == 0)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003085 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName));
Douglas Gregor1b605f72009-11-19 01:08:35 +00003086 else {
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003087 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003088
Douglas Gregor1b605f72009-11-19 01:08:35 +00003089 // If there is only one parameter, and we're past it, add an empty
3090 // typed-text chunk since there is nothing to type.
3091 if (Method->param_size() == 1)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003092 Result.AddTypedTextChunk("");
Douglas Gregor1b605f72009-11-19 01:08:35 +00003093 }
Douglas Gregord3c5d792009-11-17 16:44:22 +00003094 unsigned Idx = 0;
Dmitri Gribenkofe0483d2013-01-23 17:21:11 +00003095 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003096 PEnd = Method->param_end();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003097 P != PEnd; (void)++P, ++Idx) {
3098 if (Idx > 0) {
Douglas Gregor1b605f72009-11-19 01:08:35 +00003099 std::string Keyword;
3100 if (Idx > StartParameter)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003101 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace);
Douglas Gregord3c5d792009-11-17 16:44:22 +00003102 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx))
Benjamin Kramer632500c2011-07-26 16:59:25 +00003103 Keyword += II->getName();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003104 Keyword += ":";
Douglas Gregor95887f92010-07-08 23:20:03 +00003105 if (Idx < StartParameter || AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003106 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword));
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003107 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003108 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003109 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003110
Douglas Gregor1b605f72009-11-19 01:08:35 +00003111 // If we're before the starting parameter, skip the placeholder.
3112 if (Idx < StartParameter)
3113 continue;
Douglas Gregord3c5d792009-11-17 16:44:22 +00003114
3115 std::string Arg;
Douglas Gregorc3425b12015-07-07 06:20:19 +00003116 QualType ParamType = (*P)->getType();
3117 Optional<ArrayRef<QualType>> ObjCSubsts;
3118 if (!CCContext.getBaseType().isNull())
3119 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method);
3120
3121 if (ParamType->isBlockPointerType() && !DeclaringEntity)
3122 Arg = FormatFunctionParameter(Policy, *P, true,
Fangrui Song050229d2018-11-24 00:14:31 +00003123 /*SuppressBlock=*/false, ObjCSubsts);
Douglas Gregore90dd002010-08-24 16:15:59 +00003124 else {
Douglas Gregorc3425b12015-07-07 06:20:19 +00003125 if (ObjCSubsts)
Fangrui Song050229d2018-11-24 00:14:31 +00003126 ParamType = ParamType.substObjCTypeArgs(
3127 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter);
Douglas Gregor86b42682015-06-19 18:27:52 +00003128 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(),
Douglas Gregorc3425b12015-07-07 06:20:19 +00003129 ParamType);
3130 Arg += ParamType.getAsString(Policy) + ")";
Douglas Gregore90dd002010-08-24 16:15:59 +00003131 if (IdentifierInfo *II = (*P)->getIdentifier())
Douglas Gregor981a0c42010-08-29 19:47:46 +00003132 if (DeclaringEntity || AllParametersAreInformative)
Benjamin Kramer632500c2011-07-26 16:59:25 +00003133 Arg += II->getName();
Douglas Gregore90dd002010-08-24 16:15:59 +00003134 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003135
Douglas Gregor400f5972010-08-31 05:13:43 +00003136 if (Method->isVariadic() && (P + 1) == PEnd)
3137 Arg += ", ...";
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003138
Douglas Gregor95887f92010-07-08 23:20:03 +00003139 if (DeclaringEntity)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003140 Result.AddTextChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregor95887f92010-07-08 23:20:03 +00003141 else if (AllParametersAreInformative)
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003142 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregorc8537c52009-11-19 07:41:15 +00003143 else
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003144 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg));
Douglas Gregord3c5d792009-11-17 16:44:22 +00003145 }
3146
Douglas Gregor04c5f972009-12-23 00:21:46 +00003147 if (Method->isVariadic()) {
Douglas Gregor400f5972010-08-31 05:13:43 +00003148 if (Method->param_size() == 0) {
3149 if (DeclaringEntity)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003150 Result.AddTextChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003151 else if (AllParametersAreInformative)
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003152 Result.AddInformativeChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003153 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003154 Result.AddPlaceholderChunk(", ...");
Douglas Gregor400f5972010-08-31 05:13:43 +00003155 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003156
Richard Smith20e883e2015-04-29 23:20:19 +00003157 MaybeAddSentinel(PP, Method, Result);
Douglas Gregor04c5f972009-12-23 00:21:46 +00003158 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003159
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003160 return Result.TakeString();
Douglas Gregord3c5d792009-11-17 16:44:22 +00003161 }
3162
Douglas Gregorf09935f2009-12-01 05:55:20 +00003163 if (Qualifier)
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003164 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative,
Argyrios Kyrtzidis8d05ca72012-01-17 02:15:51 +00003165 Ctx, Policy);
Douglas Gregorf09935f2009-12-01 05:55:20 +00003166
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003167 Result.AddTypedTextChunk(
Kadir Cetinkayaae45d0a42018-10-02 09:42:31 +00003168 Result.getAllocator().CopyString(ND->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003169 return Result.TakeString();
Douglas Gregor3545ff42009-09-21 16:56:56 +00003170}
3171
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003172const RawComment *clang::getCompletionComment(const ASTContext &Ctx,
3173 const NamedDecl *ND) {
3174 if (!ND)
3175 return nullptr;
3176 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND))
3177 return RC;
3178
3179 // Try to find comment from a property for ObjC methods.
Fangrui Song050229d2018-11-24 00:14:31 +00003180 const auto *M = dyn_cast<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003181 if (!M)
3182 return nullptr;
3183 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3184 if (!PDecl)
3185 return nullptr;
3186
3187 return Ctx.getRawCommentForAnyRedecl(PDecl);
3188}
3189
3190const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx,
3191 const NamedDecl *ND) {
Fangrui Song050229d2018-11-24 00:14:31 +00003192 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND);
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003193 if (!M || !M->isPropertyAccessor())
3194 return nullptr;
3195
3196 // Provide code completion comment for self.GetterName where
3197 // GetterName is the getter method for a property with name
3198 // different from the property name (declared via a property
3199 // getter attribute.
3200 const ObjCPropertyDecl *PDecl = M->findPropertyDecl();
3201 if (!PDecl)
3202 return nullptr;
3203 if (PDecl->getGetterName() == M->getSelector() &&
3204 PDecl->getIdentifier() != M->getIdentifier()) {
3205 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M))
3206 return RC;
3207 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl))
3208 return RC;
3209 }
3210 return nullptr;
3211}
3212
3213const RawComment *clang::getParameterComment(
3214 const ASTContext &Ctx,
Fangrui Song050229d2018-11-24 00:14:31 +00003215 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003216 auto FDecl = Result.getFunction();
3217 if (!FDecl)
3218 return nullptr;
3219 if (ArgIndex < FDecl->getNumParams())
3220 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex));
3221 return nullptr;
3222}
3223
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003224/// Add function overload parameter chunks to the given code completion
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003225/// string.
3226static void AddOverloadParameterChunks(ASTContext &Context,
3227 const PrintingPolicy &Policy,
3228 const FunctionDecl *Function,
3229 const FunctionProtoType *Prototype,
3230 CodeCompletionBuilder &Result,
Fangrui Song050229d2018-11-24 00:14:31 +00003231 unsigned CurrentArg, unsigned Start = 0,
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003232 bool InOptional = false) {
3233 bool FirstParameter = true;
Fangrui Song050229d2018-11-24 00:14:31 +00003234 unsigned NumParams =
3235 Function ? Function->getNumParams() : Prototype->getNumParams();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003236
3237 for (unsigned P = Start; P != NumParams; ++P) {
3238 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) {
3239 // When we see an optional default argument, put that argument and
3240 // the remaining default arguments into a new, optional string.
3241 CodeCompletionBuilder Opt(Result.getAllocator(),
3242 Result.getCodeCompletionTUInfo());
3243 if (!FirstParameter)
3244 Opt.AddChunk(CodeCompletionString::CK_Comma);
3245 // Optional sections are nested.
3246 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt,
3247 CurrentArg, P, /*InOptional=*/true);
3248 Result.AddOptionalChunk(Opt.TakeString());
3249 return;
3250 }
3251
3252 if (FirstParameter)
3253 FirstParameter = false;
3254 else
3255 Result.AddChunk(CodeCompletionString::CK_Comma);
3256
3257 InOptional = false;
3258
3259 // Format the placeholder string.
3260 std::string Placeholder;
Erik Verbruggen11338c52017-07-19 10:45:40 +00003261 if (Function) {
3262 const ParmVarDecl *Param = Function->getParamDecl(P);
3263 Placeholder = FormatFunctionParameter(Policy, Param);
3264 if (Param->hasDefaultArg())
Fangrui Song050229d2018-11-24 00:14:31 +00003265 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(),
3266 Context.getLangOpts());
Erik Verbruggen11338c52017-07-19 10:45:40 +00003267 } else {
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003268 Placeholder = Prototype->getParamType(P).getAsString(Policy);
Erik Verbruggen11338c52017-07-19 10:45:40 +00003269 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003270
3271 if (P == CurrentArg)
3272 Result.AddCurrentParameterChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003273 Result.getAllocator().CopyString(Placeholder));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003274 else
3275 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder));
3276 }
3277
3278 if (Prototype && Prototype->isVariadic()) {
3279 CodeCompletionBuilder Opt(Result.getAllocator(),
3280 Result.getCodeCompletionTUInfo());
3281 if (!FirstParameter)
3282 Opt.AddChunk(CodeCompletionString::CK_Comma);
3283
3284 if (CurrentArg < NumParams)
3285 Opt.AddPlaceholderChunk("...");
3286 else
3287 Opt.AddCurrentParameterChunk("...");
3288
3289 Result.AddOptionalChunk(Opt.TakeString());
3290 }
3291}
3292
Douglas Gregorf0f51982009-09-23 00:34:09 +00003293CodeCompletionString *
3294CodeCompleteConsumer::OverloadCandidate::CreateSignatureString(
Fangrui Song050229d2018-11-24 00:14:31 +00003295 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator,
3296 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const {
Douglas Gregor75acd922011-09-27 23:30:47 +00003297 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
John McCall31168b02011-06-15 23:02:42 +00003298
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003299 // FIXME: Set priority, availability appropriately.
Fangrui Song050229d2018-11-24 00:14:31 +00003300 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1,
3301 CXAvailability_Available);
Douglas Gregorf0f51982009-09-23 00:34:09 +00003302 FunctionDecl *FDecl = getFunction();
Fangrui Song050229d2018-11-24 00:14:31 +00003303 const FunctionProtoType *Proto =
3304 dyn_cast<FunctionProtoType>(getFunctionType());
Douglas Gregorf0f51982009-09-23 00:34:09 +00003305 if (!FDecl && !Proto) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003306 // Function without a prototype. Just give the return type and a
Douglas Gregorf0f51982009-09-23 00:34:09 +00003307 // highlighted ellipsis.
3308 const FunctionType *FT = getFunctionType();
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003309 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Fangrui Song050229d2018-11-24 00:14:31 +00003310 FT->getReturnType().getAsString(Policy)));
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003311 Result.AddChunk(CodeCompletionString::CK_LeftParen);
3312 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "...");
3313 Result.AddChunk(CodeCompletionString::CK_RightParen);
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003314 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003315 }
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003316
3317 if (FDecl) {
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003318 if (IncludeBriefComments) {
3319 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg))
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003320 Result.addBriefComment(RC->getBriefText(S.getASTContext()));
Ilya Biryukova3f955b2018-05-16 12:30:01 +00003321 }
Douglas Gregorc3425b12015-07-07 06:20:19 +00003322 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003323 Result.AddTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003324 Result.getAllocator().CopyString(FDecl->getNameAsString()));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003325 } else {
Fangrui Song050229d2018-11-24 00:14:31 +00003326 Result.AddResultTypeChunk(Result.getAllocator().CopyString(
Alp Toker314cc812014-01-25 16:55:45 +00003327 Proto->getReturnType().getAsString(Policy)));
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003328 }
Alp Toker314cc812014-01-25 16:55:45 +00003329
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003330 Result.AddChunk(CodeCompletionString::CK_LeftParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003331 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result,
3332 CurrentArg);
Benjamin Kramerdb534a42012-03-26 16:57:36 +00003333 Result.AddChunk(CodeCompletionString::CK_RightParen);
Francisco Lopes da Silva0c010cd2015-01-28 14:17:22 +00003334
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003335 return Result.TakeString();
Douglas Gregorf0f51982009-09-23 00:34:09 +00003336}
3337
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003338unsigned clang::getMacroUsagePriority(StringRef MacroName,
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003339 const LangOptions &LangOpts,
Douglas Gregor6e240332010-08-16 16:18:59 +00003340 bool PreferredTypeIsPointer) {
3341 unsigned Priority = CCP_Macro;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003342
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003343 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants.
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003344 if (MacroName.equals("nil") || MacroName.equals("NULL") ||
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003345 MacroName.equals("Nil")) {
Douglas Gregor6e240332010-08-16 16:18:59 +00003346 Priority = CCP_Constant;
3347 if (PreferredTypeIsPointer)
3348 Priority = Priority / CCF_SimilarTypeMatch;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003349 }
Douglas Gregor9dcf58a2010-09-20 21:11:48 +00003350 // Treat "YES", "NO", "true", and "false" as constants.
3351 else if (MacroName.equals("YES") || MacroName.equals("NO") ||
3352 MacroName.equals("true") || MacroName.equals("false"))
3353 Priority = CCP_Constant;
3354 // Treat "bool" as a type.
3355 else if (MacroName.equals("bool"))
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003356 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003357
Douglas Gregor6e240332010-08-16 16:18:59 +00003358 return Priority;
3359}
3360
Dmitri Gribenkobdc80de2013-01-11 20:32:41 +00003361CXCursorKind clang::getCursorKindForDecl(const Decl *D) {
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003362 if (!D)
3363 return CXCursor_UnexposedDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003364
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003365 switch (D->getKind()) {
Fangrui Song050229d2018-11-24 00:14:31 +00003366 case Decl::Enum:
3367 return CXCursor_EnumDecl;
3368 case Decl::EnumConstant:
3369 return CXCursor_EnumConstantDecl;
3370 case Decl::Field:
3371 return CXCursor_FieldDecl;
3372 case Decl::Function:
3373 return CXCursor_FunctionDecl;
3374 case Decl::ObjCCategory:
3375 return CXCursor_ObjCCategoryDecl;
3376 case Decl::ObjCCategoryImpl:
3377 return CXCursor_ObjCCategoryImplDecl;
3378 case Decl::ObjCImplementation:
3379 return CXCursor_ObjCImplementationDecl;
Douglas Gregordeafd0b2011-12-27 22:43:10 +00003380
Fangrui Song050229d2018-11-24 00:14:31 +00003381 case Decl::ObjCInterface:
3382 return CXCursor_ObjCInterfaceDecl;
3383 case Decl::ObjCIvar:
3384 return CXCursor_ObjCIvarDecl;
3385 case Decl::ObjCMethod:
3386 return cast<ObjCMethodDecl>(D)->isInstanceMethod()
3387 ? CXCursor_ObjCInstanceMethodDecl
3388 : CXCursor_ObjCClassMethodDecl;
3389 case Decl::CXXMethod:
3390 return CXCursor_CXXMethod;
3391 case Decl::CXXConstructor:
3392 return CXCursor_Constructor;
3393 case Decl::CXXDestructor:
3394 return CXCursor_Destructor;
3395 case Decl::CXXConversion:
3396 return CXCursor_ConversionFunction;
3397 case Decl::ObjCProperty:
3398 return CXCursor_ObjCPropertyDecl;
3399 case Decl::ObjCProtocol:
3400 return CXCursor_ObjCProtocolDecl;
3401 case Decl::ParmVar:
3402 return CXCursor_ParmDecl;
3403 case Decl::Typedef:
3404 return CXCursor_TypedefDecl;
3405 case Decl::TypeAlias:
3406 return CXCursor_TypeAliasDecl;
3407 case Decl::TypeAliasTemplate:
3408 return CXCursor_TypeAliasTemplateDecl;
3409 case Decl::Var:
3410 return CXCursor_VarDecl;
3411 case Decl::Namespace:
3412 return CXCursor_Namespace;
3413 case Decl::NamespaceAlias:
3414 return CXCursor_NamespaceAlias;
3415 case Decl::TemplateTypeParm:
3416 return CXCursor_TemplateTypeParameter;
3417 case Decl::NonTypeTemplateParm:
3418 return CXCursor_NonTypeTemplateParameter;
3419 case Decl::TemplateTemplateParm:
3420 return CXCursor_TemplateTemplateParameter;
3421 case Decl::FunctionTemplate:
3422 return CXCursor_FunctionTemplate;
3423 case Decl::ClassTemplate:
3424 return CXCursor_ClassTemplate;
3425 case Decl::AccessSpec:
3426 return CXCursor_CXXAccessSpecifier;
3427 case Decl::ClassTemplatePartialSpecialization:
3428 return CXCursor_ClassTemplatePartialSpecialization;
3429 case Decl::UsingDirective:
3430 return CXCursor_UsingDirective;
3431 case Decl::StaticAssert:
3432 return CXCursor_StaticAssert;
3433 case Decl::Friend:
3434 return CXCursor_FriendDecl;
3435 case Decl::TranslationUnit:
3436 return CXCursor_TranslationUnit;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003437
Fangrui Song050229d2018-11-24 00:14:31 +00003438 case Decl::Using:
3439 case Decl::UnresolvedUsingValue:
3440 case Decl::UnresolvedUsingTypename:
3441 return CXCursor_UsingDeclaration;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003442
Fangrui Song050229d2018-11-24 00:14:31 +00003443 case Decl::ObjCPropertyImpl:
3444 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) {
3445 case ObjCPropertyImplDecl::Dynamic:
3446 return CXCursor_ObjCDynamicDecl;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003447
Fangrui Song050229d2018-11-24 00:14:31 +00003448 case ObjCPropertyImplDecl::Synthesize:
3449 return CXCursor_ObjCSynthesizeDecl;
3450 }
3451
3452 case Decl::Import:
3453 return CXCursor_ModuleImportDecl;
3454
3455 case Decl::ObjCTypeParam:
3456 return CXCursor_TemplateTypeParameter;
3457
3458 default:
3459 if (const auto *TD = dyn_cast<TagDecl>(D)) {
3460 switch (TD->getTagKind()) {
3461 case TTK_Interface: // fall through
3462 case TTK_Struct:
3463 return CXCursor_StructDecl;
3464 case TTK_Class:
3465 return CXCursor_ClassDecl;
3466 case TTK_Union:
3467 return CXCursor_UnionDecl;
3468 case TTK_Enum:
3469 return CXCursor_EnumDecl;
Douglas Gregor4cd65962011-06-03 23:08:58 +00003470 }
Fangrui Song050229d2018-11-24 00:14:31 +00003471 }
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003472 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003473
Douglas Gregor09c0eb12010-09-03 23:30:36 +00003474 return CXCursor_UnexposedDecl;
3475}
3476
Douglas Gregor55b037b2010-07-08 20:55:51 +00003477static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results,
Eric Liu88de9f62018-09-19 09:34:55 +00003478 bool LoadExternal, bool IncludeUndefined,
Douglas Gregor55b037b2010-07-08 20:55:51 +00003479 bool TargetTypeIsPointer = false) {
John McCall276321a2010-08-25 06:19:51 +00003480 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003481
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003482 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003483
Eric Liu88de9f62018-09-19 09:34:55 +00003484 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal),
3485 MEnd = PP.macro_end(LoadExternal);
Douglas Gregor55b037b2010-07-08 20:55:51 +00003486 M != MEnd; ++M) {
Richard Smith20e883e2015-04-29 23:20:19 +00003487 auto MD = PP.getMacroDefinition(M->first);
3488 if (IncludeUndefined || MD) {
Eric Liud485df12018-09-05 14:59:17 +00003489 MacroInfo *MI = MD.getMacroInfo();
3490 if (MI && MI->isUsedForHeaderGuard())
3491 continue;
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003492
Eric Liud485df12018-09-05 14:59:17 +00003493 Results.AddResult(
3494 Result(M->first, MI,
3495 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(),
3496 TargetTypeIsPointer)));
Argyrios Kyrtzidis9ef53ce2014-04-09 18:21:23 +00003497 }
Douglas Gregor55b037b2010-07-08 20:55:51 +00003498 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003499
Douglas Gregorf329c7c2009-10-30 16:50:04 +00003500 Results.ExitScope();
3501}
3502
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003503static void AddPrettyFunctionResults(const LangOptions &LangOpts,
Douglas Gregorce0e8562010-08-23 21:54:33 +00003504 ResultBuilder &Results) {
John McCall276321a2010-08-25 06:19:51 +00003505 typedef CodeCompletionResult Result;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003506
Douglas Gregorce0e8562010-08-23 21:54:33 +00003507 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003508
Douglas Gregorce0e8562010-08-23 21:54:33 +00003509 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant));
3510 Results.AddResult(Result("__FUNCTION__", CCP_Constant));
Richard Smith2bf7fdb2013-01-02 11:42:31 +00003511 if (LangOpts.C99 || LangOpts.CPlusPlus11)
Douglas Gregorce0e8562010-08-23 21:54:33 +00003512 Results.AddResult(Result("__func__", CCP_Constant));
3513 Results.ExitScope();
3514}
3515
Daniel Dunbar242ea9a2009-11-13 08:58:20 +00003516static void HandleCodeCompleteResults(Sema *S,
3517 CodeCompleteConsumer *CodeCompleter,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003518 CodeCompletionContext Context,
John McCall276321a2010-08-25 06:19:51 +00003519 CodeCompletionResult *Results,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003520 unsigned NumResults) {
Douglas Gregor3545ff42009-09-21 16:56:56 +00003521 if (CodeCompleter)
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003522 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults);
Douglas Gregor3545ff42009-09-21 16:56:56 +00003523}
3524
Fangrui Song050229d2018-11-24 00:14:31 +00003525static enum CodeCompletionContext::Kind
3526mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003527 switch (PCC) {
John McCallfaf5fb42010-08-26 23:41:50 +00003528 case Sema::PCC_Namespace:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003529 return CodeCompletionContext::CCC_TopLevel;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003530
John McCallfaf5fb42010-08-26 23:41:50 +00003531 case Sema::PCC_Class:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003532 return CodeCompletionContext::CCC_ClassStructUnion;
3533
John McCallfaf5fb42010-08-26 23:41:50 +00003534 case Sema::PCC_ObjCInterface:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003535 return CodeCompletionContext::CCC_ObjCInterface;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003536
John McCallfaf5fb42010-08-26 23:41:50 +00003537 case Sema::PCC_ObjCImplementation:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003538 return CodeCompletionContext::CCC_ObjCImplementation;
3539
John McCallfaf5fb42010-08-26 23:41:50 +00003540 case Sema::PCC_ObjCInstanceVariableList:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003541 return CodeCompletionContext::CCC_ObjCIvarList;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003542
John McCallfaf5fb42010-08-26 23:41:50 +00003543 case Sema::PCC_Template:
3544 case Sema::PCC_MemberTemplate:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003545 if (S.CurContext->isFileContext())
3546 return CodeCompletionContext::CCC_TopLevel;
David Blaikie8a40f702012-01-17 06:56:22 +00003547 if (S.CurContext->isRecord())
Douglas Gregor0ac41382010-09-23 23:01:17 +00003548 return CodeCompletionContext::CCC_ClassStructUnion;
David Blaikie8a40f702012-01-17 06:56:22 +00003549 return CodeCompletionContext::CCC_Other;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003550
John McCallfaf5fb42010-08-26 23:41:50 +00003551 case Sema::PCC_RecoveryInFunction:
Douglas Gregor0ac41382010-09-23 23:01:17 +00003552 return CodeCompletionContext::CCC_Recovery;
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003553
John McCallfaf5fb42010-08-26 23:41:50 +00003554 case Sema::PCC_ForInit:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003555 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 ||
Erik Pilkingtonfa983902018-10-30 20:31:30 +00003556 S.getLangOpts().ObjC)
Douglas Gregorc769d6e2010-10-18 22:01:46 +00003557 return CodeCompletionContext::CCC_ParenthesizedExpression;
3558 else
3559 return CodeCompletionContext::CCC_Expression;
3560
3561 case Sema::PCC_Expression:
John McCallfaf5fb42010-08-26 23:41:50 +00003562 case Sema::PCC_Condition:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003563 return CodeCompletionContext::CCC_Expression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003564
John McCallfaf5fb42010-08-26 23:41:50 +00003565 case Sema::PCC_Statement:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003566 return CodeCompletionContext::CCC_Statement;
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003567
John McCallfaf5fb42010-08-26 23:41:50 +00003568 case Sema::PCC_Type:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003569 return CodeCompletionContext::CCC_Type;
Douglas Gregor5e35d592010-09-14 23:59:36 +00003570
3571 case Sema::PCC_ParenthesizedExpression:
3572 return CodeCompletionContext::CCC_ParenthesizedExpression;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003573
Douglas Gregor80039242011-02-15 20:33:25 +00003574 case Sema::PCC_LocalDeclarationSpecifiers:
3575 return CodeCompletionContext::CCC_Type;
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003576 }
David Blaikie8a40f702012-01-17 06:56:22 +00003577
3578 llvm_unreachable("Invalid ParserCompletionContext!");
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003579}
3580
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003581/// If we're in a C++ virtual member function, add completion results
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003582/// that invoke the functions we override, since it's common to invoke the
Douglas Gregorac322ec2010-08-27 21:18:54 +00003583/// overridden function as well as adding new functionality.
3584///
3585/// \param S The semantic analysis object for which we are generating results.
3586///
3587/// \param InContext This context in which the nested-name-specifier preceding
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003588/// the code-completion point
Douglas Gregorac322ec2010-08-27 21:18:54 +00003589static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext,
3590 ResultBuilder &Results) {
3591 // Look through blocks.
3592 DeclContext *CurContext = S.CurContext;
3593 while (isa<BlockDecl>(CurContext))
3594 CurContext = CurContext->getParent();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003595
Douglas Gregorac322ec2010-08-27 21:18:54 +00003596 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext);
3597 if (!Method || !Method->isVirtual())
3598 return;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003599
3600 // We need to have names for all of the parameters, if we're going to
Douglas Gregorac322ec2010-08-27 21:18:54 +00003601 // generate a forwarding call.
David Majnemer59f77922016-06-24 04:05:48 +00003602 for (auto P : Method->parameters())
Aaron Ballman43b68be2014-03-07 17:50:17 +00003603 if (!P->getDeclName())
Douglas Gregorac322ec2010-08-27 21:18:54 +00003604 return;
Douglas Gregorac322ec2010-08-27 21:18:54 +00003605
Douglas Gregor75acd922011-09-27 23:30:47 +00003606 PrintingPolicy Policy = getCompletionPrintingPolicy(S);
Benjamin Krameracfa3392017-12-17 23:52:45 +00003607 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) {
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003608 CodeCompletionBuilder Builder(Results.getAllocator(),
3609 Results.getCodeCompletionTUInfo());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003610 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl())
3611 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003612
Douglas Gregorac322ec2010-08-27 21:18:54 +00003613 // If we need a nested-name-specifier, add one now.
3614 if (!InContext) {
Fangrui Song050229d2018-11-24 00:14:31 +00003615 NestedNameSpecifier *NNS = getRequiredQualification(
3616 S.Context, CurContext, Overridden->getDeclContext());
Douglas Gregorac322ec2010-08-27 21:18:54 +00003617 if (NNS) {
3618 std::string Str;
3619 llvm::raw_string_ostream OS(Str);
Douglas Gregor75acd922011-09-27 23:30:47 +00003620 NNS->print(OS, Policy);
Douglas Gregorbcbf46c2011-02-01 22:57:45 +00003621 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003622 }
3623 } else if (!InContext->Equals(Overridden->getDeclContext()))
3624 continue;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003625
Fangrui Song050229d2018-11-24 00:14:31 +00003626 Builder.AddTypedTextChunk(
3627 Results.getAllocator().CopyString(Overridden->getNameAsString()));
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003628 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003629 bool FirstParam = true;
David Majnemer59f77922016-06-24 04:05:48 +00003630 for (auto P : Method->parameters()) {
Douglas Gregorac322ec2010-08-27 21:18:54 +00003631 if (FirstParam)
3632 FirstParam = false;
3633 else
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003634 Builder.AddChunk(CodeCompletionString::CK_Comma);
Douglas Gregorac322ec2010-08-27 21:18:54 +00003635
Aaron Ballman43b68be2014-03-07 17:50:17 +00003636 Builder.AddPlaceholderChunk(
3637 Results.getAllocator().CopyString(P->getIdentifier()->getName()));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003638 }
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003639 Builder.AddChunk(CodeCompletionString::CK_RightParen);
Fangrui Song050229d2018-11-24 00:14:31 +00003640 Results.AddResult(CodeCompletionResult(
3641 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod,
3642 CXAvailability_Available, Overridden));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003643 Results.Ignore(Overridden);
3644 }
3645}
3646
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003647void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc,
Douglas Gregor07f43572012-01-29 18:15:03 +00003648 ModuleIdPath Path) {
3649 typedef CodeCompletionResult Result;
3650 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003651 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor07f43572012-01-29 18:15:03 +00003652 CodeCompletionContext::CCC_Other);
3653 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003654
Douglas Gregor07f43572012-01-29 18:15:03 +00003655 CodeCompletionAllocator &Allocator = Results.getAllocator();
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003656 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo());
Douglas Gregor07f43572012-01-29 18:15:03 +00003657 typedef CodeCompletionResult Result;
3658 if (Path.empty()) {
3659 // Enumerate all top-level modules.
Dmitri Gribenkof8579502013-01-12 19:30:44 +00003660 SmallVector<Module *, 8> Modules;
Douglas Gregor07f43572012-01-29 18:15:03 +00003661 PP.getHeaderSearchInfo().collectAllModules(Modules);
3662 for (unsigned I = 0, N = Modules.size(); I != N; ++I) {
3663 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003664 Builder.getAllocator().CopyString(Modules[I]->Name));
3665 Results.AddResult(Result(
3666 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3667 Modules[I]->isAvailable() ? CXAvailability_Available
3668 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003669 }
Daniel Jasper07e6c402013-08-05 20:26:17 +00003670 } else if (getLangOpts().Modules) {
Douglas Gregor07f43572012-01-29 18:15:03 +00003671 // Load the named module.
Fangrui Song050229d2018-11-24 00:14:31 +00003672 Module *Mod =
3673 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible,
3674 /*IsInclusionDirective=*/false);
Douglas Gregor07f43572012-01-29 18:15:03 +00003675 // Enumerate submodules.
3676 if (Mod) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003677 for (Module::submodule_iterator Sub = Mod->submodule_begin(),
Fangrui Song050229d2018-11-24 00:14:31 +00003678 SubEnd = Mod->submodule_end();
Douglas Gregor07f43572012-01-29 18:15:03 +00003679 Sub != SubEnd; ++Sub) {
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003680
Douglas Gregor07f43572012-01-29 18:15:03 +00003681 Builder.AddTypedTextChunk(
Fangrui Song050229d2018-11-24 00:14:31 +00003682 Builder.getAllocator().CopyString((*Sub)->Name));
3683 Results.AddResult(Result(
3684 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl,
3685 (*Sub)->isAvailable() ? CXAvailability_Available
3686 : CXAvailability_NotAvailable));
Douglas Gregor07f43572012-01-29 18:15:03 +00003687 }
3688 }
3689 }
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003690 Results.ExitScope();
Douglas Gregor07f43572012-01-29 18:15:03 +00003691 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(),
Fangrui Song050229d2018-11-24 00:14:31 +00003692 Results.data(), Results.size());
Douglas Gregor07f43572012-01-29 18:15:03 +00003693}
3694
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003695void Sema::CodeCompleteOrdinaryName(Scope *S,
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003696 ParserCompletionContext CompletionContext) {
Douglas Gregorb278aaf2011-02-01 19:23:04 +00003697 ResultBuilder Results(*this, CodeCompleter->getAllocator(),
Argyrios Kyrtzidis9d7c0fe2012-04-10 17:23:48 +00003698 CodeCompleter->getCodeCompletionTUInfo(),
Douglas Gregor0ac41382010-09-23 23:01:17 +00003699 mapCodeCompletionContext(*this, CompletionContext));
Douglas Gregorac322ec2010-08-27 21:18:54 +00003700 Results.EnterNewScope();
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003701
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003702 // Determine how to filter results, e.g., so that the names of
3703 // values (functions, enumerators, function templates, etc.) are
3704 // only allowed where we can have an expression.
3705 switch (CompletionContext) {
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003706 case PCC_Namespace:
3707 case PCC_Class:
3708 case PCC_ObjCInterface:
3709 case PCC_ObjCImplementation:
3710 case PCC_ObjCInstanceVariableList:
3711 case PCC_Template:
3712 case PCC_MemberTemplate:
Douglas Gregorf02e5f32010-08-24 01:11:00 +00003713 case PCC_Type:
Douglas Gregor80039242011-02-15 20:33:25 +00003714 case PCC_LocalDeclarationSpecifiers:
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003715 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName);
3716 break;
3717
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003718 case PCC_Statement:
Douglas Gregor5e35d592010-09-14 23:59:36 +00003719 case PCC_ParenthesizedExpression:
Douglas Gregor4d755e82010-08-24 23:58:17 +00003720 case PCC_Expression:
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003721 case PCC_ForInit:
3722 case PCC_Condition:
David Blaikiebbafb8a2012-03-11 07:00:24 +00003723 if (WantTypesInContext(CompletionContext, getLangOpts()))
Douglas Gregor70febae2010-05-28 00:49:12 +00003724 Results.setFilter(&ResultBuilder::IsOrdinaryName);
3725 else
3726 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName);
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003727
David Blaikiebbafb8a2012-03-11 07:00:24 +00003728 if (getLangOpts().CPlusPlus)
Craig Topperc3ec1492014-05-26 06:22:03 +00003729 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results);
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003730 break;
Kirill Bobyrev7cf29bc2018-07-05 09:37:26 +00003731
Douglas Gregor00c37ef2010-08-11 21:23:17 +00003732 case PCC_RecoveryInFunction:
Douglas Gregor6da3db42010-05-25 05:58:43 +00003733 // Unfiltered
3734 break;
Douglas Gregor504a6ae2010-01-10 23:08:15 +00003735 }
3736
Douglas Gregor9be0ed42010-08-26 16:36:48 +00003737 // If we are in a C++ non-static member function, check the qualifiers on
Ilya Biryukovf1822ec2018-12-03 13:29:17 +00003738 // the member function to filter/prioritize the results list.
Eric Liu2bfd3f52018-10-22 08:47:31 +00003739 if (CXXMethodDecl *CurMethod = dyn_cast<CXXMethodDecl>(CurContext)) {
3740 if (CurMethod->isInstance()) {
Mikael Nilsson90646732018-12-12 15:06:16 +00003741 Results.setObjectTypeQualifiers(
3742 Qualifiers::fromCVRMask(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}