Mercurial > hg > CbC > CbC_llvm
comparison clang/lib/Sema/SemaCodeComplete.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | e8a9b4f4d755 0572611fdcc8 |
comparison
equal
deleted
inserted
replaced
147:c2174574ed3a | 150:1d019706d866 |
---|---|
1 //===---------------- SemaCodeComplete.cpp - Code Completion ----*- C++ -*-===// | |
2 // | |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
4 // See https://llvm.org/LICENSE.txt for license information. | |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
6 // | |
7 //===----------------------------------------------------------------------===// | |
8 // | |
9 // This file defines the code-completion semantic actions. | |
10 // | |
11 //===----------------------------------------------------------------------===// | |
12 #include "clang/AST/Decl.h" | |
13 #include "clang/AST/DeclBase.h" | |
14 #include "clang/AST/DeclCXX.h" | |
15 #include "clang/AST/DeclObjC.h" | |
16 #include "clang/AST/DeclTemplate.h" | |
17 #include "clang/AST/Expr.h" | |
18 #include "clang/AST/ExprCXX.h" | |
19 #include "clang/AST/ExprObjC.h" | |
20 #include "clang/AST/QualTypeNames.h" | |
21 #include "clang/AST/Type.h" | |
22 #include "clang/Basic/CharInfo.h" | |
23 #include "clang/Basic/Specifiers.h" | |
24 #include "clang/Lex/HeaderSearch.h" | |
25 #include "clang/Lex/MacroInfo.h" | |
26 #include "clang/Lex/Preprocessor.h" | |
27 #include "clang/Sema/CodeCompleteConsumer.h" | |
28 #include "clang/Sema/Designator.h" | |
29 #include "clang/Sema/Lookup.h" | |
30 #include "clang/Sema/Overload.h" | |
31 #include "clang/Sema/Scope.h" | |
32 #include "clang/Sema/ScopeInfo.h" | |
33 #include "clang/Sema/Sema.h" | |
34 #include "clang/Sema/SemaInternal.h" | |
35 #include "llvm/ADT/ArrayRef.h" | |
36 #include "llvm/ADT/DenseSet.h" | |
37 #include "llvm/ADT/SmallBitVector.h" | |
38 #include "llvm/ADT/SmallPtrSet.h" | |
39 #include "llvm/ADT/SmallString.h" | |
40 #include "llvm/ADT/StringExtras.h" | |
41 #include "llvm/ADT/StringSwitch.h" | |
42 #include "llvm/ADT/Twine.h" | |
43 #include "llvm/ADT/iterator_range.h" | |
44 #include "llvm/Support/Casting.h" | |
45 #include "llvm/Support/Path.h" | |
46 #include "llvm/Support/raw_ostream.h" | |
47 #include <list> | |
48 #include <map> | |
49 #include <string> | |
50 #include <vector> | |
51 | |
52 using namespace clang; | |
53 using namespace sema; | |
54 | |
55 namespace { | |
56 /// A container of code-completion results. | |
57 class ResultBuilder { | |
58 public: | |
59 /// The type of a name-lookup filter, which can be provided to the | |
60 /// name-lookup routines to specify which declarations should be included in | |
61 /// the result set (when it returns true) and which declarations should be | |
62 /// filtered out (returns false). | |
63 typedef bool (ResultBuilder::*LookupFilter)(const NamedDecl *) const; | |
64 | |
65 typedef CodeCompletionResult Result; | |
66 | |
67 private: | |
68 /// The actual results we have found. | |
69 std::vector<Result> Results; | |
70 | |
71 /// A record of all of the declarations we have found and placed | |
72 /// into the result set, used to ensure that no declaration ever gets into | |
73 /// the result set twice. | |
74 llvm::SmallPtrSet<const Decl *, 16> AllDeclsFound; | |
75 | |
76 typedef std::pair<const NamedDecl *, unsigned> DeclIndexPair; | |
77 | |
78 /// An entry in the shadow map, which is optimized to store | |
79 /// a single (declaration, index) mapping (the common case) but | |
80 /// can also store a list of (declaration, index) mappings. | |
81 class ShadowMapEntry { | |
82 typedef SmallVector<DeclIndexPair, 4> DeclIndexPairVector; | |
83 | |
84 /// Contains either the solitary NamedDecl * or a vector | |
85 /// of (declaration, index) pairs. | |
86 llvm::PointerUnion<const NamedDecl *, DeclIndexPairVector *> DeclOrVector; | |
87 | |
88 /// When the entry contains a single declaration, this is | |
89 /// the index associated with that entry. | |
90 unsigned SingleDeclIndex; | |
91 | |
92 public: | |
93 ShadowMapEntry() : DeclOrVector(), SingleDeclIndex(0) {} | |
94 ShadowMapEntry(const ShadowMapEntry &) = delete; | |
95 ShadowMapEntry(ShadowMapEntry &&Move) { *this = std::move(Move); } | |
96 ShadowMapEntry &operator=(const ShadowMapEntry &) = delete; | |
97 ShadowMapEntry &operator=(ShadowMapEntry &&Move) { | |
98 SingleDeclIndex = Move.SingleDeclIndex; | |
99 DeclOrVector = Move.DeclOrVector; | |
100 Move.DeclOrVector = nullptr; | |
101 return *this; | |
102 } | |
103 | |
104 void Add(const NamedDecl *ND, unsigned Index) { | |
105 if (DeclOrVector.isNull()) { | |
106 // 0 - > 1 elements: just set the single element information. | |
107 DeclOrVector = ND; | |
108 SingleDeclIndex = Index; | |
109 return; | |
110 } | |
111 | |
112 if (const NamedDecl *PrevND = | |
113 DeclOrVector.dyn_cast<const NamedDecl *>()) { | |
114 // 1 -> 2 elements: create the vector of results and push in the | |
115 // existing declaration. | |
116 DeclIndexPairVector *Vec = new DeclIndexPairVector; | |
117 Vec->push_back(DeclIndexPair(PrevND, SingleDeclIndex)); | |
118 DeclOrVector = Vec; | |
119 } | |
120 | |
121 // Add the new element to the end of the vector. | |
122 DeclOrVector.get<DeclIndexPairVector *>()->push_back( | |
123 DeclIndexPair(ND, Index)); | |
124 } | |
125 | |
126 ~ShadowMapEntry() { | |
127 if (DeclIndexPairVector *Vec = | |
128 DeclOrVector.dyn_cast<DeclIndexPairVector *>()) { | |
129 delete Vec; | |
130 DeclOrVector = ((NamedDecl *)nullptr); | |
131 } | |
132 } | |
133 | |
134 // Iteration. | |
135 class iterator; | |
136 iterator begin() const; | |
137 iterator end() const; | |
138 }; | |
139 | |
140 /// A mapping from declaration names to the declarations that have | |
141 /// this name within a particular scope and their index within the list of | |
142 /// results. | |
143 typedef llvm::DenseMap<DeclarationName, ShadowMapEntry> ShadowMap; | |
144 | |
145 /// The semantic analysis object for which results are being | |
146 /// produced. | |
147 Sema &SemaRef; | |
148 | |
149 /// The allocator used to allocate new code-completion strings. | |
150 CodeCompletionAllocator &Allocator; | |
151 | |
152 CodeCompletionTUInfo &CCTUInfo; | |
153 | |
154 /// If non-NULL, a filter function used to remove any code-completion | |
155 /// results that are not desirable. | |
156 LookupFilter Filter; | |
157 | |
158 /// Whether we should allow declarations as | |
159 /// nested-name-specifiers that would otherwise be filtered out. | |
160 bool AllowNestedNameSpecifiers; | |
161 | |
162 /// If set, the type that we would prefer our resulting value | |
163 /// declarations to have. | |
164 /// | |
165 /// Closely matching the preferred type gives a boost to a result's | |
166 /// priority. | |
167 CanQualType PreferredType; | |
168 | |
169 /// A list of shadow maps, which is used to model name hiding at | |
170 /// different levels of, e.g., the inheritance hierarchy. | |
171 std::list<ShadowMap> ShadowMaps; | |
172 | |
173 /// Overloaded C++ member functions found by SemaLookup. | |
174 /// Used to determine when one overload is dominated by another. | |
175 llvm::DenseMap<std::pair<DeclContext *, /*Name*/uintptr_t>, ShadowMapEntry> | |
176 OverloadMap; | |
177 | |
178 /// If we're potentially referring to a C++ member function, the set | |
179 /// of qualifiers applied to the object type. | |
180 Qualifiers ObjectTypeQualifiers; | |
181 /// The kind of the object expression, for rvalue/lvalue overloads. | |
182 ExprValueKind ObjectKind; | |
183 | |
184 /// Whether the \p ObjectTypeQualifiers field is active. | |
185 bool HasObjectTypeQualifiers; | |
186 | |
187 /// The selector that we prefer. | |
188 Selector PreferredSelector; | |
189 | |
190 /// The completion context in which we are gathering results. | |
191 CodeCompletionContext CompletionContext; | |
192 | |
193 /// If we are in an instance method definition, the \@implementation | |
194 /// object. | |
195 ObjCImplementationDecl *ObjCImplementation; | |
196 | |
197 void AdjustResultPriorityForDecl(Result &R); | |
198 | |
199 void MaybeAddConstructorResults(Result R); | |
200 | |
201 public: | |
202 explicit ResultBuilder(Sema &SemaRef, CodeCompletionAllocator &Allocator, | |
203 CodeCompletionTUInfo &CCTUInfo, | |
204 const CodeCompletionContext &CompletionContext, | |
205 LookupFilter Filter = nullptr) | |
206 : SemaRef(SemaRef), Allocator(Allocator), CCTUInfo(CCTUInfo), | |
207 Filter(Filter), AllowNestedNameSpecifiers(false), | |
208 HasObjectTypeQualifiers(false), CompletionContext(CompletionContext), | |
209 ObjCImplementation(nullptr) { | |
210 // If this is an Objective-C instance method definition, dig out the | |
211 // corresponding implementation. | |
212 switch (CompletionContext.getKind()) { | |
213 case CodeCompletionContext::CCC_Expression: | |
214 case CodeCompletionContext::CCC_ObjCMessageReceiver: | |
215 case CodeCompletionContext::CCC_ParenthesizedExpression: | |
216 case CodeCompletionContext::CCC_Statement: | |
217 case CodeCompletionContext::CCC_Recovery: | |
218 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) | |
219 if (Method->isInstanceMethod()) | |
220 if (ObjCInterfaceDecl *Interface = Method->getClassInterface()) | |
221 ObjCImplementation = Interface->getImplementation(); | |
222 break; | |
223 | |
224 default: | |
225 break; | |
226 } | |
227 } | |
228 | |
229 /// Determine the priority for a reference to the given declaration. | |
230 unsigned getBasePriority(const NamedDecl *D); | |
231 | |
232 /// Whether we should include code patterns in the completion | |
233 /// results. | |
234 bool includeCodePatterns() const { | |
235 return SemaRef.CodeCompleter && | |
236 SemaRef.CodeCompleter->includeCodePatterns(); | |
237 } | |
238 | |
239 /// Set the filter used for code-completion results. | |
240 void setFilter(LookupFilter Filter) { this->Filter = Filter; } | |
241 | |
242 Result *data() { return Results.empty() ? nullptr : &Results.front(); } | |
243 unsigned size() const { return Results.size(); } | |
244 bool empty() const { return Results.empty(); } | |
245 | |
246 /// Specify the preferred type. | |
247 void setPreferredType(QualType T) { | |
248 PreferredType = SemaRef.Context.getCanonicalType(T); | |
249 } | |
250 | |
251 /// Set the cv-qualifiers on the object type, for us in filtering | |
252 /// calls to member functions. | |
253 /// | |
254 /// When there are qualifiers in this set, they will be used to filter | |
255 /// out member functions that aren't available (because there will be a | |
256 /// cv-qualifier mismatch) or prefer functions with an exact qualifier | |
257 /// match. | |
258 void setObjectTypeQualifiers(Qualifiers Quals, ExprValueKind Kind) { | |
259 ObjectTypeQualifiers = Quals; | |
260 ObjectKind = Kind; | |
261 HasObjectTypeQualifiers = true; | |
262 } | |
263 | |
264 /// Set the preferred selector. | |
265 /// | |
266 /// When an Objective-C method declaration result is added, and that | |
267 /// method's selector matches this preferred selector, we give that method | |
268 /// a slight priority boost. | |
269 void setPreferredSelector(Selector Sel) { PreferredSelector = Sel; } | |
270 | |
271 /// Retrieve the code-completion context for which results are | |
272 /// being collected. | |
273 const CodeCompletionContext &getCompletionContext() const { | |
274 return CompletionContext; | |
275 } | |
276 | |
277 /// Specify whether nested-name-specifiers are allowed. | |
278 void allowNestedNameSpecifiers(bool Allow = true) { | |
279 AllowNestedNameSpecifiers = Allow; | |
280 } | |
281 | |
282 /// Return the semantic analysis object for which we are collecting | |
283 /// code completion results. | |
284 Sema &getSema() const { return SemaRef; } | |
285 | |
286 /// Retrieve the allocator used to allocate code completion strings. | |
287 CodeCompletionAllocator &getAllocator() const { return Allocator; } | |
288 | |
289 CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } | |
290 | |
291 /// Determine whether the given declaration is at all interesting | |
292 /// as a code-completion result. | |
293 /// | |
294 /// \param ND the declaration that we are inspecting. | |
295 /// | |
296 /// \param AsNestedNameSpecifier will be set true if this declaration is | |
297 /// only interesting when it is a nested-name-specifier. | |
298 bool isInterestingDecl(const NamedDecl *ND, | |
299 bool &AsNestedNameSpecifier) const; | |
300 | |
301 /// Check whether the result is hidden by the Hiding declaration. | |
302 /// | |
303 /// \returns true if the result is hidden and cannot be found, false if | |
304 /// the hidden result could still be found. When false, \p R may be | |
305 /// modified to describe how the result can be found (e.g., via extra | |
306 /// qualification). | |
307 bool CheckHiddenResult(Result &R, DeclContext *CurContext, | |
308 const NamedDecl *Hiding); | |
309 | |
310 /// Add a new result to this result set (if it isn't already in one | |
311 /// of the shadow maps), or replace an existing result (for, e.g., a | |
312 /// redeclaration). | |
313 /// | |
314 /// \param R the result to add (if it is unique). | |
315 /// | |
316 /// \param CurContext the context in which this result will be named. | |
317 void MaybeAddResult(Result R, DeclContext *CurContext = nullptr); | |
318 | |
319 /// Add a new result to this result set, where we already know | |
320 /// the hiding declaration (if any). | |
321 /// | |
322 /// \param R the result to add (if it is unique). | |
323 /// | |
324 /// \param CurContext the context in which this result will be named. | |
325 /// | |
326 /// \param Hiding the declaration that hides the result. | |
327 /// | |
328 /// \param InBaseClass whether the result was found in a base | |
329 /// class of the searched context. | |
330 void AddResult(Result R, DeclContext *CurContext, NamedDecl *Hiding, | |
331 bool InBaseClass); | |
332 | |
333 /// Add a new non-declaration result to this result set. | |
334 void AddResult(Result R); | |
335 | |
336 /// Enter into a new scope. | |
337 void EnterNewScope(); | |
338 | |
339 /// Exit from the current scope. | |
340 void ExitScope(); | |
341 | |
342 /// Ignore this declaration, if it is seen again. | |
343 void Ignore(const Decl *D) { AllDeclsFound.insert(D->getCanonicalDecl()); } | |
344 | |
345 /// Add a visited context. | |
346 void addVisitedContext(DeclContext *Ctx) { | |
347 CompletionContext.addVisitedContext(Ctx); | |
348 } | |
349 | |
350 /// \name Name lookup predicates | |
351 /// | |
352 /// These predicates can be passed to the name lookup functions to filter the | |
353 /// results of name lookup. All of the predicates have the same type, so that | |
354 /// | |
355 //@{ | |
356 bool IsOrdinaryName(const NamedDecl *ND) const; | |
357 bool IsOrdinaryNonTypeName(const NamedDecl *ND) const; | |
358 bool IsIntegralConstantValue(const NamedDecl *ND) const; | |
359 bool IsOrdinaryNonValueName(const NamedDecl *ND) const; | |
360 bool IsNestedNameSpecifier(const NamedDecl *ND) const; | |
361 bool IsEnum(const NamedDecl *ND) const; | |
362 bool IsClassOrStruct(const NamedDecl *ND) const; | |
363 bool IsUnion(const NamedDecl *ND) const; | |
364 bool IsNamespace(const NamedDecl *ND) const; | |
365 bool IsNamespaceOrAlias(const NamedDecl *ND) const; | |
366 bool IsType(const NamedDecl *ND) const; | |
367 bool IsMember(const NamedDecl *ND) const; | |
368 bool IsObjCIvar(const NamedDecl *ND) const; | |
369 bool IsObjCMessageReceiver(const NamedDecl *ND) const; | |
370 bool IsObjCMessageReceiverOrLambdaCapture(const NamedDecl *ND) const; | |
371 bool IsObjCCollection(const NamedDecl *ND) const; | |
372 bool IsImpossibleToSatisfy(const NamedDecl *ND) const; | |
373 //@} | |
374 }; | |
375 } // namespace | |
376 | |
377 void PreferredTypeBuilder::enterReturn(Sema &S, SourceLocation Tok) { | |
378 if (isa<BlockDecl>(S.CurContext)) { | |
379 if (sema::BlockScopeInfo *BSI = S.getCurBlock()) { | |
380 ComputeType = nullptr; | |
381 Type = BSI->ReturnType; | |
382 ExpectedLoc = Tok; | |
383 } | |
384 } else if (const auto *Function = dyn_cast<FunctionDecl>(S.CurContext)) { | |
385 ComputeType = nullptr; | |
386 Type = Function->getReturnType(); | |
387 ExpectedLoc = Tok; | |
388 } else if (const auto *Method = dyn_cast<ObjCMethodDecl>(S.CurContext)) { | |
389 ComputeType = nullptr; | |
390 Type = Method->getReturnType(); | |
391 ExpectedLoc = Tok; | |
392 } | |
393 } | |
394 | |
395 void PreferredTypeBuilder::enterVariableInit(SourceLocation Tok, Decl *D) { | |
396 auto *VD = llvm::dyn_cast_or_null<ValueDecl>(D); | |
397 ComputeType = nullptr; | |
398 Type = VD ? VD->getType() : QualType(); | |
399 ExpectedLoc = Tok; | |
400 } | |
401 | |
402 void PreferredTypeBuilder::enterFunctionArgument( | |
403 SourceLocation Tok, llvm::function_ref<QualType()> ComputeType) { | |
404 this->ComputeType = ComputeType; | |
405 Type = QualType(); | |
406 ExpectedLoc = Tok; | |
407 } | |
408 | |
409 void PreferredTypeBuilder::enterParenExpr(SourceLocation Tok, | |
410 SourceLocation LParLoc) { | |
411 // expected type for parenthesized expression does not change. | |
412 if (ExpectedLoc == LParLoc) | |
413 ExpectedLoc = Tok; | |
414 } | |
415 | |
416 static QualType getPreferredTypeOfBinaryRHS(Sema &S, Expr *LHS, | |
417 tok::TokenKind Op) { | |
418 if (!LHS) | |
419 return QualType(); | |
420 | |
421 QualType LHSType = LHS->getType(); | |
422 if (LHSType->isPointerType()) { | |
423 if (Op == tok::plus || Op == tok::plusequal || Op == tok::minusequal) | |
424 return S.getASTContext().getPointerDiffType(); | |
425 // Pointer difference is more common than subtracting an int from a pointer. | |
426 if (Op == tok::minus) | |
427 return LHSType; | |
428 } | |
429 | |
430 switch (Op) { | |
431 // No way to infer the type of RHS from LHS. | |
432 case tok::comma: | |
433 return QualType(); | |
434 // Prefer the type of the left operand for all of these. | |
435 // Arithmetic operations. | |
436 case tok::plus: | |
437 case tok::plusequal: | |
438 case tok::minus: | |
439 case tok::minusequal: | |
440 case tok::percent: | |
441 case tok::percentequal: | |
442 case tok::slash: | |
443 case tok::slashequal: | |
444 case tok::star: | |
445 case tok::starequal: | |
446 // Assignment. | |
447 case tok::equal: | |
448 // Comparison operators. | |
449 case tok::equalequal: | |
450 case tok::exclaimequal: | |
451 case tok::less: | |
452 case tok::lessequal: | |
453 case tok::greater: | |
454 case tok::greaterequal: | |
455 case tok::spaceship: | |
456 return LHS->getType(); | |
457 // Binary shifts are often overloaded, so don't try to guess those. | |
458 case tok::greatergreater: | |
459 case tok::greatergreaterequal: | |
460 case tok::lessless: | |
461 case tok::lesslessequal: | |
462 if (LHSType->isIntegralOrEnumerationType()) | |
463 return S.getASTContext().IntTy; | |
464 return QualType(); | |
465 // Logical operators, assume we want bool. | |
466 case tok::ampamp: | |
467 case tok::pipepipe: | |
468 case tok::caretcaret: | |
469 return S.getASTContext().BoolTy; | |
470 // Operators often used for bit manipulation are typically used with the type | |
471 // of the left argument. | |
472 case tok::pipe: | |
473 case tok::pipeequal: | |
474 case tok::caret: | |
475 case tok::caretequal: | |
476 case tok::amp: | |
477 case tok::ampequal: | |
478 if (LHSType->isIntegralOrEnumerationType()) | |
479 return LHSType; | |
480 return QualType(); | |
481 // RHS should be a pointer to a member of the 'LHS' type, but we can't give | |
482 // any particular type here. | |
483 case tok::periodstar: | |
484 case tok::arrowstar: | |
485 return QualType(); | |
486 default: | |
487 // FIXME(ibiryukov): handle the missing op, re-add the assertion. | |
488 // assert(false && "unhandled binary op"); | |
489 return QualType(); | |
490 } | |
491 } | |
492 | |
493 /// Get preferred type for an argument of an unary expression. \p ContextType is | |
494 /// preferred type of the whole unary expression. | |
495 static QualType getPreferredTypeOfUnaryArg(Sema &S, QualType ContextType, | |
496 tok::TokenKind Op) { | |
497 switch (Op) { | |
498 case tok::exclaim: | |
499 return S.getASTContext().BoolTy; | |
500 case tok::amp: | |
501 if (!ContextType.isNull() && ContextType->isPointerType()) | |
502 return ContextType->getPointeeType(); | |
503 return QualType(); | |
504 case tok::star: | |
505 if (ContextType.isNull()) | |
506 return QualType(); | |
507 return S.getASTContext().getPointerType(ContextType.getNonReferenceType()); | |
508 case tok::plus: | |
509 case tok::minus: | |
510 case tok::tilde: | |
511 case tok::minusminus: | |
512 case tok::plusplus: | |
513 if (ContextType.isNull()) | |
514 return S.getASTContext().IntTy; | |
515 // leave as is, these operators typically return the same type. | |
516 return ContextType; | |
517 case tok::kw___real: | |
518 case tok::kw___imag: | |
519 return QualType(); | |
520 default: | |
521 assert(false && "unhandled unary op"); | |
522 return QualType(); | |
523 } | |
524 } | |
525 | |
526 void PreferredTypeBuilder::enterBinary(Sema &S, SourceLocation Tok, Expr *LHS, | |
527 tok::TokenKind Op) { | |
528 ComputeType = nullptr; | |
529 Type = getPreferredTypeOfBinaryRHS(S, LHS, Op); | |
530 ExpectedLoc = Tok; | |
531 } | |
532 | |
533 void PreferredTypeBuilder::enterMemAccess(Sema &S, SourceLocation Tok, | |
534 Expr *Base) { | |
535 if (!Base) | |
536 return; | |
537 // Do we have expected type for Base? | |
538 if (ExpectedLoc != Base->getBeginLoc()) | |
539 return; | |
540 // Keep the expected type, only update the location. | |
541 ExpectedLoc = Tok; | |
542 return; | |
543 } | |
544 | |
545 void PreferredTypeBuilder::enterUnary(Sema &S, SourceLocation Tok, | |
546 tok::TokenKind OpKind, | |
547 SourceLocation OpLoc) { | |
548 ComputeType = nullptr; | |
549 Type = getPreferredTypeOfUnaryArg(S, this->get(OpLoc), OpKind); | |
550 ExpectedLoc = Tok; | |
551 } | |
552 | |
553 void PreferredTypeBuilder::enterSubscript(Sema &S, SourceLocation Tok, | |
554 Expr *LHS) { | |
555 ComputeType = nullptr; | |
556 Type = S.getASTContext().IntTy; | |
557 ExpectedLoc = Tok; | |
558 } | |
559 | |
560 void PreferredTypeBuilder::enterTypeCast(SourceLocation Tok, | |
561 QualType CastType) { | |
562 ComputeType = nullptr; | |
563 Type = !CastType.isNull() ? CastType.getCanonicalType() : QualType(); | |
564 ExpectedLoc = Tok; | |
565 } | |
566 | |
567 void PreferredTypeBuilder::enterCondition(Sema &S, SourceLocation Tok) { | |
568 ComputeType = nullptr; | |
569 Type = S.getASTContext().BoolTy; | |
570 ExpectedLoc = Tok; | |
571 } | |
572 | |
573 class ResultBuilder::ShadowMapEntry::iterator { | |
574 llvm::PointerUnion<const NamedDecl *, const DeclIndexPair *> DeclOrIterator; | |
575 unsigned SingleDeclIndex; | |
576 | |
577 public: | |
578 typedef DeclIndexPair value_type; | |
579 typedef value_type reference; | |
580 typedef std::ptrdiff_t difference_type; | |
581 typedef std::input_iterator_tag iterator_category; | |
582 | |
583 class pointer { | |
584 DeclIndexPair Value; | |
585 | |
586 public: | |
587 pointer(const DeclIndexPair &Value) : Value(Value) {} | |
588 | |
589 const DeclIndexPair *operator->() const { return &Value; } | |
590 }; | |
591 | |
592 iterator() : DeclOrIterator((NamedDecl *)nullptr), SingleDeclIndex(0) {} | |
593 | |
594 iterator(const NamedDecl *SingleDecl, unsigned Index) | |
595 : DeclOrIterator(SingleDecl), SingleDeclIndex(Index) {} | |
596 | |
597 iterator(const DeclIndexPair *Iterator) | |
598 : DeclOrIterator(Iterator), SingleDeclIndex(0) {} | |
599 | |
600 iterator &operator++() { | |
601 if (DeclOrIterator.is<const NamedDecl *>()) { | |
602 DeclOrIterator = (NamedDecl *)nullptr; | |
603 SingleDeclIndex = 0; | |
604 return *this; | |
605 } | |
606 | |
607 const DeclIndexPair *I = DeclOrIterator.get<const DeclIndexPair *>(); | |
608 ++I; | |
609 DeclOrIterator = I; | |
610 return *this; | |
611 } | |
612 | |
613 /*iterator operator++(int) { | |
614 iterator tmp(*this); | |
615 ++(*this); | |
616 return tmp; | |
617 }*/ | |
618 | |
619 reference operator*() const { | |
620 if (const NamedDecl *ND = DeclOrIterator.dyn_cast<const NamedDecl *>()) | |
621 return reference(ND, SingleDeclIndex); | |
622 | |
623 return *DeclOrIterator.get<const DeclIndexPair *>(); | |
624 } | |
625 | |
626 pointer operator->() const { return pointer(**this); } | |
627 | |
628 friend bool operator==(const iterator &X, const iterator &Y) { | |
629 return X.DeclOrIterator.getOpaqueValue() == | |
630 Y.DeclOrIterator.getOpaqueValue() && | |
631 X.SingleDeclIndex == Y.SingleDeclIndex; | |
632 } | |
633 | |
634 friend bool operator!=(const iterator &X, const iterator &Y) { | |
635 return !(X == Y); | |
636 } | |
637 }; | |
638 | |
639 ResultBuilder::ShadowMapEntry::iterator | |
640 ResultBuilder::ShadowMapEntry::begin() const { | |
641 if (DeclOrVector.isNull()) | |
642 return iterator(); | |
643 | |
644 if (const NamedDecl *ND = DeclOrVector.dyn_cast<const NamedDecl *>()) | |
645 return iterator(ND, SingleDeclIndex); | |
646 | |
647 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->begin()); | |
648 } | |
649 | |
650 ResultBuilder::ShadowMapEntry::iterator | |
651 ResultBuilder::ShadowMapEntry::end() const { | |
652 if (DeclOrVector.is<const NamedDecl *>() || DeclOrVector.isNull()) | |
653 return iterator(); | |
654 | |
655 return iterator(DeclOrVector.get<DeclIndexPairVector *>()->end()); | |
656 } | |
657 | |
658 /// Compute the qualification required to get from the current context | |
659 /// (\p CurContext) to the target context (\p TargetContext). | |
660 /// | |
661 /// \param Context the AST context in which the qualification will be used. | |
662 /// | |
663 /// \param CurContext the context where an entity is being named, which is | |
664 /// typically based on the current scope. | |
665 /// | |
666 /// \param TargetContext the context in which the named entity actually | |
667 /// resides. | |
668 /// | |
669 /// \returns a nested name specifier that refers into the target context, or | |
670 /// NULL if no qualification is needed. | |
671 static NestedNameSpecifier * | |
672 getRequiredQualification(ASTContext &Context, const DeclContext *CurContext, | |
673 const DeclContext *TargetContext) { | |
674 SmallVector<const DeclContext *, 4> TargetParents; | |
675 | |
676 for (const DeclContext *CommonAncestor = TargetContext; | |
677 CommonAncestor && !CommonAncestor->Encloses(CurContext); | |
678 CommonAncestor = CommonAncestor->getLookupParent()) { | |
679 if (CommonAncestor->isTransparentContext() || | |
680 CommonAncestor->isFunctionOrMethod()) | |
681 continue; | |
682 | |
683 TargetParents.push_back(CommonAncestor); | |
684 } | |
685 | |
686 NestedNameSpecifier *Result = nullptr; | |
687 while (!TargetParents.empty()) { | |
688 const DeclContext *Parent = TargetParents.pop_back_val(); | |
689 | |
690 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Parent)) { | |
691 if (!Namespace->getIdentifier()) | |
692 continue; | |
693 | |
694 Result = NestedNameSpecifier::Create(Context, Result, Namespace); | |
695 } else if (const auto *TD = dyn_cast<TagDecl>(Parent)) | |
696 Result = NestedNameSpecifier::Create( | |
697 Context, Result, false, Context.getTypeDeclType(TD).getTypePtr()); | |
698 } | |
699 return Result; | |
700 } | |
701 | |
702 // Some declarations have reserved names that we don't want to ever show. | |
703 // Filter out names reserved for the implementation if they come from a | |
704 // system header. | |
705 static bool shouldIgnoreDueToReservedName(const NamedDecl *ND, Sema &SemaRef) { | |
706 const IdentifierInfo *Id = ND->getIdentifier(); | |
707 if (!Id) | |
708 return false; | |
709 | |
710 // Ignore reserved names for compiler provided decls. | |
711 if (Id->isReservedName() && ND->getLocation().isInvalid()) | |
712 return true; | |
713 | |
714 // For system headers ignore only double-underscore names. | |
715 // This allows for system headers providing private symbols with a single | |
716 // underscore. | |
717 if (Id->isReservedName(/*doubleUnderscoreOnly=*/true) && | |
718 SemaRef.SourceMgr.isInSystemHeader( | |
719 SemaRef.SourceMgr.getSpellingLoc(ND->getLocation()))) | |
720 return true; | |
721 | |
722 return false; | |
723 } | |
724 | |
725 bool ResultBuilder::isInterestingDecl(const NamedDecl *ND, | |
726 bool &AsNestedNameSpecifier) const { | |
727 AsNestedNameSpecifier = false; | |
728 | |
729 auto *Named = ND; | |
730 ND = ND->getUnderlyingDecl(); | |
731 | |
732 // Skip unnamed entities. | |
733 if (!ND->getDeclName()) | |
734 return false; | |
735 | |
736 // Friend declarations and declarations introduced due to friends are never | |
737 // added as results. | |
738 if (ND->getFriendObjectKind() == Decl::FOK_Undeclared) | |
739 return false; | |
740 | |
741 // Class template (partial) specializations are never added as results. | |
742 if (isa<ClassTemplateSpecializationDecl>(ND) || | |
743 isa<ClassTemplatePartialSpecializationDecl>(ND)) | |
744 return false; | |
745 | |
746 // Using declarations themselves are never added as results. | |
747 if (isa<UsingDecl>(ND)) | |
748 return false; | |
749 | |
750 if (shouldIgnoreDueToReservedName(ND, SemaRef)) | |
751 return false; | |
752 | |
753 if (Filter == &ResultBuilder::IsNestedNameSpecifier || | |
754 (isa<NamespaceDecl>(ND) && Filter != &ResultBuilder::IsNamespace && | |
755 Filter != &ResultBuilder::IsNamespaceOrAlias && Filter != nullptr)) | |
756 AsNestedNameSpecifier = true; | |
757 | |
758 // Filter out any unwanted results. | |
759 if (Filter && !(this->*Filter)(Named)) { | |
760 // Check whether it is interesting as a nested-name-specifier. | |
761 if (AllowNestedNameSpecifiers && SemaRef.getLangOpts().CPlusPlus && | |
762 IsNestedNameSpecifier(ND) && | |
763 (Filter != &ResultBuilder::IsMember || | |
764 (isa<CXXRecordDecl>(ND) && | |
765 cast<CXXRecordDecl>(ND)->isInjectedClassName()))) { | |
766 AsNestedNameSpecifier = true; | |
767 return true; | |
768 } | |
769 | |
770 return false; | |
771 } | |
772 // ... then it must be interesting! | |
773 return true; | |
774 } | |
775 | |
776 bool ResultBuilder::CheckHiddenResult(Result &R, DeclContext *CurContext, | |
777 const NamedDecl *Hiding) { | |
778 // In C, there is no way to refer to a hidden name. | |
779 // FIXME: This isn't true; we can find a tag name hidden by an ordinary | |
780 // name if we introduce the tag type. | |
781 if (!SemaRef.getLangOpts().CPlusPlus) | |
782 return true; | |
783 | |
784 const DeclContext *HiddenCtx = | |
785 R.Declaration->getDeclContext()->getRedeclContext(); | |
786 | |
787 // There is no way to qualify a name declared in a function or method. | |
788 if (HiddenCtx->isFunctionOrMethod()) | |
789 return true; | |
790 | |
791 if (HiddenCtx == Hiding->getDeclContext()->getRedeclContext()) | |
792 return true; | |
793 | |
794 // We can refer to the result with the appropriate qualification. Do it. | |
795 R.Hidden = true; | |
796 R.QualifierIsInformative = false; | |
797 | |
798 if (!R.Qualifier) | |
799 R.Qualifier = getRequiredQualification(SemaRef.Context, CurContext, | |
800 R.Declaration->getDeclContext()); | |
801 return false; | |
802 } | |
803 | |
804 /// A simplified classification of types used to determine whether two | |
805 /// types are "similar enough" when adjusting priorities. | |
806 SimplifiedTypeClass clang::getSimplifiedTypeClass(CanQualType T) { | |
807 switch (T->getTypeClass()) { | |
808 case Type::Builtin: | |
809 switch (cast<BuiltinType>(T)->getKind()) { | |
810 case BuiltinType::Void: | |
811 return STC_Void; | |
812 | |
813 case BuiltinType::NullPtr: | |
814 return STC_Pointer; | |
815 | |
816 case BuiltinType::Overload: | |
817 case BuiltinType::Dependent: | |
818 return STC_Other; | |
819 | |
820 case BuiltinType::ObjCId: | |
821 case BuiltinType::ObjCClass: | |
822 case BuiltinType::ObjCSel: | |
823 return STC_ObjectiveC; | |
824 | |
825 default: | |
826 return STC_Arithmetic; | |
827 } | |
828 | |
829 case Type::Complex: | |
830 return STC_Arithmetic; | |
831 | |
832 case Type::Pointer: | |
833 return STC_Pointer; | |
834 | |
835 case Type::BlockPointer: | |
836 return STC_Block; | |
837 | |
838 case Type::LValueReference: | |
839 case Type::RValueReference: | |
840 return getSimplifiedTypeClass(T->getAs<ReferenceType>()->getPointeeType()); | |
841 | |
842 case Type::ConstantArray: | |
843 case Type::IncompleteArray: | |
844 case Type::VariableArray: | |
845 case Type::DependentSizedArray: | |
846 return STC_Array; | |
847 | |
848 case Type::DependentSizedExtVector: | |
849 case Type::Vector: | |
850 case Type::ExtVector: | |
851 return STC_Arithmetic; | |
852 | |
853 case Type::FunctionProto: | |
854 case Type::FunctionNoProto: | |
855 return STC_Function; | |
856 | |
857 case Type::Record: | |
858 return STC_Record; | |
859 | |
860 case Type::Enum: | |
861 return STC_Arithmetic; | |
862 | |
863 case Type::ObjCObject: | |
864 case Type::ObjCInterface: | |
865 case Type::ObjCObjectPointer: | |
866 return STC_ObjectiveC; | |
867 | |
868 default: | |
869 return STC_Other; | |
870 } | |
871 } | |
872 | |
873 /// Get the type that a given expression will have if this declaration | |
874 /// is used as an expression in its "typical" code-completion form. | |
875 QualType clang::getDeclUsageType(ASTContext &C, const NamedDecl *ND) { | |
876 ND = ND->getUnderlyingDecl(); | |
877 | |
878 if (const auto *Type = dyn_cast<TypeDecl>(ND)) | |
879 return C.getTypeDeclType(Type); | |
880 if (const auto *Iface = dyn_cast<ObjCInterfaceDecl>(ND)) | |
881 return C.getObjCInterfaceType(Iface); | |
882 | |
883 QualType T; | |
884 if (const FunctionDecl *Function = ND->getAsFunction()) | |
885 T = Function->getCallResultType(); | |
886 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) | |
887 T = Method->getSendResultType(); | |
888 else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) | |
889 T = C.getTypeDeclType(cast<EnumDecl>(Enumerator->getDeclContext())); | |
890 else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) | |
891 T = Property->getType(); | |
892 else if (const auto *Value = dyn_cast<ValueDecl>(ND)) | |
893 T = Value->getType(); | |
894 | |
895 if (T.isNull()) | |
896 return QualType(); | |
897 | |
898 // Dig through references, function pointers, and block pointers to | |
899 // get down to the likely type of an expression when the entity is | |
900 // used. | |
901 do { | |
902 if (const auto *Ref = T->getAs<ReferenceType>()) { | |
903 T = Ref->getPointeeType(); | |
904 continue; | |
905 } | |
906 | |
907 if (const auto *Pointer = T->getAs<PointerType>()) { | |
908 if (Pointer->getPointeeType()->isFunctionType()) { | |
909 T = Pointer->getPointeeType(); | |
910 continue; | |
911 } | |
912 | |
913 break; | |
914 } | |
915 | |
916 if (const auto *Block = T->getAs<BlockPointerType>()) { | |
917 T = Block->getPointeeType(); | |
918 continue; | |
919 } | |
920 | |
921 if (const auto *Function = T->getAs<FunctionType>()) { | |
922 T = Function->getReturnType(); | |
923 continue; | |
924 } | |
925 | |
926 break; | |
927 } while (true); | |
928 | |
929 return T; | |
930 } | |
931 | |
932 unsigned ResultBuilder::getBasePriority(const NamedDecl *ND) { | |
933 if (!ND) | |
934 return CCP_Unlikely; | |
935 | |
936 // Context-based decisions. | |
937 const DeclContext *LexicalDC = ND->getLexicalDeclContext(); | |
938 if (LexicalDC->isFunctionOrMethod()) { | |
939 // _cmd is relatively rare | |
940 if (const auto *ImplicitParam = dyn_cast<ImplicitParamDecl>(ND)) | |
941 if (ImplicitParam->getIdentifier() && | |
942 ImplicitParam->getIdentifier()->isStr("_cmd")) | |
943 return CCP_ObjC_cmd; | |
944 | |
945 return CCP_LocalDeclaration; | |
946 } | |
947 | |
948 const DeclContext *DC = ND->getDeclContext()->getRedeclContext(); | |
949 if (DC->isRecord() || isa<ObjCContainerDecl>(DC)) { | |
950 // Explicit destructor calls are very rare. | |
951 if (isa<CXXDestructorDecl>(ND)) | |
952 return CCP_Unlikely; | |
953 // Explicit operator and conversion function calls are also very rare. | |
954 auto DeclNameKind = ND->getDeclName().getNameKind(); | |
955 if (DeclNameKind == DeclarationName::CXXOperatorName || | |
956 DeclNameKind == DeclarationName::CXXLiteralOperatorName || | |
957 DeclNameKind == DeclarationName::CXXConversionFunctionName) | |
958 return CCP_Unlikely; | |
959 return CCP_MemberDeclaration; | |
960 } | |
961 | |
962 // Content-based decisions. | |
963 if (isa<EnumConstantDecl>(ND)) | |
964 return CCP_Constant; | |
965 | |
966 // Use CCP_Type for type declarations unless we're in a statement, Objective-C | |
967 // message receiver, or parenthesized expression context. There, it's as | |
968 // likely that the user will want to write a type as other declarations. | |
969 if ((isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) && | |
970 !(CompletionContext.getKind() == CodeCompletionContext::CCC_Statement || | |
971 CompletionContext.getKind() == | |
972 CodeCompletionContext::CCC_ObjCMessageReceiver || | |
973 CompletionContext.getKind() == | |
974 CodeCompletionContext::CCC_ParenthesizedExpression)) | |
975 return CCP_Type; | |
976 | |
977 return CCP_Declaration; | |
978 } | |
979 | |
980 void ResultBuilder::AdjustResultPriorityForDecl(Result &R) { | |
981 // If this is an Objective-C method declaration whose selector matches our | |
982 // preferred selector, give it a priority boost. | |
983 if (!PreferredSelector.isNull()) | |
984 if (const auto *Method = dyn_cast<ObjCMethodDecl>(R.Declaration)) | |
985 if (PreferredSelector == Method->getSelector()) | |
986 R.Priority += CCD_SelectorMatch; | |
987 | |
988 // If we have a preferred type, adjust the priority for results with exactly- | |
989 // matching or nearly-matching types. | |
990 if (!PreferredType.isNull()) { | |
991 QualType T = getDeclUsageType(SemaRef.Context, R.Declaration); | |
992 if (!T.isNull()) { | |
993 CanQualType TC = SemaRef.Context.getCanonicalType(T); | |
994 // Check for exactly-matching types (modulo qualifiers). | |
995 if (SemaRef.Context.hasSameUnqualifiedType(PreferredType, TC)) | |
996 R.Priority /= CCF_ExactTypeMatch; | |
997 // Check for nearly-matching types, based on classification of each. | |
998 else if ((getSimplifiedTypeClass(PreferredType) == | |
999 getSimplifiedTypeClass(TC)) && | |
1000 !(PreferredType->isEnumeralType() && TC->isEnumeralType())) | |
1001 R.Priority /= CCF_SimilarTypeMatch; | |
1002 } | |
1003 } | |
1004 } | |
1005 | |
1006 static DeclContext::lookup_result getConstructors(ASTContext &Context, | |
1007 const CXXRecordDecl *Record) { | |
1008 QualType RecordTy = Context.getTypeDeclType(Record); | |
1009 DeclarationName ConstructorName = | |
1010 Context.DeclarationNames.getCXXConstructorName( | |
1011 Context.getCanonicalType(RecordTy)); | |
1012 return Record->lookup(ConstructorName); | |
1013 } | |
1014 | |
1015 void ResultBuilder::MaybeAddConstructorResults(Result R) { | |
1016 if (!SemaRef.getLangOpts().CPlusPlus || !R.Declaration || | |
1017 !CompletionContext.wantConstructorResults()) | |
1018 return; | |
1019 | |
1020 const NamedDecl *D = R.Declaration; | |
1021 const CXXRecordDecl *Record = nullptr; | |
1022 if (const ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(D)) | |
1023 Record = ClassTemplate->getTemplatedDecl(); | |
1024 else if ((Record = dyn_cast<CXXRecordDecl>(D))) { | |
1025 // Skip specializations and partial specializations. | |
1026 if (isa<ClassTemplateSpecializationDecl>(Record)) | |
1027 return; | |
1028 } else { | |
1029 // There are no constructors here. | |
1030 return; | |
1031 } | |
1032 | |
1033 Record = Record->getDefinition(); | |
1034 if (!Record) | |
1035 return; | |
1036 | |
1037 for (NamedDecl *Ctor : getConstructors(SemaRef.Context, Record)) { | |
1038 R.Declaration = Ctor; | |
1039 R.CursorKind = getCursorKindForDecl(R.Declaration); | |
1040 Results.push_back(R); | |
1041 } | |
1042 } | |
1043 | |
1044 static bool isConstructor(const Decl *ND) { | |
1045 if (const auto *Tmpl = dyn_cast<FunctionTemplateDecl>(ND)) | |
1046 ND = Tmpl->getTemplatedDecl(); | |
1047 return isa<CXXConstructorDecl>(ND); | |
1048 } | |
1049 | |
1050 void ResultBuilder::MaybeAddResult(Result R, DeclContext *CurContext) { | |
1051 assert(!ShadowMaps.empty() && "Must enter into a results scope"); | |
1052 | |
1053 if (R.Kind != Result::RK_Declaration) { | |
1054 // For non-declaration results, just add the result. | |
1055 Results.push_back(R); | |
1056 return; | |
1057 } | |
1058 | |
1059 // Look through using declarations. | |
1060 if (const UsingShadowDecl *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { | |
1061 CodeCompletionResult Result(Using->getTargetDecl(), | |
1062 getBasePriority(Using->getTargetDecl()), | |
1063 R.Qualifier); | |
1064 Result.ShadowDecl = Using; | |
1065 MaybeAddResult(Result, CurContext); | |
1066 return; | |
1067 } | |
1068 | |
1069 const Decl *CanonDecl = R.Declaration->getCanonicalDecl(); | |
1070 unsigned IDNS = CanonDecl->getIdentifierNamespace(); | |
1071 | |
1072 bool AsNestedNameSpecifier = false; | |
1073 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) | |
1074 return; | |
1075 | |
1076 // C++ constructors are never found by name lookup. | |
1077 if (isConstructor(R.Declaration)) | |
1078 return; | |
1079 | |
1080 ShadowMap &SMap = ShadowMaps.back(); | |
1081 ShadowMapEntry::iterator I, IEnd; | |
1082 ShadowMap::iterator NamePos = SMap.find(R.Declaration->getDeclName()); | |
1083 if (NamePos != SMap.end()) { | |
1084 I = NamePos->second.begin(); | |
1085 IEnd = NamePos->second.end(); | |
1086 } | |
1087 | |
1088 for (; I != IEnd; ++I) { | |
1089 const NamedDecl *ND = I->first; | |
1090 unsigned Index = I->second; | |
1091 if (ND->getCanonicalDecl() == CanonDecl) { | |
1092 // This is a redeclaration. Always pick the newer declaration. | |
1093 Results[Index].Declaration = R.Declaration; | |
1094 | |
1095 // We're done. | |
1096 return; | |
1097 } | |
1098 } | |
1099 | |
1100 // This is a new declaration in this scope. However, check whether this | |
1101 // declaration name is hidden by a similarly-named declaration in an outer | |
1102 // scope. | |
1103 std::list<ShadowMap>::iterator SM, SMEnd = ShadowMaps.end(); | |
1104 --SMEnd; | |
1105 for (SM = ShadowMaps.begin(); SM != SMEnd; ++SM) { | |
1106 ShadowMapEntry::iterator I, IEnd; | |
1107 ShadowMap::iterator NamePos = SM->find(R.Declaration->getDeclName()); | |
1108 if (NamePos != SM->end()) { | |
1109 I = NamePos->second.begin(); | |
1110 IEnd = NamePos->second.end(); | |
1111 } | |
1112 for (; I != IEnd; ++I) { | |
1113 // A tag declaration does not hide a non-tag declaration. | |
1114 if (I->first->hasTagIdentifierNamespace() && | |
1115 (IDNS & (Decl::IDNS_Member | Decl::IDNS_Ordinary | | |
1116 Decl::IDNS_LocalExtern | Decl::IDNS_ObjCProtocol))) | |
1117 continue; | |
1118 | |
1119 // Protocols are in distinct namespaces from everything else. | |
1120 if (((I->first->getIdentifierNamespace() & Decl::IDNS_ObjCProtocol) || | |
1121 (IDNS & Decl::IDNS_ObjCProtocol)) && | |
1122 I->first->getIdentifierNamespace() != IDNS) | |
1123 continue; | |
1124 | |
1125 // The newly-added result is hidden by an entry in the shadow map. | |
1126 if (CheckHiddenResult(R, CurContext, I->first)) | |
1127 return; | |
1128 | |
1129 break; | |
1130 } | |
1131 } | |
1132 | |
1133 // Make sure that any given declaration only shows up in the result set once. | |
1134 if (!AllDeclsFound.insert(CanonDecl).second) | |
1135 return; | |
1136 | |
1137 // If the filter is for nested-name-specifiers, then this result starts a | |
1138 // nested-name-specifier. | |
1139 if (AsNestedNameSpecifier) { | |
1140 R.StartsNestedNameSpecifier = true; | |
1141 R.Priority = CCP_NestedNameSpecifier; | |
1142 } else | |
1143 AdjustResultPriorityForDecl(R); | |
1144 | |
1145 // If this result is supposed to have an informative qualifier, add one. | |
1146 if (R.QualifierIsInformative && !R.Qualifier && | |
1147 !R.StartsNestedNameSpecifier) { | |
1148 const DeclContext *Ctx = R.Declaration->getDeclContext(); | |
1149 if (const NamespaceDecl *Namespace = dyn_cast<NamespaceDecl>(Ctx)) | |
1150 R.Qualifier = | |
1151 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); | |
1152 else if (const TagDecl *Tag = dyn_cast<TagDecl>(Ctx)) | |
1153 R.Qualifier = NestedNameSpecifier::Create( | |
1154 SemaRef.Context, nullptr, false, | |
1155 SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); | |
1156 else | |
1157 R.QualifierIsInformative = false; | |
1158 } | |
1159 | |
1160 // Insert this result into the set of results and into the current shadow | |
1161 // map. | |
1162 SMap[R.Declaration->getDeclName()].Add(R.Declaration, Results.size()); | |
1163 Results.push_back(R); | |
1164 | |
1165 if (!AsNestedNameSpecifier) | |
1166 MaybeAddConstructorResults(R); | |
1167 } | |
1168 | |
1169 static void setInBaseClass(ResultBuilder::Result &R) { | |
1170 R.Priority += CCD_InBaseClass; | |
1171 R.InBaseClass = true; | |
1172 } | |
1173 | |
1174 enum class OverloadCompare { BothViable, Dominates, Dominated }; | |
1175 // Will Candidate ever be called on the object, when overloaded with Incumbent? | |
1176 // Returns Dominates if Candidate is always called, Dominated if Incumbent is | |
1177 // always called, BothViable if either may be called dependending on arguments. | |
1178 // Precondition: must actually be overloads! | |
1179 static OverloadCompare compareOverloads(const CXXMethodDecl &Candidate, | |
1180 const CXXMethodDecl &Incumbent, | |
1181 const Qualifiers &ObjectQuals, | |
1182 ExprValueKind ObjectKind) { | |
1183 // Base/derived shadowing is handled elsewhere. | |
1184 if (Candidate.getDeclContext() != Incumbent.getDeclContext()) | |
1185 return OverloadCompare::BothViable; | |
1186 if (Candidate.isVariadic() != Incumbent.isVariadic() || | |
1187 Candidate.getNumParams() != Incumbent.getNumParams() || | |
1188 Candidate.getMinRequiredArguments() != | |
1189 Incumbent.getMinRequiredArguments()) | |
1190 return OverloadCompare::BothViable; | |
1191 for (unsigned I = 0, E = Candidate.getNumParams(); I != E; ++I) | |
1192 if (Candidate.parameters()[I]->getType().getCanonicalType() != | |
1193 Incumbent.parameters()[I]->getType().getCanonicalType()) | |
1194 return OverloadCompare::BothViable; | |
1195 if (!llvm::empty(Candidate.specific_attrs<EnableIfAttr>()) || | |
1196 !llvm::empty(Incumbent.specific_attrs<EnableIfAttr>())) | |
1197 return OverloadCompare::BothViable; | |
1198 // At this point, we know calls can't pick one or the other based on | |
1199 // arguments, so one of the two must win. (Or both fail, handled elsewhere). | |
1200 RefQualifierKind CandidateRef = Candidate.getRefQualifier(); | |
1201 RefQualifierKind IncumbentRef = Incumbent.getRefQualifier(); | |
1202 if (CandidateRef != IncumbentRef) { | |
1203 // If the object kind is LValue/RValue, there's one acceptable ref-qualifier | |
1204 // and it can't be mixed with ref-unqualified overloads (in valid code). | |
1205 | |
1206 // For xvalue objects, we prefer the rvalue overload even if we have to | |
1207 // add qualifiers (which is rare, because const&& is rare). | |
1208 if (ObjectKind == clang::VK_XValue) | |
1209 return CandidateRef == RQ_RValue ? OverloadCompare::Dominates | |
1210 : OverloadCompare::Dominated; | |
1211 } | |
1212 // Now the ref qualifiers are the same (or we're in some invalid state). | |
1213 // So make some decision based on the qualifiers. | |
1214 Qualifiers CandidateQual = Candidate.getMethodQualifiers(); | |
1215 Qualifiers IncumbentQual = Incumbent.getMethodQualifiers(); | |
1216 bool CandidateSuperset = CandidateQual.compatiblyIncludes(IncumbentQual); | |
1217 bool IncumbentSuperset = IncumbentQual.compatiblyIncludes(CandidateQual); | |
1218 if (CandidateSuperset == IncumbentSuperset) | |
1219 return OverloadCompare::BothViable; | |
1220 return IncumbentSuperset ? OverloadCompare::Dominates | |
1221 : OverloadCompare::Dominated; | |
1222 } | |
1223 | |
1224 void ResultBuilder::AddResult(Result R, DeclContext *CurContext, | |
1225 NamedDecl *Hiding, bool InBaseClass = false) { | |
1226 if (R.Kind != Result::RK_Declaration) { | |
1227 // For non-declaration results, just add the result. | |
1228 Results.push_back(R); | |
1229 return; | |
1230 } | |
1231 | |
1232 // Look through using declarations. | |
1233 if (const auto *Using = dyn_cast<UsingShadowDecl>(R.Declaration)) { | |
1234 CodeCompletionResult Result(Using->getTargetDecl(), | |
1235 getBasePriority(Using->getTargetDecl()), | |
1236 R.Qualifier); | |
1237 Result.ShadowDecl = Using; | |
1238 AddResult(Result, CurContext, Hiding); | |
1239 return; | |
1240 } | |
1241 | |
1242 bool AsNestedNameSpecifier = false; | |
1243 if (!isInterestingDecl(R.Declaration, AsNestedNameSpecifier)) | |
1244 return; | |
1245 | |
1246 // C++ constructors are never found by name lookup. | |
1247 if (isConstructor(R.Declaration)) | |
1248 return; | |
1249 | |
1250 if (Hiding && CheckHiddenResult(R, CurContext, Hiding)) | |
1251 return; | |
1252 | |
1253 // Make sure that any given declaration only shows up in the result set once. | |
1254 if (!AllDeclsFound.insert(R.Declaration->getCanonicalDecl()).second) | |
1255 return; | |
1256 | |
1257 // If the filter is for nested-name-specifiers, then this result starts a | |
1258 // nested-name-specifier. | |
1259 if (AsNestedNameSpecifier) { | |
1260 R.StartsNestedNameSpecifier = true; | |
1261 R.Priority = CCP_NestedNameSpecifier; | |
1262 } else if (Filter == &ResultBuilder::IsMember && !R.Qualifier && | |
1263 InBaseClass && | |
1264 isa<CXXRecordDecl>( | |
1265 R.Declaration->getDeclContext()->getRedeclContext())) | |
1266 R.QualifierIsInformative = true; | |
1267 | |
1268 // If this result is supposed to have an informative qualifier, add one. | |
1269 if (R.QualifierIsInformative && !R.Qualifier && | |
1270 !R.StartsNestedNameSpecifier) { | |
1271 const DeclContext *Ctx = R.Declaration->getDeclContext(); | |
1272 if (const auto *Namespace = dyn_cast<NamespaceDecl>(Ctx)) | |
1273 R.Qualifier = | |
1274 NestedNameSpecifier::Create(SemaRef.Context, nullptr, Namespace); | |
1275 else if (const auto *Tag = dyn_cast<TagDecl>(Ctx)) | |
1276 R.Qualifier = NestedNameSpecifier::Create( | |
1277 SemaRef.Context, nullptr, false, | |
1278 SemaRef.Context.getTypeDeclType(Tag).getTypePtr()); | |
1279 else | |
1280 R.QualifierIsInformative = false; | |
1281 } | |
1282 | |
1283 // Adjust the priority if this result comes from a base class. | |
1284 if (InBaseClass) | |
1285 setInBaseClass(R); | |
1286 | |
1287 AdjustResultPriorityForDecl(R); | |
1288 | |
1289 if (HasObjectTypeQualifiers) | |
1290 if (const auto *Method = dyn_cast<CXXMethodDecl>(R.Declaration)) | |
1291 if (Method->isInstance()) { | |
1292 Qualifiers MethodQuals = Method->getMethodQualifiers(); | |
1293 if (ObjectTypeQualifiers == MethodQuals) | |
1294 R.Priority += CCD_ObjectQualifierMatch; | |
1295 else if (ObjectTypeQualifiers - MethodQuals) { | |
1296 // The method cannot be invoked, because doing so would drop | |
1297 // qualifiers. | |
1298 return; | |
1299 } | |
1300 // Detect cases where a ref-qualified method cannot be invoked. | |
1301 switch (Method->getRefQualifier()) { | |
1302 case RQ_LValue: | |
1303 if (ObjectKind != VK_LValue && !MethodQuals.hasConst()) | |
1304 return; | |
1305 break; | |
1306 case RQ_RValue: | |
1307 if (ObjectKind == VK_LValue) | |
1308 return; | |
1309 break; | |
1310 case RQ_None: | |
1311 break; | |
1312 } | |
1313 | |
1314 /// Check whether this dominates another overloaded method, which should | |
1315 /// be suppressed (or vice versa). | |
1316 /// Motivating case is const_iterator begin() const vs iterator begin(). | |
1317 auto &OverloadSet = OverloadMap[std::make_pair( | |
1318 CurContext, Method->getDeclName().getAsOpaqueInteger())]; | |
1319 for (const DeclIndexPair Entry : OverloadSet) { | |
1320 Result &Incumbent = Results[Entry.second]; | |
1321 switch (compareOverloads(*Method, | |
1322 *cast<CXXMethodDecl>(Incumbent.Declaration), | |
1323 ObjectTypeQualifiers, ObjectKind)) { | |
1324 case OverloadCompare::Dominates: | |
1325 // Replace the dominated overload with this one. | |
1326 // FIXME: if the overload dominates multiple incumbents then we | |
1327 // should remove all. But two overloads is by far the common case. | |
1328 Incumbent = std::move(R); | |
1329 return; | |
1330 case OverloadCompare::Dominated: | |
1331 // This overload can't be called, drop it. | |
1332 return; | |
1333 case OverloadCompare::BothViable: | |
1334 break; | |
1335 } | |
1336 } | |
1337 OverloadSet.Add(Method, Results.size()); | |
1338 } | |
1339 | |
1340 // Insert this result into the set of results. | |
1341 Results.push_back(R); | |
1342 | |
1343 if (!AsNestedNameSpecifier) | |
1344 MaybeAddConstructorResults(R); | |
1345 } | |
1346 | |
1347 void ResultBuilder::AddResult(Result R) { | |
1348 assert(R.Kind != Result::RK_Declaration && | |
1349 "Declaration results need more context"); | |
1350 Results.push_back(R); | |
1351 } | |
1352 | |
1353 /// Enter into a new scope. | |
1354 void ResultBuilder::EnterNewScope() { ShadowMaps.emplace_back(); } | |
1355 | |
1356 /// Exit from the current scope. | |
1357 void ResultBuilder::ExitScope() { | |
1358 ShadowMaps.pop_back(); | |
1359 } | |
1360 | |
1361 /// Determines whether this given declaration will be found by | |
1362 /// ordinary name lookup. | |
1363 bool ResultBuilder::IsOrdinaryName(const NamedDecl *ND) const { | |
1364 ND = ND->getUnderlyingDecl(); | |
1365 | |
1366 // If name lookup finds a local extern declaration, then we are in a | |
1367 // context where it behaves like an ordinary name. | |
1368 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; | |
1369 if (SemaRef.getLangOpts().CPlusPlus) | |
1370 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; | |
1371 else if (SemaRef.getLangOpts().ObjC) { | |
1372 if (isa<ObjCIvarDecl>(ND)) | |
1373 return true; | |
1374 } | |
1375 | |
1376 return ND->getIdentifierNamespace() & IDNS; | |
1377 } | |
1378 | |
1379 /// Determines whether this given declaration will be found by | |
1380 /// ordinary name lookup but is not a type name. | |
1381 bool ResultBuilder::IsOrdinaryNonTypeName(const NamedDecl *ND) const { | |
1382 ND = ND->getUnderlyingDecl(); | |
1383 if (isa<TypeDecl>(ND)) | |
1384 return false; | |
1385 // Objective-C interfaces names are not filtered by this method because they | |
1386 // can be used in a class property expression. We can still filter out | |
1387 // @class declarations though. | |
1388 if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND)) { | |
1389 if (!ID->getDefinition()) | |
1390 return false; | |
1391 } | |
1392 | |
1393 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; | |
1394 if (SemaRef.getLangOpts().CPlusPlus) | |
1395 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace | Decl::IDNS_Member; | |
1396 else if (SemaRef.getLangOpts().ObjC) { | |
1397 if (isa<ObjCIvarDecl>(ND)) | |
1398 return true; | |
1399 } | |
1400 | |
1401 return ND->getIdentifierNamespace() & IDNS; | |
1402 } | |
1403 | |
1404 bool ResultBuilder::IsIntegralConstantValue(const NamedDecl *ND) const { | |
1405 if (!IsOrdinaryNonTypeName(ND)) | |
1406 return 0; | |
1407 | |
1408 if (const auto *VD = dyn_cast<ValueDecl>(ND->getUnderlyingDecl())) | |
1409 if (VD->getType()->isIntegralOrEnumerationType()) | |
1410 return true; | |
1411 | |
1412 return false; | |
1413 } | |
1414 | |
1415 /// Determines whether this given declaration will be found by | |
1416 /// ordinary name lookup. | |
1417 bool ResultBuilder::IsOrdinaryNonValueName(const NamedDecl *ND) const { | |
1418 ND = ND->getUnderlyingDecl(); | |
1419 | |
1420 unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_LocalExtern; | |
1421 if (SemaRef.getLangOpts().CPlusPlus) | |
1422 IDNS |= Decl::IDNS_Tag | Decl::IDNS_Namespace; | |
1423 | |
1424 return (ND->getIdentifierNamespace() & IDNS) && !isa<ValueDecl>(ND) && | |
1425 !isa<FunctionTemplateDecl>(ND) && !isa<ObjCPropertyDecl>(ND); | |
1426 } | |
1427 | |
1428 /// Determines whether the given declaration is suitable as the | |
1429 /// start of a C++ nested-name-specifier, e.g., a class or namespace. | |
1430 bool ResultBuilder::IsNestedNameSpecifier(const NamedDecl *ND) const { | |
1431 // Allow us to find class templates, too. | |
1432 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) | |
1433 ND = ClassTemplate->getTemplatedDecl(); | |
1434 | |
1435 return SemaRef.isAcceptableNestedNameSpecifier(ND); | |
1436 } | |
1437 | |
1438 /// Determines whether the given declaration is an enumeration. | |
1439 bool ResultBuilder::IsEnum(const NamedDecl *ND) const { | |
1440 return isa<EnumDecl>(ND); | |
1441 } | |
1442 | |
1443 /// Determines whether the given declaration is a class or struct. | |
1444 bool ResultBuilder::IsClassOrStruct(const NamedDecl *ND) const { | |
1445 // Allow us to find class templates, too. | |
1446 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) | |
1447 ND = ClassTemplate->getTemplatedDecl(); | |
1448 | |
1449 // For purposes of this check, interfaces match too. | |
1450 if (const auto *RD = dyn_cast<RecordDecl>(ND)) | |
1451 return RD->getTagKind() == TTK_Class || RD->getTagKind() == TTK_Struct || | |
1452 RD->getTagKind() == TTK_Interface; | |
1453 | |
1454 return false; | |
1455 } | |
1456 | |
1457 /// Determines whether the given declaration is a union. | |
1458 bool ResultBuilder::IsUnion(const NamedDecl *ND) const { | |
1459 // Allow us to find class templates, too. | |
1460 if (const auto *ClassTemplate = dyn_cast<ClassTemplateDecl>(ND)) | |
1461 ND = ClassTemplate->getTemplatedDecl(); | |
1462 | |
1463 if (const auto *RD = dyn_cast<RecordDecl>(ND)) | |
1464 return RD->getTagKind() == TTK_Union; | |
1465 | |
1466 return false; | |
1467 } | |
1468 | |
1469 /// Determines whether the given declaration is a namespace. | |
1470 bool ResultBuilder::IsNamespace(const NamedDecl *ND) const { | |
1471 return isa<NamespaceDecl>(ND); | |
1472 } | |
1473 | |
1474 /// Determines whether the given declaration is a namespace or | |
1475 /// namespace alias. | |
1476 bool ResultBuilder::IsNamespaceOrAlias(const NamedDecl *ND) const { | |
1477 return isa<NamespaceDecl>(ND->getUnderlyingDecl()); | |
1478 } | |
1479 | |
1480 /// Determines whether the given declaration is a type. | |
1481 bool ResultBuilder::IsType(const NamedDecl *ND) const { | |
1482 ND = ND->getUnderlyingDecl(); | |
1483 return isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); | |
1484 } | |
1485 | |
1486 /// Determines which members of a class should be visible via | |
1487 /// "." or "->". Only value declarations, nested name specifiers, and | |
1488 /// using declarations thereof should show up. | |
1489 bool ResultBuilder::IsMember(const NamedDecl *ND) const { | |
1490 ND = ND->getUnderlyingDecl(); | |
1491 return isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND) || | |
1492 isa<ObjCPropertyDecl>(ND); | |
1493 } | |
1494 | |
1495 static bool isObjCReceiverType(ASTContext &C, QualType T) { | |
1496 T = C.getCanonicalType(T); | |
1497 switch (T->getTypeClass()) { | |
1498 case Type::ObjCObject: | |
1499 case Type::ObjCInterface: | |
1500 case Type::ObjCObjectPointer: | |
1501 return true; | |
1502 | |
1503 case Type::Builtin: | |
1504 switch (cast<BuiltinType>(T)->getKind()) { | |
1505 case BuiltinType::ObjCId: | |
1506 case BuiltinType::ObjCClass: | |
1507 case BuiltinType::ObjCSel: | |
1508 return true; | |
1509 | |
1510 default: | |
1511 break; | |
1512 } | |
1513 return false; | |
1514 | |
1515 default: | |
1516 break; | |
1517 } | |
1518 | |
1519 if (!C.getLangOpts().CPlusPlus) | |
1520 return false; | |
1521 | |
1522 // FIXME: We could perform more analysis here to determine whether a | |
1523 // particular class type has any conversions to Objective-C types. For now, | |
1524 // just accept all class types. | |
1525 return T->isDependentType() || T->isRecordType(); | |
1526 } | |
1527 | |
1528 bool ResultBuilder::IsObjCMessageReceiver(const NamedDecl *ND) const { | |
1529 QualType T = getDeclUsageType(SemaRef.Context, ND); | |
1530 if (T.isNull()) | |
1531 return false; | |
1532 | |
1533 T = SemaRef.Context.getBaseElementType(T); | |
1534 return isObjCReceiverType(SemaRef.Context, T); | |
1535 } | |
1536 | |
1537 bool ResultBuilder::IsObjCMessageReceiverOrLambdaCapture( | |
1538 const NamedDecl *ND) const { | |
1539 if (IsObjCMessageReceiver(ND)) | |
1540 return true; | |
1541 | |
1542 const auto *Var = dyn_cast<VarDecl>(ND); | |
1543 if (!Var) | |
1544 return false; | |
1545 | |
1546 return Var->hasLocalStorage() && !Var->hasAttr<BlocksAttr>(); | |
1547 } | |
1548 | |
1549 bool ResultBuilder::IsObjCCollection(const NamedDecl *ND) const { | |
1550 if ((SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryName(ND)) || | |
1551 (!SemaRef.getLangOpts().CPlusPlus && !IsOrdinaryNonTypeName(ND))) | |
1552 return false; | |
1553 | |
1554 QualType T = getDeclUsageType(SemaRef.Context, ND); | |
1555 if (T.isNull()) | |
1556 return false; | |
1557 | |
1558 T = SemaRef.Context.getBaseElementType(T); | |
1559 return T->isObjCObjectType() || T->isObjCObjectPointerType() || | |
1560 T->isObjCIdType() || | |
1561 (SemaRef.getLangOpts().CPlusPlus && T->isRecordType()); | |
1562 } | |
1563 | |
1564 bool ResultBuilder::IsImpossibleToSatisfy(const NamedDecl *ND) const { | |
1565 return false; | |
1566 } | |
1567 | |
1568 /// Determines whether the given declaration is an Objective-C | |
1569 /// instance variable. | |
1570 bool ResultBuilder::IsObjCIvar(const NamedDecl *ND) const { | |
1571 return isa<ObjCIvarDecl>(ND); | |
1572 } | |
1573 | |
1574 namespace { | |
1575 | |
1576 /// Visible declaration consumer that adds a code-completion result | |
1577 /// for each visible declaration. | |
1578 class CodeCompletionDeclConsumer : public VisibleDeclConsumer { | |
1579 ResultBuilder &Results; | |
1580 DeclContext *InitialLookupCtx; | |
1581 // NamingClass and BaseType are used for access-checking. See | |
1582 // Sema::IsSimplyAccessible for details. | |
1583 CXXRecordDecl *NamingClass; | |
1584 QualType BaseType; | |
1585 std::vector<FixItHint> FixIts; | |
1586 | |
1587 public: | |
1588 CodeCompletionDeclConsumer( | |
1589 ResultBuilder &Results, DeclContext *InitialLookupCtx, | |
1590 QualType BaseType = QualType(), | |
1591 std::vector<FixItHint> FixIts = std::vector<FixItHint>()) | |
1592 : Results(Results), InitialLookupCtx(InitialLookupCtx), | |
1593 FixIts(std::move(FixIts)) { | |
1594 NamingClass = llvm::dyn_cast<CXXRecordDecl>(InitialLookupCtx); | |
1595 // If BaseType was not provided explicitly, emulate implicit 'this->'. | |
1596 if (BaseType.isNull()) { | |
1597 auto ThisType = Results.getSema().getCurrentThisType(); | |
1598 if (!ThisType.isNull()) { | |
1599 assert(ThisType->isPointerType()); | |
1600 BaseType = ThisType->getPointeeType(); | |
1601 if (!NamingClass) | |
1602 NamingClass = BaseType->getAsCXXRecordDecl(); | |
1603 } | |
1604 } | |
1605 this->BaseType = BaseType; | |
1606 } | |
1607 | |
1608 void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, | |
1609 bool InBaseClass) override { | |
1610 ResultBuilder::Result Result(ND, Results.getBasePriority(ND), nullptr, | |
1611 false, IsAccessible(ND, Ctx), FixIts); | |
1612 Results.AddResult(Result, InitialLookupCtx, Hiding, InBaseClass); | |
1613 } | |
1614 | |
1615 void EnteredContext(DeclContext *Ctx) override { | |
1616 Results.addVisitedContext(Ctx); | |
1617 } | |
1618 | |
1619 private: | |
1620 bool IsAccessible(NamedDecl *ND, DeclContext *Ctx) { | |
1621 // Naming class to use for access check. In most cases it was provided | |
1622 // explicitly (e.g. member access (lhs.foo) or qualified lookup (X::)), | |
1623 // for unqualified lookup we fallback to the \p Ctx in which we found the | |
1624 // member. | |
1625 auto *NamingClass = this->NamingClass; | |
1626 QualType BaseType = this->BaseType; | |
1627 if (auto *Cls = llvm::dyn_cast_or_null<CXXRecordDecl>(Ctx)) { | |
1628 if (!NamingClass) | |
1629 NamingClass = Cls; | |
1630 // When we emulate implicit 'this->' in an unqualified lookup, we might | |
1631 // end up with an invalid naming class. In that case, we avoid emulating | |
1632 // 'this->' qualifier to satisfy preconditions of the access checking. | |
1633 if (NamingClass->getCanonicalDecl() != Cls->getCanonicalDecl() && | |
1634 !NamingClass->isDerivedFrom(Cls)) { | |
1635 NamingClass = Cls; | |
1636 BaseType = QualType(); | |
1637 } | |
1638 } else { | |
1639 // The decl was found outside the C++ class, so only ObjC access checks | |
1640 // apply. Those do not rely on NamingClass and BaseType, so we clear them | |
1641 // out. | |
1642 NamingClass = nullptr; | |
1643 BaseType = QualType(); | |
1644 } | |
1645 return Results.getSema().IsSimplyAccessible(ND, NamingClass, BaseType); | |
1646 } | |
1647 }; | |
1648 } // namespace | |
1649 | |
1650 /// Add type specifiers for the current language as keyword results. | |
1651 static void AddTypeSpecifierResults(const LangOptions &LangOpts, | |
1652 ResultBuilder &Results) { | |
1653 typedef CodeCompletionResult Result; | |
1654 Results.AddResult(Result("short", CCP_Type)); | |
1655 Results.AddResult(Result("long", CCP_Type)); | |
1656 Results.AddResult(Result("signed", CCP_Type)); | |
1657 Results.AddResult(Result("unsigned", CCP_Type)); | |
1658 Results.AddResult(Result("void", CCP_Type)); | |
1659 Results.AddResult(Result("char", CCP_Type)); | |
1660 Results.AddResult(Result("int", CCP_Type)); | |
1661 Results.AddResult(Result("float", CCP_Type)); | |
1662 Results.AddResult(Result("double", CCP_Type)); | |
1663 Results.AddResult(Result("enum", CCP_Type)); | |
1664 Results.AddResult(Result("struct", CCP_Type)); | |
1665 Results.AddResult(Result("union", CCP_Type)); | |
1666 Results.AddResult(Result("const", CCP_Type)); | |
1667 Results.AddResult(Result("volatile", CCP_Type)); | |
1668 | |
1669 if (LangOpts.C99) { | |
1670 // C99-specific | |
1671 Results.AddResult(Result("_Complex", CCP_Type)); | |
1672 Results.AddResult(Result("_Imaginary", CCP_Type)); | |
1673 Results.AddResult(Result("_Bool", CCP_Type)); | |
1674 Results.AddResult(Result("restrict", CCP_Type)); | |
1675 } | |
1676 | |
1677 CodeCompletionBuilder Builder(Results.getAllocator(), | |
1678 Results.getCodeCompletionTUInfo()); | |
1679 if (LangOpts.CPlusPlus) { | |
1680 // C++-specific | |
1681 Results.AddResult( | |
1682 Result("bool", CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0))); | |
1683 Results.AddResult(Result("class", CCP_Type)); | |
1684 Results.AddResult(Result("wchar_t", CCP_Type)); | |
1685 | |
1686 // typename qualified-id | |
1687 Builder.AddTypedTextChunk("typename"); | |
1688 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
1689 Builder.AddPlaceholderChunk("qualifier"); | |
1690 Builder.AddTextChunk("::"); | |
1691 Builder.AddPlaceholderChunk("name"); | |
1692 Results.AddResult(Result(Builder.TakeString())); | |
1693 | |
1694 if (LangOpts.CPlusPlus11) { | |
1695 Results.AddResult(Result("auto", CCP_Type)); | |
1696 Results.AddResult(Result("char16_t", CCP_Type)); | |
1697 Results.AddResult(Result("char32_t", CCP_Type)); | |
1698 | |
1699 Builder.AddTypedTextChunk("decltype"); | |
1700 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
1701 Builder.AddPlaceholderChunk("expression"); | |
1702 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
1703 Results.AddResult(Result(Builder.TakeString())); | |
1704 } | |
1705 } else | |
1706 Results.AddResult(Result("__auto_type", CCP_Type)); | |
1707 | |
1708 // GNU keywords | |
1709 if (LangOpts.GNUKeywords) { | |
1710 // FIXME: Enable when we actually support decimal floating point. | |
1711 // Results.AddResult(Result("_Decimal32")); | |
1712 // Results.AddResult(Result("_Decimal64")); | |
1713 // Results.AddResult(Result("_Decimal128")); | |
1714 | |
1715 Builder.AddTypedTextChunk("typeof"); | |
1716 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
1717 Builder.AddPlaceholderChunk("expression"); | |
1718 Results.AddResult(Result(Builder.TakeString())); | |
1719 | |
1720 Builder.AddTypedTextChunk("typeof"); | |
1721 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
1722 Builder.AddPlaceholderChunk("type"); | |
1723 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
1724 Results.AddResult(Result(Builder.TakeString())); | |
1725 } | |
1726 | |
1727 // Nullability | |
1728 Results.AddResult(Result("_Nonnull", CCP_Type)); | |
1729 Results.AddResult(Result("_Null_unspecified", CCP_Type)); | |
1730 Results.AddResult(Result("_Nullable", CCP_Type)); | |
1731 } | |
1732 | |
1733 static void AddStorageSpecifiers(Sema::ParserCompletionContext CCC, | |
1734 const LangOptions &LangOpts, | |
1735 ResultBuilder &Results) { | |
1736 typedef CodeCompletionResult Result; | |
1737 // Note: we don't suggest either "auto" or "register", because both | |
1738 // are pointless as storage specifiers. Elsewhere, we suggest "auto" | |
1739 // in C++0x as a type specifier. | |
1740 Results.AddResult(Result("extern")); | |
1741 Results.AddResult(Result("static")); | |
1742 | |
1743 if (LangOpts.CPlusPlus11) { | |
1744 CodeCompletionAllocator &Allocator = Results.getAllocator(); | |
1745 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); | |
1746 | |
1747 // alignas | |
1748 Builder.AddTypedTextChunk("alignas"); | |
1749 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
1750 Builder.AddPlaceholderChunk("expression"); | |
1751 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
1752 Results.AddResult(Result(Builder.TakeString())); | |
1753 | |
1754 Results.AddResult(Result("constexpr")); | |
1755 Results.AddResult(Result("thread_local")); | |
1756 } | |
1757 } | |
1758 | |
1759 static void AddFunctionSpecifiers(Sema::ParserCompletionContext CCC, | |
1760 const LangOptions &LangOpts, | |
1761 ResultBuilder &Results) { | |
1762 typedef CodeCompletionResult Result; | |
1763 switch (CCC) { | |
1764 case Sema::PCC_Class: | |
1765 case Sema::PCC_MemberTemplate: | |
1766 if (LangOpts.CPlusPlus) { | |
1767 Results.AddResult(Result("explicit")); | |
1768 Results.AddResult(Result("friend")); | |
1769 Results.AddResult(Result("mutable")); | |
1770 Results.AddResult(Result("virtual")); | |
1771 } | |
1772 LLVM_FALLTHROUGH; | |
1773 | |
1774 case Sema::PCC_ObjCInterface: | |
1775 case Sema::PCC_ObjCImplementation: | |
1776 case Sema::PCC_Namespace: | |
1777 case Sema::PCC_Template: | |
1778 if (LangOpts.CPlusPlus || LangOpts.C99) | |
1779 Results.AddResult(Result("inline")); | |
1780 break; | |
1781 | |
1782 case Sema::PCC_ObjCInstanceVariableList: | |
1783 case Sema::PCC_Expression: | |
1784 case Sema::PCC_Statement: | |
1785 case Sema::PCC_ForInit: | |
1786 case Sema::PCC_Condition: | |
1787 case Sema::PCC_RecoveryInFunction: | |
1788 case Sema::PCC_Type: | |
1789 case Sema::PCC_ParenthesizedExpression: | |
1790 case Sema::PCC_LocalDeclarationSpecifiers: | |
1791 break; | |
1792 } | |
1793 } | |
1794 | |
1795 static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt); | |
1796 static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt); | |
1797 static void AddObjCVisibilityResults(const LangOptions &LangOpts, | |
1798 ResultBuilder &Results, bool NeedAt); | |
1799 static void AddObjCImplementationResults(const LangOptions &LangOpts, | |
1800 ResultBuilder &Results, bool NeedAt); | |
1801 static void AddObjCInterfaceResults(const LangOptions &LangOpts, | |
1802 ResultBuilder &Results, bool NeedAt); | |
1803 static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt); | |
1804 | |
1805 static void AddTypedefResult(ResultBuilder &Results) { | |
1806 CodeCompletionBuilder Builder(Results.getAllocator(), | |
1807 Results.getCodeCompletionTUInfo()); | |
1808 Builder.AddTypedTextChunk("typedef"); | |
1809 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
1810 Builder.AddPlaceholderChunk("type"); | |
1811 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
1812 Builder.AddPlaceholderChunk("name"); | |
1813 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
1814 Results.AddResult(CodeCompletionResult(Builder.TakeString())); | |
1815 } | |
1816 | |
1817 static bool WantTypesInContext(Sema::ParserCompletionContext CCC, | |
1818 const LangOptions &LangOpts) { | |
1819 switch (CCC) { | |
1820 case Sema::PCC_Namespace: | |
1821 case Sema::PCC_Class: | |
1822 case Sema::PCC_ObjCInstanceVariableList: | |
1823 case Sema::PCC_Template: | |
1824 case Sema::PCC_MemberTemplate: | |
1825 case Sema::PCC_Statement: | |
1826 case Sema::PCC_RecoveryInFunction: | |
1827 case Sema::PCC_Type: | |
1828 case Sema::PCC_ParenthesizedExpression: | |
1829 case Sema::PCC_LocalDeclarationSpecifiers: | |
1830 return true; | |
1831 | |
1832 case Sema::PCC_Expression: | |
1833 case Sema::PCC_Condition: | |
1834 return LangOpts.CPlusPlus; | |
1835 | |
1836 case Sema::PCC_ObjCInterface: | |
1837 case Sema::PCC_ObjCImplementation: | |
1838 return false; | |
1839 | |
1840 case Sema::PCC_ForInit: | |
1841 return LangOpts.CPlusPlus || LangOpts.ObjC || LangOpts.C99; | |
1842 } | |
1843 | |
1844 llvm_unreachable("Invalid ParserCompletionContext!"); | |
1845 } | |
1846 | |
1847 static PrintingPolicy getCompletionPrintingPolicy(const ASTContext &Context, | |
1848 const Preprocessor &PP) { | |
1849 PrintingPolicy Policy = Sema::getPrintingPolicy(Context, PP); | |
1850 Policy.AnonymousTagLocations = false; | |
1851 Policy.SuppressStrongLifetime = true; | |
1852 Policy.SuppressUnwrittenScope = true; | |
1853 Policy.SuppressScope = true; | |
1854 return Policy; | |
1855 } | |
1856 | |
1857 /// Retrieve a printing policy suitable for code completion. | |
1858 static PrintingPolicy getCompletionPrintingPolicy(Sema &S) { | |
1859 return getCompletionPrintingPolicy(S.Context, S.PP); | |
1860 } | |
1861 | |
1862 /// Retrieve the string representation of the given type as a string | |
1863 /// that has the appropriate lifetime for code completion. | |
1864 /// | |
1865 /// This routine provides a fast path where we provide constant strings for | |
1866 /// common type names. | |
1867 static const char *GetCompletionTypeString(QualType T, ASTContext &Context, | |
1868 const PrintingPolicy &Policy, | |
1869 CodeCompletionAllocator &Allocator) { | |
1870 if (!T.getLocalQualifiers()) { | |
1871 // Built-in type names are constant strings. | |
1872 if (const BuiltinType *BT = dyn_cast<BuiltinType>(T)) | |
1873 return BT->getNameAsCString(Policy); | |
1874 | |
1875 // Anonymous tag types are constant strings. | |
1876 if (const TagType *TagT = dyn_cast<TagType>(T)) | |
1877 if (TagDecl *Tag = TagT->getDecl()) | |
1878 if (!Tag->hasNameForLinkage()) { | |
1879 switch (Tag->getTagKind()) { | |
1880 case TTK_Struct: | |
1881 return "struct <anonymous>"; | |
1882 case TTK_Interface: | |
1883 return "__interface <anonymous>"; | |
1884 case TTK_Class: | |
1885 return "class <anonymous>"; | |
1886 case TTK_Union: | |
1887 return "union <anonymous>"; | |
1888 case TTK_Enum: | |
1889 return "enum <anonymous>"; | |
1890 } | |
1891 } | |
1892 } | |
1893 | |
1894 // Slow path: format the type as a string. | |
1895 std::string Result; | |
1896 T.getAsStringInternal(Result, Policy); | |
1897 return Allocator.CopyString(Result); | |
1898 } | |
1899 | |
1900 /// Add a completion for "this", if we're in a member function. | |
1901 static void addThisCompletion(Sema &S, ResultBuilder &Results) { | |
1902 QualType ThisTy = S.getCurrentThisType(); | |
1903 if (ThisTy.isNull()) | |
1904 return; | |
1905 | |
1906 CodeCompletionAllocator &Allocator = Results.getAllocator(); | |
1907 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); | |
1908 PrintingPolicy Policy = getCompletionPrintingPolicy(S); | |
1909 Builder.AddResultTypeChunk( | |
1910 GetCompletionTypeString(ThisTy, S.Context, Policy, Allocator)); | |
1911 Builder.AddTypedTextChunk("this"); | |
1912 Results.AddResult(CodeCompletionResult(Builder.TakeString())); | |
1913 } | |
1914 | |
1915 static void AddStaticAssertResult(CodeCompletionBuilder &Builder, | |
1916 ResultBuilder &Results, | |
1917 const LangOptions &LangOpts) { | |
1918 if (!LangOpts.CPlusPlus11) | |
1919 return; | |
1920 | |
1921 Builder.AddTypedTextChunk("static_assert"); | |
1922 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
1923 Builder.AddPlaceholderChunk("expression"); | |
1924 Builder.AddChunk(CodeCompletionString::CK_Comma); | |
1925 Builder.AddPlaceholderChunk("message"); | |
1926 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
1927 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
1928 Results.AddResult(CodeCompletionResult(Builder.TakeString())); | |
1929 } | |
1930 | |
1931 static void AddOverrideResults(ResultBuilder &Results, | |
1932 const CodeCompletionContext &CCContext, | |
1933 CodeCompletionBuilder &Builder) { | |
1934 Sema &S = Results.getSema(); | |
1935 const auto *CR = llvm::dyn_cast<CXXRecordDecl>(S.CurContext); | |
1936 // If not inside a class/struct/union return empty. | |
1937 if (!CR) | |
1938 return; | |
1939 // First store overrides within current class. | |
1940 // These are stored by name to make querying fast in the later step. | |
1941 llvm::StringMap<std::vector<FunctionDecl *>> Overrides; | |
1942 for (auto *Method : CR->methods()) { | |
1943 if (!Method->isVirtual() || !Method->getIdentifier()) | |
1944 continue; | |
1945 Overrides[Method->getName()].push_back(Method); | |
1946 } | |
1947 | |
1948 for (const auto &Base : CR->bases()) { | |
1949 const auto *BR = Base.getType().getTypePtr()->getAsCXXRecordDecl(); | |
1950 if (!BR) | |
1951 continue; | |
1952 for (auto *Method : BR->methods()) { | |
1953 if (!Method->isVirtual() || !Method->getIdentifier()) | |
1954 continue; | |
1955 const auto it = Overrides.find(Method->getName()); | |
1956 bool IsOverriden = false; | |
1957 if (it != Overrides.end()) { | |
1958 for (auto *MD : it->second) { | |
1959 // If the method in current body is not an overload of this virtual | |
1960 // function, then it overrides this one. | |
1961 if (!S.IsOverload(MD, Method, false)) { | |
1962 IsOverriden = true; | |
1963 break; | |
1964 } | |
1965 } | |
1966 } | |
1967 if (!IsOverriden) { | |
1968 // Generates a new CodeCompletionResult by taking this function and | |
1969 // converting it into an override declaration with only one chunk in the | |
1970 // final CodeCompletionString as a TypedTextChunk. | |
1971 std::string OverrideSignature; | |
1972 llvm::raw_string_ostream OS(OverrideSignature); | |
1973 CodeCompletionResult CCR(Method, 0); | |
1974 PrintingPolicy Policy = | |
1975 getCompletionPrintingPolicy(S.getASTContext(), S.getPreprocessor()); | |
1976 auto *CCS = CCR.createCodeCompletionStringForOverride( | |
1977 S.getPreprocessor(), S.getASTContext(), Builder, | |
1978 /*IncludeBriefComments=*/false, CCContext, Policy); | |
1979 Results.AddResult(CodeCompletionResult(CCS, Method, CCP_CodePattern)); | |
1980 } | |
1981 } | |
1982 } | |
1983 } | |
1984 | |
1985 /// Add language constructs that show up for "ordinary" names. | |
1986 static void AddOrdinaryNameResults(Sema::ParserCompletionContext CCC, Scope *S, | |
1987 Sema &SemaRef, ResultBuilder &Results) { | |
1988 CodeCompletionAllocator &Allocator = Results.getAllocator(); | |
1989 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); | |
1990 | |
1991 typedef CodeCompletionResult Result; | |
1992 switch (CCC) { | |
1993 case Sema::PCC_Namespace: | |
1994 if (SemaRef.getLangOpts().CPlusPlus) { | |
1995 if (Results.includeCodePatterns()) { | |
1996 // namespace <identifier> { declarations } | |
1997 Builder.AddTypedTextChunk("namespace"); | |
1998 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
1999 Builder.AddPlaceholderChunk("identifier"); | |
2000 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2001 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
2002 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2003 Builder.AddPlaceholderChunk("declarations"); | |
2004 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2005 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
2006 Results.AddResult(Result(Builder.TakeString())); | |
2007 } | |
2008 | |
2009 // namespace identifier = identifier ; | |
2010 Builder.AddTypedTextChunk("namespace"); | |
2011 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2012 Builder.AddPlaceholderChunk("name"); | |
2013 Builder.AddChunk(CodeCompletionString::CK_Equal); | |
2014 Builder.AddPlaceholderChunk("namespace"); | |
2015 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2016 Results.AddResult(Result(Builder.TakeString())); | |
2017 | |
2018 // Using directives | |
2019 Builder.AddTypedTextChunk("using namespace"); | |
2020 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2021 Builder.AddPlaceholderChunk("identifier"); | |
2022 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2023 Results.AddResult(Result(Builder.TakeString())); | |
2024 | |
2025 // asm(string-literal) | |
2026 Builder.AddTypedTextChunk("asm"); | |
2027 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2028 Builder.AddPlaceholderChunk("string-literal"); | |
2029 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2030 Results.AddResult(Result(Builder.TakeString())); | |
2031 | |
2032 if (Results.includeCodePatterns()) { | |
2033 // Explicit template instantiation | |
2034 Builder.AddTypedTextChunk("template"); | |
2035 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2036 Builder.AddPlaceholderChunk("declaration"); | |
2037 Results.AddResult(Result(Builder.TakeString())); | |
2038 } else { | |
2039 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword)); | |
2040 } | |
2041 } | |
2042 | |
2043 if (SemaRef.getLangOpts().ObjC) | |
2044 AddObjCTopLevelResults(Results, true); | |
2045 | |
2046 AddTypedefResult(Results); | |
2047 LLVM_FALLTHROUGH; | |
2048 | |
2049 case Sema::PCC_Class: | |
2050 if (SemaRef.getLangOpts().CPlusPlus) { | |
2051 // Using declaration | |
2052 Builder.AddTypedTextChunk("using"); | |
2053 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2054 Builder.AddPlaceholderChunk("qualifier"); | |
2055 Builder.AddTextChunk("::"); | |
2056 Builder.AddPlaceholderChunk("name"); | |
2057 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2058 Results.AddResult(Result(Builder.TakeString())); | |
2059 | |
2060 // using typename qualifier::name (only in a dependent context) | |
2061 if (SemaRef.CurContext->isDependentContext()) { | |
2062 Builder.AddTypedTextChunk("using typename"); | |
2063 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2064 Builder.AddPlaceholderChunk("qualifier"); | |
2065 Builder.AddTextChunk("::"); | |
2066 Builder.AddPlaceholderChunk("name"); | |
2067 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2068 Results.AddResult(Result(Builder.TakeString())); | |
2069 } | |
2070 | |
2071 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); | |
2072 | |
2073 if (CCC == Sema::PCC_Class) { | |
2074 AddTypedefResult(Results); | |
2075 | |
2076 bool IsNotInheritanceScope = | |
2077 !(S->getFlags() & Scope::ClassInheritanceScope); | |
2078 // public: | |
2079 Builder.AddTypedTextChunk("public"); | |
2080 if (IsNotInheritanceScope && Results.includeCodePatterns()) | |
2081 Builder.AddChunk(CodeCompletionString::CK_Colon); | |
2082 Results.AddResult(Result(Builder.TakeString())); | |
2083 | |
2084 // protected: | |
2085 Builder.AddTypedTextChunk("protected"); | |
2086 if (IsNotInheritanceScope && Results.includeCodePatterns()) | |
2087 Builder.AddChunk(CodeCompletionString::CK_Colon); | |
2088 Results.AddResult(Result(Builder.TakeString())); | |
2089 | |
2090 // private: | |
2091 Builder.AddTypedTextChunk("private"); | |
2092 if (IsNotInheritanceScope && Results.includeCodePatterns()) | |
2093 Builder.AddChunk(CodeCompletionString::CK_Colon); | |
2094 Results.AddResult(Result(Builder.TakeString())); | |
2095 | |
2096 // FIXME: This adds override results only if we are at the first word of | |
2097 // the declaration/definition. Also call this from other sides to have | |
2098 // more use-cases. | |
2099 AddOverrideResults(Results, CodeCompletionContext::CCC_ClassStructUnion, | |
2100 Builder); | |
2101 } | |
2102 } | |
2103 LLVM_FALLTHROUGH; | |
2104 | |
2105 case Sema::PCC_Template: | |
2106 case Sema::PCC_MemberTemplate: | |
2107 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns()) { | |
2108 // template < parameters > | |
2109 Builder.AddTypedTextChunk("template"); | |
2110 Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | |
2111 Builder.AddPlaceholderChunk("parameters"); | |
2112 Builder.AddChunk(CodeCompletionString::CK_RightAngle); | |
2113 Results.AddResult(Result(Builder.TakeString())); | |
2114 } else { | |
2115 Results.AddResult(Result("template", CodeCompletionResult::RK_Keyword)); | |
2116 } | |
2117 | |
2118 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); | |
2119 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); | |
2120 break; | |
2121 | |
2122 case Sema::PCC_ObjCInterface: | |
2123 AddObjCInterfaceResults(SemaRef.getLangOpts(), Results, true); | |
2124 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); | |
2125 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); | |
2126 break; | |
2127 | |
2128 case Sema::PCC_ObjCImplementation: | |
2129 AddObjCImplementationResults(SemaRef.getLangOpts(), Results, true); | |
2130 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); | |
2131 AddFunctionSpecifiers(CCC, SemaRef.getLangOpts(), Results); | |
2132 break; | |
2133 | |
2134 case Sema::PCC_ObjCInstanceVariableList: | |
2135 AddObjCVisibilityResults(SemaRef.getLangOpts(), Results, true); | |
2136 break; | |
2137 | |
2138 case Sema::PCC_RecoveryInFunction: | |
2139 case Sema::PCC_Statement: { | |
2140 AddTypedefResult(Results); | |
2141 | |
2142 if (SemaRef.getLangOpts().CPlusPlus && Results.includeCodePatterns() && | |
2143 SemaRef.getLangOpts().CXXExceptions) { | |
2144 Builder.AddTypedTextChunk("try"); | |
2145 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2146 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
2147 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2148 Builder.AddPlaceholderChunk("statements"); | |
2149 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2150 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
2151 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2152 Builder.AddTextChunk("catch"); | |
2153 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2154 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2155 Builder.AddPlaceholderChunk("declaration"); | |
2156 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2157 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2158 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
2159 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2160 Builder.AddPlaceholderChunk("statements"); | |
2161 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2162 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
2163 Results.AddResult(Result(Builder.TakeString())); | |
2164 } | |
2165 if (SemaRef.getLangOpts().ObjC) | |
2166 AddObjCStatementResults(Results, true); | |
2167 | |
2168 if (Results.includeCodePatterns()) { | |
2169 // if (condition) { statements } | |
2170 Builder.AddTypedTextChunk("if"); | |
2171 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2172 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2173 if (SemaRef.getLangOpts().CPlusPlus) | |
2174 Builder.AddPlaceholderChunk("condition"); | |
2175 else | |
2176 Builder.AddPlaceholderChunk("expression"); | |
2177 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2178 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2179 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
2180 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2181 Builder.AddPlaceholderChunk("statements"); | |
2182 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2183 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
2184 Results.AddResult(Result(Builder.TakeString())); | |
2185 | |
2186 // switch (condition) { } | |
2187 Builder.AddTypedTextChunk("switch"); | |
2188 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2189 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2190 if (SemaRef.getLangOpts().CPlusPlus) | |
2191 Builder.AddPlaceholderChunk("condition"); | |
2192 else | |
2193 Builder.AddPlaceholderChunk("expression"); | |
2194 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2195 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2196 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
2197 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2198 Builder.AddPlaceholderChunk("cases"); | |
2199 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2200 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
2201 Results.AddResult(Result(Builder.TakeString())); | |
2202 } | |
2203 | |
2204 // Switch-specific statements. | |
2205 if (SemaRef.getCurFunction() && | |
2206 !SemaRef.getCurFunction()->SwitchStack.empty()) { | |
2207 // case expression: | |
2208 Builder.AddTypedTextChunk("case"); | |
2209 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2210 Builder.AddPlaceholderChunk("expression"); | |
2211 Builder.AddChunk(CodeCompletionString::CK_Colon); | |
2212 Results.AddResult(Result(Builder.TakeString())); | |
2213 | |
2214 // default: | |
2215 Builder.AddTypedTextChunk("default"); | |
2216 Builder.AddChunk(CodeCompletionString::CK_Colon); | |
2217 Results.AddResult(Result(Builder.TakeString())); | |
2218 } | |
2219 | |
2220 if (Results.includeCodePatterns()) { | |
2221 /// while (condition) { statements } | |
2222 Builder.AddTypedTextChunk("while"); | |
2223 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2224 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2225 if (SemaRef.getLangOpts().CPlusPlus) | |
2226 Builder.AddPlaceholderChunk("condition"); | |
2227 else | |
2228 Builder.AddPlaceholderChunk("expression"); | |
2229 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2230 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2231 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
2232 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2233 Builder.AddPlaceholderChunk("statements"); | |
2234 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2235 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
2236 Results.AddResult(Result(Builder.TakeString())); | |
2237 | |
2238 // do { statements } while ( expression ); | |
2239 Builder.AddTypedTextChunk("do"); | |
2240 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2241 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
2242 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2243 Builder.AddPlaceholderChunk("statements"); | |
2244 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2245 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
2246 Builder.AddTextChunk("while"); | |
2247 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2248 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2249 Builder.AddPlaceholderChunk("expression"); | |
2250 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2251 Results.AddResult(Result(Builder.TakeString())); | |
2252 | |
2253 // for ( for-init-statement ; condition ; expression ) { statements } | |
2254 Builder.AddTypedTextChunk("for"); | |
2255 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2256 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2257 if (SemaRef.getLangOpts().CPlusPlus || SemaRef.getLangOpts().C99) | |
2258 Builder.AddPlaceholderChunk("init-statement"); | |
2259 else | |
2260 Builder.AddPlaceholderChunk("init-expression"); | |
2261 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2262 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2263 Builder.AddPlaceholderChunk("condition"); | |
2264 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2265 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2266 Builder.AddPlaceholderChunk("inc-expression"); | |
2267 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2268 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2269 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
2270 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2271 Builder.AddPlaceholderChunk("statements"); | |
2272 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
2273 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
2274 Results.AddResult(Result(Builder.TakeString())); | |
2275 } | |
2276 | |
2277 if (S->getContinueParent()) { | |
2278 // continue ; | |
2279 Builder.AddTypedTextChunk("continue"); | |
2280 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2281 Results.AddResult(Result(Builder.TakeString())); | |
2282 } | |
2283 | |
2284 if (S->getBreakParent()) { | |
2285 // break ; | |
2286 Builder.AddTypedTextChunk("break"); | |
2287 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2288 Results.AddResult(Result(Builder.TakeString())); | |
2289 } | |
2290 | |
2291 // "return expression ;" or "return ;", depending on the return type. | |
2292 QualType ReturnType; | |
2293 if (const auto *Function = dyn_cast<FunctionDecl>(SemaRef.CurContext)) | |
2294 ReturnType = Function->getReturnType(); | |
2295 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(SemaRef.CurContext)) | |
2296 ReturnType = Method->getReturnType(); | |
2297 else if (SemaRef.getCurBlock() && | |
2298 !SemaRef.getCurBlock()->ReturnType.isNull()) | |
2299 ReturnType = SemaRef.getCurBlock()->ReturnType;; | |
2300 if (ReturnType.isNull() || ReturnType->isVoidType()) { | |
2301 Builder.AddTypedTextChunk("return"); | |
2302 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2303 Results.AddResult(Result(Builder.TakeString())); | |
2304 } else { | |
2305 assert(!ReturnType.isNull()); | |
2306 // "return expression ;" | |
2307 Builder.AddTypedTextChunk("return"); | |
2308 Builder.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace); | |
2309 Builder.AddPlaceholderChunk("expression"); | |
2310 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2311 Results.AddResult(Result(Builder.TakeString())); | |
2312 // When boolean, also add 'return true;' and 'return false;'. | |
2313 if (ReturnType->isBooleanType()) { | |
2314 Builder.AddTypedTextChunk("return true"); | |
2315 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2316 Results.AddResult(Result(Builder.TakeString())); | |
2317 | |
2318 Builder.AddTypedTextChunk("return false"); | |
2319 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2320 Results.AddResult(Result(Builder.TakeString())); | |
2321 } | |
2322 // For pointers, suggest 'return nullptr' in C++. | |
2323 if (SemaRef.getLangOpts().CPlusPlus11 && | |
2324 (ReturnType->isPointerType() || ReturnType->isMemberPointerType())) { | |
2325 Builder.AddTypedTextChunk("return nullptr"); | |
2326 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2327 Results.AddResult(Result(Builder.TakeString())); | |
2328 } | |
2329 } | |
2330 | |
2331 // goto identifier ; | |
2332 Builder.AddTypedTextChunk("goto"); | |
2333 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2334 Builder.AddPlaceholderChunk("label"); | |
2335 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2336 Results.AddResult(Result(Builder.TakeString())); | |
2337 | |
2338 // Using directives | |
2339 Builder.AddTypedTextChunk("using namespace"); | |
2340 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2341 Builder.AddPlaceholderChunk("identifier"); | |
2342 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
2343 Results.AddResult(Result(Builder.TakeString())); | |
2344 | |
2345 AddStaticAssertResult(Builder, Results, SemaRef.getLangOpts()); | |
2346 } | |
2347 LLVM_FALLTHROUGH; | |
2348 | |
2349 // Fall through (for statement expressions). | |
2350 case Sema::PCC_ForInit: | |
2351 case Sema::PCC_Condition: | |
2352 AddStorageSpecifiers(CCC, SemaRef.getLangOpts(), Results); | |
2353 // Fall through: conditions and statements can have expressions. | |
2354 LLVM_FALLTHROUGH; | |
2355 | |
2356 case Sema::PCC_ParenthesizedExpression: | |
2357 if (SemaRef.getLangOpts().ObjCAutoRefCount && | |
2358 CCC == Sema::PCC_ParenthesizedExpression) { | |
2359 // (__bridge <type>)<expression> | |
2360 Builder.AddTypedTextChunk("__bridge"); | |
2361 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2362 Builder.AddPlaceholderChunk("type"); | |
2363 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2364 Builder.AddPlaceholderChunk("expression"); | |
2365 Results.AddResult(Result(Builder.TakeString())); | |
2366 | |
2367 // (__bridge_transfer <Objective-C type>)<expression> | |
2368 Builder.AddTypedTextChunk("__bridge_transfer"); | |
2369 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2370 Builder.AddPlaceholderChunk("Objective-C type"); | |
2371 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2372 Builder.AddPlaceholderChunk("expression"); | |
2373 Results.AddResult(Result(Builder.TakeString())); | |
2374 | |
2375 // (__bridge_retained <CF type>)<expression> | |
2376 Builder.AddTypedTextChunk("__bridge_retained"); | |
2377 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2378 Builder.AddPlaceholderChunk("CF type"); | |
2379 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2380 Builder.AddPlaceholderChunk("expression"); | |
2381 Results.AddResult(Result(Builder.TakeString())); | |
2382 } | |
2383 // Fall through | |
2384 LLVM_FALLTHROUGH; | |
2385 | |
2386 case Sema::PCC_Expression: { | |
2387 if (SemaRef.getLangOpts().CPlusPlus) { | |
2388 // 'this', if we're in a non-static member function. | |
2389 addThisCompletion(SemaRef, Results); | |
2390 | |
2391 // true | |
2392 Builder.AddResultTypeChunk("bool"); | |
2393 Builder.AddTypedTextChunk("true"); | |
2394 Results.AddResult(Result(Builder.TakeString())); | |
2395 | |
2396 // false | |
2397 Builder.AddResultTypeChunk("bool"); | |
2398 Builder.AddTypedTextChunk("false"); | |
2399 Results.AddResult(Result(Builder.TakeString())); | |
2400 | |
2401 if (SemaRef.getLangOpts().RTTI) { | |
2402 // dynamic_cast < type-id > ( expression ) | |
2403 Builder.AddTypedTextChunk("dynamic_cast"); | |
2404 Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | |
2405 Builder.AddPlaceholderChunk("type"); | |
2406 Builder.AddChunk(CodeCompletionString::CK_RightAngle); | |
2407 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2408 Builder.AddPlaceholderChunk("expression"); | |
2409 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2410 Results.AddResult(Result(Builder.TakeString())); | |
2411 } | |
2412 | |
2413 // static_cast < type-id > ( expression ) | |
2414 Builder.AddTypedTextChunk("static_cast"); | |
2415 Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | |
2416 Builder.AddPlaceholderChunk("type"); | |
2417 Builder.AddChunk(CodeCompletionString::CK_RightAngle); | |
2418 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2419 Builder.AddPlaceholderChunk("expression"); | |
2420 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2421 Results.AddResult(Result(Builder.TakeString())); | |
2422 | |
2423 // reinterpret_cast < type-id > ( expression ) | |
2424 Builder.AddTypedTextChunk("reinterpret_cast"); | |
2425 Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | |
2426 Builder.AddPlaceholderChunk("type"); | |
2427 Builder.AddChunk(CodeCompletionString::CK_RightAngle); | |
2428 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2429 Builder.AddPlaceholderChunk("expression"); | |
2430 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2431 Results.AddResult(Result(Builder.TakeString())); | |
2432 | |
2433 // const_cast < type-id > ( expression ) | |
2434 Builder.AddTypedTextChunk("const_cast"); | |
2435 Builder.AddChunk(CodeCompletionString::CK_LeftAngle); | |
2436 Builder.AddPlaceholderChunk("type"); | |
2437 Builder.AddChunk(CodeCompletionString::CK_RightAngle); | |
2438 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2439 Builder.AddPlaceholderChunk("expression"); | |
2440 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2441 Results.AddResult(Result(Builder.TakeString())); | |
2442 | |
2443 if (SemaRef.getLangOpts().RTTI) { | |
2444 // typeid ( expression-or-type ) | |
2445 Builder.AddResultTypeChunk("std::type_info"); | |
2446 Builder.AddTypedTextChunk("typeid"); | |
2447 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2448 Builder.AddPlaceholderChunk("expression-or-type"); | |
2449 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2450 Results.AddResult(Result(Builder.TakeString())); | |
2451 } | |
2452 | |
2453 // new T ( ... ) | |
2454 Builder.AddTypedTextChunk("new"); | |
2455 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2456 Builder.AddPlaceholderChunk("type"); | |
2457 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2458 Builder.AddPlaceholderChunk("expressions"); | |
2459 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2460 Results.AddResult(Result(Builder.TakeString())); | |
2461 | |
2462 // new T [ ] ( ... ) | |
2463 Builder.AddTypedTextChunk("new"); | |
2464 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2465 Builder.AddPlaceholderChunk("type"); | |
2466 Builder.AddChunk(CodeCompletionString::CK_LeftBracket); | |
2467 Builder.AddPlaceholderChunk("size"); | |
2468 Builder.AddChunk(CodeCompletionString::CK_RightBracket); | |
2469 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2470 Builder.AddPlaceholderChunk("expressions"); | |
2471 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2472 Results.AddResult(Result(Builder.TakeString())); | |
2473 | |
2474 // delete expression | |
2475 Builder.AddResultTypeChunk("void"); | |
2476 Builder.AddTypedTextChunk("delete"); | |
2477 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2478 Builder.AddPlaceholderChunk("expression"); | |
2479 Results.AddResult(Result(Builder.TakeString())); | |
2480 | |
2481 // delete [] expression | |
2482 Builder.AddResultTypeChunk("void"); | |
2483 Builder.AddTypedTextChunk("delete"); | |
2484 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2485 Builder.AddChunk(CodeCompletionString::CK_LeftBracket); | |
2486 Builder.AddChunk(CodeCompletionString::CK_RightBracket); | |
2487 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2488 Builder.AddPlaceholderChunk("expression"); | |
2489 Results.AddResult(Result(Builder.TakeString())); | |
2490 | |
2491 if (SemaRef.getLangOpts().CXXExceptions) { | |
2492 // throw expression | |
2493 Builder.AddResultTypeChunk("void"); | |
2494 Builder.AddTypedTextChunk("throw"); | |
2495 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
2496 Builder.AddPlaceholderChunk("expression"); | |
2497 Results.AddResult(Result(Builder.TakeString())); | |
2498 } | |
2499 | |
2500 // FIXME: Rethrow? | |
2501 | |
2502 if (SemaRef.getLangOpts().CPlusPlus11) { | |
2503 // nullptr | |
2504 Builder.AddResultTypeChunk("std::nullptr_t"); | |
2505 Builder.AddTypedTextChunk("nullptr"); | |
2506 Results.AddResult(Result(Builder.TakeString())); | |
2507 | |
2508 // alignof | |
2509 Builder.AddResultTypeChunk("size_t"); | |
2510 Builder.AddTypedTextChunk("alignof"); | |
2511 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2512 Builder.AddPlaceholderChunk("type"); | |
2513 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2514 Results.AddResult(Result(Builder.TakeString())); | |
2515 | |
2516 // noexcept | |
2517 Builder.AddResultTypeChunk("bool"); | |
2518 Builder.AddTypedTextChunk("noexcept"); | |
2519 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2520 Builder.AddPlaceholderChunk("expression"); | |
2521 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2522 Results.AddResult(Result(Builder.TakeString())); | |
2523 | |
2524 // sizeof... expression | |
2525 Builder.AddResultTypeChunk("size_t"); | |
2526 Builder.AddTypedTextChunk("sizeof..."); | |
2527 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2528 Builder.AddPlaceholderChunk("parameter-pack"); | |
2529 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2530 Results.AddResult(Result(Builder.TakeString())); | |
2531 } | |
2532 } | |
2533 | |
2534 if (SemaRef.getLangOpts().ObjC) { | |
2535 // Add "super", if we're in an Objective-C class with a superclass. | |
2536 if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl()) { | |
2537 // The interface can be NULL. | |
2538 if (ObjCInterfaceDecl *ID = Method->getClassInterface()) | |
2539 if (ID->getSuperClass()) { | |
2540 std::string SuperType; | |
2541 SuperType = ID->getSuperClass()->getNameAsString(); | |
2542 if (Method->isInstanceMethod()) | |
2543 SuperType += " *"; | |
2544 | |
2545 Builder.AddResultTypeChunk(Allocator.CopyString(SuperType)); | |
2546 Builder.AddTypedTextChunk("super"); | |
2547 Results.AddResult(Result(Builder.TakeString())); | |
2548 } | |
2549 } | |
2550 | |
2551 AddObjCExpressionResults(Results, true); | |
2552 } | |
2553 | |
2554 if (SemaRef.getLangOpts().C11) { | |
2555 // _Alignof | |
2556 Builder.AddResultTypeChunk("size_t"); | |
2557 if (SemaRef.PP.isMacroDefined("alignof")) | |
2558 Builder.AddTypedTextChunk("alignof"); | |
2559 else | |
2560 Builder.AddTypedTextChunk("_Alignof"); | |
2561 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2562 Builder.AddPlaceholderChunk("type"); | |
2563 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2564 Results.AddResult(Result(Builder.TakeString())); | |
2565 } | |
2566 | |
2567 // sizeof expression | |
2568 Builder.AddResultTypeChunk("size_t"); | |
2569 Builder.AddTypedTextChunk("sizeof"); | |
2570 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
2571 Builder.AddPlaceholderChunk("expression-or-type"); | |
2572 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
2573 Results.AddResult(Result(Builder.TakeString())); | |
2574 break; | |
2575 } | |
2576 | |
2577 case Sema::PCC_Type: | |
2578 case Sema::PCC_LocalDeclarationSpecifiers: | |
2579 break; | |
2580 } | |
2581 | |
2582 if (WantTypesInContext(CCC, SemaRef.getLangOpts())) | |
2583 AddTypeSpecifierResults(SemaRef.getLangOpts(), Results); | |
2584 | |
2585 if (SemaRef.getLangOpts().CPlusPlus && CCC != Sema::PCC_Type) | |
2586 Results.AddResult(Result("operator")); | |
2587 } | |
2588 | |
2589 /// If the given declaration has an associated type, add it as a result | |
2590 /// type chunk. | |
2591 static void AddResultTypeChunk(ASTContext &Context, | |
2592 const PrintingPolicy &Policy, | |
2593 const NamedDecl *ND, QualType BaseType, | |
2594 CodeCompletionBuilder &Result) { | |
2595 if (!ND) | |
2596 return; | |
2597 | |
2598 // Skip constructors and conversion functions, which have their return types | |
2599 // built into their names. | |
2600 if (isConstructor(ND) || isa<CXXConversionDecl>(ND)) | |
2601 return; | |
2602 | |
2603 // Determine the type of the declaration (if it has a type). | |
2604 QualType T; | |
2605 if (const FunctionDecl *Function = ND->getAsFunction()) | |
2606 T = Function->getReturnType(); | |
2607 else if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) { | |
2608 if (!BaseType.isNull()) | |
2609 T = Method->getSendResultType(BaseType); | |
2610 else | |
2611 T = Method->getReturnType(); | |
2612 } else if (const auto *Enumerator = dyn_cast<EnumConstantDecl>(ND)) { | |
2613 T = Context.getTypeDeclType(cast<TypeDecl>(Enumerator->getDeclContext())); | |
2614 T = clang::TypeName::getFullyQualifiedType(T, Context); | |
2615 } else if (isa<UnresolvedUsingValueDecl>(ND)) { | |
2616 /* Do nothing: ignore unresolved using declarations*/ | |
2617 } else if (const auto *Ivar = dyn_cast<ObjCIvarDecl>(ND)) { | |
2618 if (!BaseType.isNull()) | |
2619 T = Ivar->getUsageType(BaseType); | |
2620 else | |
2621 T = Ivar->getType(); | |
2622 } else if (const auto *Value = dyn_cast<ValueDecl>(ND)) { | |
2623 T = Value->getType(); | |
2624 } else if (const auto *Property = dyn_cast<ObjCPropertyDecl>(ND)) { | |
2625 if (!BaseType.isNull()) | |
2626 T = Property->getUsageType(BaseType); | |
2627 else | |
2628 T = Property->getType(); | |
2629 } | |
2630 | |
2631 if (T.isNull() || Context.hasSameType(T, Context.DependentTy)) | |
2632 return; | |
2633 | |
2634 Result.AddResultTypeChunk( | |
2635 GetCompletionTypeString(T, Context, Policy, Result.getAllocator())); | |
2636 } | |
2637 | |
2638 static void MaybeAddSentinel(Preprocessor &PP, | |
2639 const NamedDecl *FunctionOrMethod, | |
2640 CodeCompletionBuilder &Result) { | |
2641 if (SentinelAttr *Sentinel = FunctionOrMethod->getAttr<SentinelAttr>()) | |
2642 if (Sentinel->getSentinel() == 0) { | |
2643 if (PP.getLangOpts().ObjC && PP.isMacroDefined("nil")) | |
2644 Result.AddTextChunk(", nil"); | |
2645 else if (PP.isMacroDefined("NULL")) | |
2646 Result.AddTextChunk(", NULL"); | |
2647 else | |
2648 Result.AddTextChunk(", (void*)0"); | |
2649 } | |
2650 } | |
2651 | |
2652 static std::string formatObjCParamQualifiers(unsigned ObjCQuals, | |
2653 QualType &Type) { | |
2654 std::string Result; | |
2655 if (ObjCQuals & Decl::OBJC_TQ_In) | |
2656 Result += "in "; | |
2657 else if (ObjCQuals & Decl::OBJC_TQ_Inout) | |
2658 Result += "inout "; | |
2659 else if (ObjCQuals & Decl::OBJC_TQ_Out) | |
2660 Result += "out "; | |
2661 if (ObjCQuals & Decl::OBJC_TQ_Bycopy) | |
2662 Result += "bycopy "; | |
2663 else if (ObjCQuals & Decl::OBJC_TQ_Byref) | |
2664 Result += "byref "; | |
2665 if (ObjCQuals & Decl::OBJC_TQ_Oneway) | |
2666 Result += "oneway "; | |
2667 if (ObjCQuals & Decl::OBJC_TQ_CSNullability) { | |
2668 if (auto nullability = AttributedType::stripOuterNullability(Type)) { | |
2669 switch (*nullability) { | |
2670 case NullabilityKind::NonNull: | |
2671 Result += "nonnull "; | |
2672 break; | |
2673 | |
2674 case NullabilityKind::Nullable: | |
2675 Result += "nullable "; | |
2676 break; | |
2677 | |
2678 case NullabilityKind::Unspecified: | |
2679 Result += "null_unspecified "; | |
2680 break; | |
2681 } | |
2682 } | |
2683 } | |
2684 return Result; | |
2685 } | |
2686 | |
2687 /// Tries to find the most appropriate type location for an Objective-C | |
2688 /// block placeholder. | |
2689 /// | |
2690 /// This function ignores things like typedefs and qualifiers in order to | |
2691 /// present the most relevant and accurate block placeholders in code completion | |
2692 /// results. | |
2693 static void findTypeLocationForBlockDecl(const TypeSourceInfo *TSInfo, | |
2694 FunctionTypeLoc &Block, | |
2695 FunctionProtoTypeLoc &BlockProto, | |
2696 bool SuppressBlock = false) { | |
2697 if (!TSInfo) | |
2698 return; | |
2699 TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc(); | |
2700 while (true) { | |
2701 // Look through typedefs. | |
2702 if (!SuppressBlock) { | |
2703 if (TypedefTypeLoc TypedefTL = TL.getAs<TypedefTypeLoc>()) { | |
2704 if (TypeSourceInfo *InnerTSInfo = | |
2705 TypedefTL.getTypedefNameDecl()->getTypeSourceInfo()) { | |
2706 TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); | |
2707 continue; | |
2708 } | |
2709 } | |
2710 | |
2711 // Look through qualified types | |
2712 if (QualifiedTypeLoc QualifiedTL = TL.getAs<QualifiedTypeLoc>()) { | |
2713 TL = QualifiedTL.getUnqualifiedLoc(); | |
2714 continue; | |
2715 } | |
2716 | |
2717 if (AttributedTypeLoc AttrTL = TL.getAs<AttributedTypeLoc>()) { | |
2718 TL = AttrTL.getModifiedLoc(); | |
2719 continue; | |
2720 } | |
2721 } | |
2722 | |
2723 // Try to get the function prototype behind the block pointer type, | |
2724 // then we're done. | |
2725 if (BlockPointerTypeLoc BlockPtr = TL.getAs<BlockPointerTypeLoc>()) { | |
2726 TL = BlockPtr.getPointeeLoc().IgnoreParens(); | |
2727 Block = TL.getAs<FunctionTypeLoc>(); | |
2728 BlockProto = TL.getAs<FunctionProtoTypeLoc>(); | |
2729 } | |
2730 break; | |
2731 } | |
2732 } | |
2733 | |
2734 static std::string | |
2735 formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl, | |
2736 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto, | |
2737 bool SuppressBlockName = false, | |
2738 bool SuppressBlock = false, | |
2739 Optional<ArrayRef<QualType>> ObjCSubsts = None); | |
2740 | |
2741 static std::string | |
2742 FormatFunctionParameter(const PrintingPolicy &Policy, const ParmVarDecl *Param, | |
2743 bool SuppressName = false, bool SuppressBlock = false, | |
2744 Optional<ArrayRef<QualType>> ObjCSubsts = None) { | |
2745 // Params are unavailable in FunctionTypeLoc if the FunctionType is invalid. | |
2746 // It would be better to pass in the param Type, which is usually avaliable. | |
2747 // But this case is rare, so just pretend we fell back to int as elsewhere. | |
2748 if (!Param) | |
2749 return "int"; | |
2750 bool ObjCMethodParam = isa<ObjCMethodDecl>(Param->getDeclContext()); | |
2751 if (Param->getType()->isDependentType() || | |
2752 !Param->getType()->isBlockPointerType()) { | |
2753 // The argument for a dependent or non-block parameter is a placeholder | |
2754 // containing that parameter's type. | |
2755 std::string Result; | |
2756 | |
2757 if (Param->getIdentifier() && !ObjCMethodParam && !SuppressName) | |
2758 Result = std::string(Param->getIdentifier()->getName()); | |
2759 | |
2760 QualType Type = Param->getType(); | |
2761 if (ObjCSubsts) | |
2762 Type = Type.substObjCTypeArgs(Param->getASTContext(), *ObjCSubsts, | |
2763 ObjCSubstitutionContext::Parameter); | |
2764 if (ObjCMethodParam) { | |
2765 Result = | |
2766 "(" + formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type); | |
2767 Result += Type.getAsString(Policy) + ")"; | |
2768 if (Param->getIdentifier() && !SuppressName) | |
2769 Result += Param->getIdentifier()->getName(); | |
2770 } else { | |
2771 Type.getAsStringInternal(Result, Policy); | |
2772 } | |
2773 return Result; | |
2774 } | |
2775 | |
2776 // The argument for a block pointer parameter is a block literal with | |
2777 // the appropriate type. | |
2778 FunctionTypeLoc Block; | |
2779 FunctionProtoTypeLoc BlockProto; | |
2780 findTypeLocationForBlockDecl(Param->getTypeSourceInfo(), Block, BlockProto, | |
2781 SuppressBlock); | |
2782 // Try to retrieve the block type information from the property if this is a | |
2783 // parameter in a setter. | |
2784 if (!Block && ObjCMethodParam && | |
2785 cast<ObjCMethodDecl>(Param->getDeclContext())->isPropertyAccessor()) { | |
2786 if (const auto *PD = cast<ObjCMethodDecl>(Param->getDeclContext()) | |
2787 ->findPropertyDecl(/*CheckOverrides=*/false)) | |
2788 findTypeLocationForBlockDecl(PD->getTypeSourceInfo(), Block, BlockProto, | |
2789 SuppressBlock); | |
2790 } | |
2791 | |
2792 if (!Block) { | |
2793 // We were unable to find a FunctionProtoTypeLoc with parameter names | |
2794 // for the block; just use the parameter type as a placeholder. | |
2795 std::string Result; | |
2796 if (!ObjCMethodParam && Param->getIdentifier()) | |
2797 Result = std::string(Param->getIdentifier()->getName()); | |
2798 | |
2799 QualType Type = Param->getType().getUnqualifiedType(); | |
2800 | |
2801 if (ObjCMethodParam) { | |
2802 Result = Type.getAsString(Policy); | |
2803 std::string Quals = | |
2804 formatObjCParamQualifiers(Param->getObjCDeclQualifier(), Type); | |
2805 if (!Quals.empty()) | |
2806 Result = "(" + Quals + " " + Result + ")"; | |
2807 if (Result.back() != ')') | |
2808 Result += " "; | |
2809 if (Param->getIdentifier()) | |
2810 Result += Param->getIdentifier()->getName(); | |
2811 } else { | |
2812 Type.getAsStringInternal(Result, Policy); | |
2813 } | |
2814 | |
2815 return Result; | |
2816 } | |
2817 | |
2818 // We have the function prototype behind the block pointer type, as it was | |
2819 // written in the source. | |
2820 return formatBlockPlaceholder(Policy, Param, Block, BlockProto, | |
2821 /*SuppressBlockName=*/false, SuppressBlock, | |
2822 ObjCSubsts); | |
2823 } | |
2824 | |
2825 /// Returns a placeholder string that corresponds to an Objective-C block | |
2826 /// declaration. | |
2827 /// | |
2828 /// \param BlockDecl A declaration with an Objective-C block type. | |
2829 /// | |
2830 /// \param Block The most relevant type location for that block type. | |
2831 /// | |
2832 /// \param SuppressBlockName Determines whether or not the name of the block | |
2833 /// declaration is included in the resulting string. | |
2834 static std::string | |
2835 formatBlockPlaceholder(const PrintingPolicy &Policy, const NamedDecl *BlockDecl, | |
2836 FunctionTypeLoc &Block, FunctionProtoTypeLoc &BlockProto, | |
2837 bool SuppressBlockName, bool SuppressBlock, | |
2838 Optional<ArrayRef<QualType>> ObjCSubsts) { | |
2839 std::string Result; | |
2840 QualType ResultType = Block.getTypePtr()->getReturnType(); | |
2841 if (ObjCSubsts) | |
2842 ResultType = | |
2843 ResultType.substObjCTypeArgs(BlockDecl->getASTContext(), *ObjCSubsts, | |
2844 ObjCSubstitutionContext::Result); | |
2845 if (!ResultType->isVoidType() || SuppressBlock) | |
2846 ResultType.getAsStringInternal(Result, Policy); | |
2847 | |
2848 // Format the parameter list. | |
2849 std::string Params; | |
2850 if (!BlockProto || Block.getNumParams() == 0) { | |
2851 if (BlockProto && BlockProto.getTypePtr()->isVariadic()) | |
2852 Params = "(...)"; | |
2853 else | |
2854 Params = "(void)"; | |
2855 } else { | |
2856 Params += "("; | |
2857 for (unsigned I = 0, N = Block.getNumParams(); I != N; ++I) { | |
2858 if (I) | |
2859 Params += ", "; | |
2860 Params += FormatFunctionParameter(Policy, Block.getParam(I), | |
2861 /*SuppressName=*/false, | |
2862 /*SuppressBlock=*/true, ObjCSubsts); | |
2863 | |
2864 if (I == N - 1 && BlockProto.getTypePtr()->isVariadic()) | |
2865 Params += ", ..."; | |
2866 } | |
2867 Params += ")"; | |
2868 } | |
2869 | |
2870 if (SuppressBlock) { | |
2871 // Format as a parameter. | |
2872 Result = Result + " (^"; | |
2873 if (!SuppressBlockName && BlockDecl->getIdentifier()) | |
2874 Result += BlockDecl->getIdentifier()->getName(); | |
2875 Result += ")"; | |
2876 Result += Params; | |
2877 } else { | |
2878 // Format as a block literal argument. | |
2879 Result = '^' + Result; | |
2880 Result += Params; | |
2881 | |
2882 if (!SuppressBlockName && BlockDecl->getIdentifier()) | |
2883 Result += BlockDecl->getIdentifier()->getName(); | |
2884 } | |
2885 | |
2886 return Result; | |
2887 } | |
2888 | |
2889 static std::string GetDefaultValueString(const ParmVarDecl *Param, | |
2890 const SourceManager &SM, | |
2891 const LangOptions &LangOpts) { | |
2892 const SourceRange SrcRange = Param->getDefaultArgRange(); | |
2893 CharSourceRange CharSrcRange = CharSourceRange::getTokenRange(SrcRange); | |
2894 bool Invalid = CharSrcRange.isInvalid(); | |
2895 if (Invalid) | |
2896 return ""; | |
2897 StringRef srcText = | |
2898 Lexer::getSourceText(CharSrcRange, SM, LangOpts, &Invalid); | |
2899 if (Invalid) | |
2900 return ""; | |
2901 | |
2902 if (srcText.empty() || srcText == "=") { | |
2903 // Lexer can't determine the value. | |
2904 // This happens if the code is incorrect (for example class is forward | |
2905 // declared). | |
2906 return ""; | |
2907 } | |
2908 std::string DefValue(srcText.str()); | |
2909 // FIXME: remove this check if the Lexer::getSourceText value is fixed and | |
2910 // this value always has (or always does not have) '=' in front of it | |
2911 if (DefValue.at(0) != '=') { | |
2912 // If we don't have '=' in front of value. | |
2913 // Lexer returns built-in types values without '=' and user-defined types | |
2914 // values with it. | |
2915 return " = " + DefValue; | |
2916 } | |
2917 return " " + DefValue; | |
2918 } | |
2919 | |
2920 /// Add function parameter chunks to the given code completion string. | |
2921 static void AddFunctionParameterChunks(Preprocessor &PP, | |
2922 const PrintingPolicy &Policy, | |
2923 const FunctionDecl *Function, | |
2924 CodeCompletionBuilder &Result, | |
2925 unsigned Start = 0, | |
2926 bool InOptional = false) { | |
2927 bool FirstParameter = true; | |
2928 | |
2929 for (unsigned P = Start, N = Function->getNumParams(); P != N; ++P) { | |
2930 const ParmVarDecl *Param = Function->getParamDecl(P); | |
2931 | |
2932 if (Param->hasDefaultArg() && !InOptional) { | |
2933 // When we see an optional default argument, put that argument and | |
2934 // the remaining default arguments into a new, optional string. | |
2935 CodeCompletionBuilder Opt(Result.getAllocator(), | |
2936 Result.getCodeCompletionTUInfo()); | |
2937 if (!FirstParameter) | |
2938 Opt.AddChunk(CodeCompletionString::CK_Comma); | |
2939 AddFunctionParameterChunks(PP, Policy, Function, Opt, P, true); | |
2940 Result.AddOptionalChunk(Opt.TakeString()); | |
2941 break; | |
2942 } | |
2943 | |
2944 if (FirstParameter) | |
2945 FirstParameter = false; | |
2946 else | |
2947 Result.AddChunk(CodeCompletionString::CK_Comma); | |
2948 | |
2949 InOptional = false; | |
2950 | |
2951 // Format the placeholder string. | |
2952 std::string PlaceholderStr = FormatFunctionParameter(Policy, Param); | |
2953 if (Param->hasDefaultArg()) | |
2954 PlaceholderStr += | |
2955 GetDefaultValueString(Param, PP.getSourceManager(), PP.getLangOpts()); | |
2956 | |
2957 if (Function->isVariadic() && P == N - 1) | |
2958 PlaceholderStr += ", ..."; | |
2959 | |
2960 // Add the placeholder string. | |
2961 Result.AddPlaceholderChunk( | |
2962 Result.getAllocator().CopyString(PlaceholderStr)); | |
2963 } | |
2964 | |
2965 if (const auto *Proto = Function->getType()->getAs<FunctionProtoType>()) | |
2966 if (Proto->isVariadic()) { | |
2967 if (Proto->getNumParams() == 0) | |
2968 Result.AddPlaceholderChunk("..."); | |
2969 | |
2970 MaybeAddSentinel(PP, Function, Result); | |
2971 } | |
2972 } | |
2973 | |
2974 /// Add template parameter chunks to the given code completion string. | |
2975 static void AddTemplateParameterChunks( | |
2976 ASTContext &Context, const PrintingPolicy &Policy, | |
2977 const TemplateDecl *Template, CodeCompletionBuilder &Result, | |
2978 unsigned MaxParameters = 0, unsigned Start = 0, bool InDefaultArg = false) { | |
2979 bool FirstParameter = true; | |
2980 | |
2981 // Prefer to take the template parameter names from the first declaration of | |
2982 // the template. | |
2983 Template = cast<TemplateDecl>(Template->getCanonicalDecl()); | |
2984 | |
2985 TemplateParameterList *Params = Template->getTemplateParameters(); | |
2986 TemplateParameterList::iterator PEnd = Params->end(); | |
2987 if (MaxParameters) | |
2988 PEnd = Params->begin() + MaxParameters; | |
2989 for (TemplateParameterList::iterator P = Params->begin() + Start; P != PEnd; | |
2990 ++P) { | |
2991 bool HasDefaultArg = false; | |
2992 std::string PlaceholderStr; | |
2993 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { | |
2994 if (TTP->wasDeclaredWithTypename()) | |
2995 PlaceholderStr = "typename"; | |
2996 else if (const auto *TC = TTP->getTypeConstraint()) { | |
2997 llvm::raw_string_ostream OS(PlaceholderStr); | |
2998 TC->print(OS, Policy); | |
2999 OS.flush(); | |
3000 } else | |
3001 PlaceholderStr = "class"; | |
3002 | |
3003 if (TTP->getIdentifier()) { | |
3004 PlaceholderStr += ' '; | |
3005 PlaceholderStr += TTP->getIdentifier()->getName(); | |
3006 } | |
3007 | |
3008 HasDefaultArg = TTP->hasDefaultArgument(); | |
3009 } else if (NonTypeTemplateParmDecl *NTTP = | |
3010 dyn_cast<NonTypeTemplateParmDecl>(*P)) { | |
3011 if (NTTP->getIdentifier()) | |
3012 PlaceholderStr = std::string(NTTP->getIdentifier()->getName()); | |
3013 NTTP->getType().getAsStringInternal(PlaceholderStr, Policy); | |
3014 HasDefaultArg = NTTP->hasDefaultArgument(); | |
3015 } else { | |
3016 assert(isa<TemplateTemplateParmDecl>(*P)); | |
3017 TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); | |
3018 | |
3019 // Since putting the template argument list into the placeholder would | |
3020 // be very, very long, we just use an abbreviation. | |
3021 PlaceholderStr = "template<...> class"; | |
3022 if (TTP->getIdentifier()) { | |
3023 PlaceholderStr += ' '; | |
3024 PlaceholderStr += TTP->getIdentifier()->getName(); | |
3025 } | |
3026 | |
3027 HasDefaultArg = TTP->hasDefaultArgument(); | |
3028 } | |
3029 | |
3030 if (HasDefaultArg && !InDefaultArg) { | |
3031 // When we see an optional default argument, put that argument and | |
3032 // the remaining default arguments into a new, optional string. | |
3033 CodeCompletionBuilder Opt(Result.getAllocator(), | |
3034 Result.getCodeCompletionTUInfo()); | |
3035 if (!FirstParameter) | |
3036 Opt.AddChunk(CodeCompletionString::CK_Comma); | |
3037 AddTemplateParameterChunks(Context, Policy, Template, Opt, MaxParameters, | |
3038 P - Params->begin(), true); | |
3039 Result.AddOptionalChunk(Opt.TakeString()); | |
3040 break; | |
3041 } | |
3042 | |
3043 InDefaultArg = false; | |
3044 | |
3045 if (FirstParameter) | |
3046 FirstParameter = false; | |
3047 else | |
3048 Result.AddChunk(CodeCompletionString::CK_Comma); | |
3049 | |
3050 // Add the placeholder string. | |
3051 Result.AddPlaceholderChunk( | |
3052 Result.getAllocator().CopyString(PlaceholderStr)); | |
3053 } | |
3054 } | |
3055 | |
3056 /// Add a qualifier to the given code-completion string, if the | |
3057 /// provided nested-name-specifier is non-NULL. | |
3058 static void AddQualifierToCompletionString(CodeCompletionBuilder &Result, | |
3059 NestedNameSpecifier *Qualifier, | |
3060 bool QualifierIsInformative, | |
3061 ASTContext &Context, | |
3062 const PrintingPolicy &Policy) { | |
3063 if (!Qualifier) | |
3064 return; | |
3065 | |
3066 std::string PrintedNNS; | |
3067 { | |
3068 llvm::raw_string_ostream OS(PrintedNNS); | |
3069 Qualifier->print(OS, Policy); | |
3070 } | |
3071 if (QualifierIsInformative) | |
3072 Result.AddInformativeChunk(Result.getAllocator().CopyString(PrintedNNS)); | |
3073 else | |
3074 Result.AddTextChunk(Result.getAllocator().CopyString(PrintedNNS)); | |
3075 } | |
3076 | |
3077 static void | |
3078 AddFunctionTypeQualsToCompletionString(CodeCompletionBuilder &Result, | |
3079 const FunctionDecl *Function) { | |
3080 const auto *Proto = Function->getType()->getAs<FunctionProtoType>(); | |
3081 if (!Proto || !Proto->getMethodQuals()) | |
3082 return; | |
3083 | |
3084 // FIXME: Add ref-qualifier! | |
3085 | |
3086 // Handle single qualifiers without copying | |
3087 if (Proto->getMethodQuals().hasOnlyConst()) { | |
3088 Result.AddInformativeChunk(" const"); | |
3089 return; | |
3090 } | |
3091 | |
3092 if (Proto->getMethodQuals().hasOnlyVolatile()) { | |
3093 Result.AddInformativeChunk(" volatile"); | |
3094 return; | |
3095 } | |
3096 | |
3097 if (Proto->getMethodQuals().hasOnlyRestrict()) { | |
3098 Result.AddInformativeChunk(" restrict"); | |
3099 return; | |
3100 } | |
3101 | |
3102 // Handle multiple qualifiers. | |
3103 std::string QualsStr; | |
3104 if (Proto->isConst()) | |
3105 QualsStr += " const"; | |
3106 if (Proto->isVolatile()) | |
3107 QualsStr += " volatile"; | |
3108 if (Proto->isRestrict()) | |
3109 QualsStr += " restrict"; | |
3110 Result.AddInformativeChunk(Result.getAllocator().CopyString(QualsStr)); | |
3111 } | |
3112 | |
3113 /// Add the name of the given declaration | |
3114 static void AddTypedNameChunk(ASTContext &Context, const PrintingPolicy &Policy, | |
3115 const NamedDecl *ND, | |
3116 CodeCompletionBuilder &Result) { | |
3117 DeclarationName Name = ND->getDeclName(); | |
3118 if (!Name) | |
3119 return; | |
3120 | |
3121 switch (Name.getNameKind()) { | |
3122 case DeclarationName::CXXOperatorName: { | |
3123 const char *OperatorName = nullptr; | |
3124 switch (Name.getCXXOverloadedOperator()) { | |
3125 case OO_None: | |
3126 case OO_Conditional: | |
3127 case NUM_OVERLOADED_OPERATORS: | |
3128 OperatorName = "operator"; | |
3129 break; | |
3130 | |
3131 #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ | |
3132 case OO_##Name: \ | |
3133 OperatorName = "operator" Spelling; \ | |
3134 break; | |
3135 #define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly) | |
3136 #include "clang/Basic/OperatorKinds.def" | |
3137 | |
3138 case OO_New: | |
3139 OperatorName = "operator new"; | |
3140 break; | |
3141 case OO_Delete: | |
3142 OperatorName = "operator delete"; | |
3143 break; | |
3144 case OO_Array_New: | |
3145 OperatorName = "operator new[]"; | |
3146 break; | |
3147 case OO_Array_Delete: | |
3148 OperatorName = "operator delete[]"; | |
3149 break; | |
3150 case OO_Call: | |
3151 OperatorName = "operator()"; | |
3152 break; | |
3153 case OO_Subscript: | |
3154 OperatorName = "operator[]"; | |
3155 break; | |
3156 } | |
3157 Result.AddTypedTextChunk(OperatorName); | |
3158 break; | |
3159 } | |
3160 | |
3161 case DeclarationName::Identifier: | |
3162 case DeclarationName::CXXConversionFunctionName: | |
3163 case DeclarationName::CXXDestructorName: | |
3164 case DeclarationName::CXXLiteralOperatorName: | |
3165 Result.AddTypedTextChunk( | |
3166 Result.getAllocator().CopyString(ND->getNameAsString())); | |
3167 break; | |
3168 | |
3169 case DeclarationName::CXXDeductionGuideName: | |
3170 case DeclarationName::CXXUsingDirective: | |
3171 case DeclarationName::ObjCZeroArgSelector: | |
3172 case DeclarationName::ObjCOneArgSelector: | |
3173 case DeclarationName::ObjCMultiArgSelector: | |
3174 break; | |
3175 | |
3176 case DeclarationName::CXXConstructorName: { | |
3177 CXXRecordDecl *Record = nullptr; | |
3178 QualType Ty = Name.getCXXNameType(); | |
3179 if (const auto *RecordTy = Ty->getAs<RecordType>()) | |
3180 Record = cast<CXXRecordDecl>(RecordTy->getDecl()); | |
3181 else if (const auto *InjectedTy = Ty->getAs<InjectedClassNameType>()) | |
3182 Record = InjectedTy->getDecl(); | |
3183 else { | |
3184 Result.AddTypedTextChunk( | |
3185 Result.getAllocator().CopyString(ND->getNameAsString())); | |
3186 break; | |
3187 } | |
3188 | |
3189 Result.AddTypedTextChunk( | |
3190 Result.getAllocator().CopyString(Record->getNameAsString())); | |
3191 if (ClassTemplateDecl *Template = Record->getDescribedClassTemplate()) { | |
3192 Result.AddChunk(CodeCompletionString::CK_LeftAngle); | |
3193 AddTemplateParameterChunks(Context, Policy, Template, Result); | |
3194 Result.AddChunk(CodeCompletionString::CK_RightAngle); | |
3195 } | |
3196 break; | |
3197 } | |
3198 } | |
3199 } | |
3200 | |
3201 CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString( | |
3202 Sema &S, const CodeCompletionContext &CCContext, | |
3203 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, | |
3204 bool IncludeBriefComments) { | |
3205 return CreateCodeCompletionString(S.Context, S.PP, CCContext, Allocator, | |
3206 CCTUInfo, IncludeBriefComments); | |
3207 } | |
3208 | |
3209 CodeCompletionString *CodeCompletionResult::CreateCodeCompletionStringForMacro( | |
3210 Preprocessor &PP, CodeCompletionAllocator &Allocator, | |
3211 CodeCompletionTUInfo &CCTUInfo) { | |
3212 assert(Kind == RK_Macro); | |
3213 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); | |
3214 const MacroInfo *MI = PP.getMacroInfo(Macro); | |
3215 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Macro->getName())); | |
3216 | |
3217 if (!MI || !MI->isFunctionLike()) | |
3218 return Result.TakeString(); | |
3219 | |
3220 // Format a function-like macro with placeholders for the arguments. | |
3221 Result.AddChunk(CodeCompletionString::CK_LeftParen); | |
3222 MacroInfo::param_iterator A = MI->param_begin(), AEnd = MI->param_end(); | |
3223 | |
3224 // C99 variadic macros add __VA_ARGS__ at the end. Skip it. | |
3225 if (MI->isC99Varargs()) { | |
3226 --AEnd; | |
3227 | |
3228 if (A == AEnd) { | |
3229 Result.AddPlaceholderChunk("..."); | |
3230 } | |
3231 } | |
3232 | |
3233 for (MacroInfo::param_iterator A = MI->param_begin(); A != AEnd; ++A) { | |
3234 if (A != MI->param_begin()) | |
3235 Result.AddChunk(CodeCompletionString::CK_Comma); | |
3236 | |
3237 if (MI->isVariadic() && (A + 1) == AEnd) { | |
3238 SmallString<32> Arg = (*A)->getName(); | |
3239 if (MI->isC99Varargs()) | |
3240 Arg += ", ..."; | |
3241 else | |
3242 Arg += "..."; | |
3243 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); | |
3244 break; | |
3245 } | |
3246 | |
3247 // Non-variadic macros are simple. | |
3248 Result.AddPlaceholderChunk( | |
3249 Result.getAllocator().CopyString((*A)->getName())); | |
3250 } | |
3251 Result.AddChunk(CodeCompletionString::CK_RightParen); | |
3252 return Result.TakeString(); | |
3253 } | |
3254 | |
3255 /// If possible, create a new code completion string for the given | |
3256 /// result. | |
3257 /// | |
3258 /// \returns Either a new, heap-allocated code completion string describing | |
3259 /// how to use this result, or NULL to indicate that the string or name of the | |
3260 /// result is all that is needed. | |
3261 CodeCompletionString *CodeCompletionResult::CreateCodeCompletionString( | |
3262 ASTContext &Ctx, Preprocessor &PP, const CodeCompletionContext &CCContext, | |
3263 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, | |
3264 bool IncludeBriefComments) { | |
3265 if (Kind == RK_Macro) | |
3266 return CreateCodeCompletionStringForMacro(PP, Allocator, CCTUInfo); | |
3267 | |
3268 CodeCompletionBuilder Result(Allocator, CCTUInfo, Priority, Availability); | |
3269 | |
3270 PrintingPolicy Policy = getCompletionPrintingPolicy(Ctx, PP); | |
3271 if (Kind == RK_Pattern) { | |
3272 Pattern->Priority = Priority; | |
3273 Pattern->Availability = Availability; | |
3274 | |
3275 if (Declaration) { | |
3276 Result.addParentContext(Declaration->getDeclContext()); | |
3277 Pattern->ParentName = Result.getParentName(); | |
3278 if (const RawComment *RC = | |
3279 getPatternCompletionComment(Ctx, Declaration)) { | |
3280 Result.addBriefComment(RC->getBriefText(Ctx)); | |
3281 Pattern->BriefComment = Result.getBriefComment(); | |
3282 } | |
3283 } | |
3284 | |
3285 return Pattern; | |
3286 } | |
3287 | |
3288 if (Kind == RK_Keyword) { | |
3289 Result.AddTypedTextChunk(Keyword); | |
3290 return Result.TakeString(); | |
3291 } | |
3292 assert(Kind == RK_Declaration && "Missed a result kind?"); | |
3293 return createCodeCompletionStringForDecl( | |
3294 PP, Ctx, Result, IncludeBriefComments, CCContext, Policy); | |
3295 } | |
3296 | |
3297 static void printOverrideString(const CodeCompletionString &CCS, | |
3298 std::string &BeforeName, | |
3299 std::string &NameAndSignature) { | |
3300 bool SeenTypedChunk = false; | |
3301 for (auto &Chunk : CCS) { | |
3302 if (Chunk.Kind == CodeCompletionString::CK_Optional) { | |
3303 assert(SeenTypedChunk && "optional parameter before name"); | |
3304 // Note that we put all chunks inside into NameAndSignature. | |
3305 printOverrideString(*Chunk.Optional, NameAndSignature, NameAndSignature); | |
3306 continue; | |
3307 } | |
3308 SeenTypedChunk |= Chunk.Kind == CodeCompletionString::CK_TypedText; | |
3309 if (SeenTypedChunk) | |
3310 NameAndSignature += Chunk.Text; | |
3311 else | |
3312 BeforeName += Chunk.Text; | |
3313 } | |
3314 } | |
3315 | |
3316 CodeCompletionString * | |
3317 CodeCompletionResult::createCodeCompletionStringForOverride( | |
3318 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, | |
3319 bool IncludeBriefComments, const CodeCompletionContext &CCContext, | |
3320 PrintingPolicy &Policy) { | |
3321 auto *CCS = createCodeCompletionStringForDecl(PP, Ctx, Result, | |
3322 /*IncludeBriefComments=*/false, | |
3323 CCContext, Policy); | |
3324 std::string BeforeName; | |
3325 std::string NameAndSignature; | |
3326 // For overrides all chunks go into the result, none are informative. | |
3327 printOverrideString(*CCS, BeforeName, NameAndSignature); | |
3328 NameAndSignature += " override"; | |
3329 | |
3330 Result.AddTextChunk(Result.getAllocator().CopyString(BeforeName)); | |
3331 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
3332 Result.AddTypedTextChunk(Result.getAllocator().CopyString(NameAndSignature)); | |
3333 return Result.TakeString(); | |
3334 } | |
3335 | |
3336 // FIXME: Right now this works well with lambdas. Add support for other functor | |
3337 // types like std::function. | |
3338 static const NamedDecl *extractFunctorCallOperator(const NamedDecl *ND) { | |
3339 const auto *VD = dyn_cast<VarDecl>(ND); | |
3340 if (!VD) | |
3341 return nullptr; | |
3342 const auto *RecordDecl = VD->getType()->getAsCXXRecordDecl(); | |
3343 if (!RecordDecl || !RecordDecl->isLambda()) | |
3344 return nullptr; | |
3345 return RecordDecl->getLambdaCallOperator(); | |
3346 } | |
3347 | |
3348 CodeCompletionString *CodeCompletionResult::createCodeCompletionStringForDecl( | |
3349 Preprocessor &PP, ASTContext &Ctx, CodeCompletionBuilder &Result, | |
3350 bool IncludeBriefComments, const CodeCompletionContext &CCContext, | |
3351 PrintingPolicy &Policy) { | |
3352 const NamedDecl *ND = Declaration; | |
3353 Result.addParentContext(ND->getDeclContext()); | |
3354 | |
3355 if (IncludeBriefComments) { | |
3356 // Add documentation comment, if it exists. | |
3357 if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) { | |
3358 Result.addBriefComment(RC->getBriefText(Ctx)); | |
3359 } | |
3360 } | |
3361 | |
3362 if (StartsNestedNameSpecifier) { | |
3363 Result.AddTypedTextChunk( | |
3364 Result.getAllocator().CopyString(ND->getNameAsString())); | |
3365 Result.AddTextChunk("::"); | |
3366 return Result.TakeString(); | |
3367 } | |
3368 | |
3369 for (const auto *I : ND->specific_attrs<AnnotateAttr>()) | |
3370 Result.AddAnnotation(Result.getAllocator().CopyString(I->getAnnotation())); | |
3371 | |
3372 auto AddFunctionTypeAndResult = [&](const FunctionDecl *Function) { | |
3373 AddResultTypeChunk(Ctx, Policy, Function, CCContext.getBaseType(), Result); | |
3374 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, | |
3375 Ctx, Policy); | |
3376 AddTypedNameChunk(Ctx, Policy, ND, Result); | |
3377 Result.AddChunk(CodeCompletionString::CK_LeftParen); | |
3378 AddFunctionParameterChunks(PP, Policy, Function, Result); | |
3379 Result.AddChunk(CodeCompletionString::CK_RightParen); | |
3380 AddFunctionTypeQualsToCompletionString(Result, Function); | |
3381 }; | |
3382 | |
3383 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) { | |
3384 AddFunctionTypeAndResult(Function); | |
3385 return Result.TakeString(); | |
3386 } | |
3387 | |
3388 if (const auto *CallOperator = | |
3389 dyn_cast_or_null<FunctionDecl>(extractFunctorCallOperator(ND))) { | |
3390 AddFunctionTypeAndResult(CallOperator); | |
3391 return Result.TakeString(); | |
3392 } | |
3393 | |
3394 AddResultTypeChunk(Ctx, Policy, ND, CCContext.getBaseType(), Result); | |
3395 | |
3396 if (const FunctionTemplateDecl *FunTmpl = | |
3397 dyn_cast<FunctionTemplateDecl>(ND)) { | |
3398 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, | |
3399 Ctx, Policy); | |
3400 FunctionDecl *Function = FunTmpl->getTemplatedDecl(); | |
3401 AddTypedNameChunk(Ctx, Policy, Function, Result); | |
3402 | |
3403 // Figure out which template parameters are deduced (or have default | |
3404 // arguments). | |
3405 llvm::SmallBitVector Deduced; | |
3406 Sema::MarkDeducedTemplateParameters(Ctx, FunTmpl, Deduced); | |
3407 unsigned LastDeducibleArgument; | |
3408 for (LastDeducibleArgument = Deduced.size(); LastDeducibleArgument > 0; | |
3409 --LastDeducibleArgument) { | |
3410 if (!Deduced[LastDeducibleArgument - 1]) { | |
3411 // C++0x: Figure out if the template argument has a default. If so, | |
3412 // the user doesn't need to type this argument. | |
3413 // FIXME: We need to abstract template parameters better! | |
3414 bool HasDefaultArg = false; | |
3415 NamedDecl *Param = FunTmpl->getTemplateParameters()->getParam( | |
3416 LastDeducibleArgument - 1); | |
3417 if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) | |
3418 HasDefaultArg = TTP->hasDefaultArgument(); | |
3419 else if (NonTypeTemplateParmDecl *NTTP = | |
3420 dyn_cast<NonTypeTemplateParmDecl>(Param)) | |
3421 HasDefaultArg = NTTP->hasDefaultArgument(); | |
3422 else { | |
3423 assert(isa<TemplateTemplateParmDecl>(Param)); | |
3424 HasDefaultArg = | |
3425 cast<TemplateTemplateParmDecl>(Param)->hasDefaultArgument(); | |
3426 } | |
3427 | |
3428 if (!HasDefaultArg) | |
3429 break; | |
3430 } | |
3431 } | |
3432 | |
3433 if (LastDeducibleArgument) { | |
3434 // Some of the function template arguments cannot be deduced from a | |
3435 // function call, so we introduce an explicit template argument list | |
3436 // containing all of the arguments up to the first deducible argument. | |
3437 Result.AddChunk(CodeCompletionString::CK_LeftAngle); | |
3438 AddTemplateParameterChunks(Ctx, Policy, FunTmpl, Result, | |
3439 LastDeducibleArgument); | |
3440 Result.AddChunk(CodeCompletionString::CK_RightAngle); | |
3441 } | |
3442 | |
3443 // Add the function parameters | |
3444 Result.AddChunk(CodeCompletionString::CK_LeftParen); | |
3445 AddFunctionParameterChunks(PP, Policy, Function, Result); | |
3446 Result.AddChunk(CodeCompletionString::CK_RightParen); | |
3447 AddFunctionTypeQualsToCompletionString(Result, Function); | |
3448 return Result.TakeString(); | |
3449 } | |
3450 | |
3451 if (const auto *Template = dyn_cast<TemplateDecl>(ND)) { | |
3452 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, | |
3453 Ctx, Policy); | |
3454 Result.AddTypedTextChunk( | |
3455 Result.getAllocator().CopyString(Template->getNameAsString())); | |
3456 Result.AddChunk(CodeCompletionString::CK_LeftAngle); | |
3457 AddTemplateParameterChunks(Ctx, Policy, Template, Result); | |
3458 Result.AddChunk(CodeCompletionString::CK_RightAngle); | |
3459 return Result.TakeString(); | |
3460 } | |
3461 | |
3462 if (const auto *Method = dyn_cast<ObjCMethodDecl>(ND)) { | |
3463 Selector Sel = Method->getSelector(); | |
3464 if (Sel.isUnarySelector()) { | |
3465 Result.AddTypedTextChunk( | |
3466 Result.getAllocator().CopyString(Sel.getNameForSlot(0))); | |
3467 return Result.TakeString(); | |
3468 } | |
3469 | |
3470 std::string SelName = Sel.getNameForSlot(0).str(); | |
3471 SelName += ':'; | |
3472 if (StartParameter == 0) | |
3473 Result.AddTypedTextChunk(Result.getAllocator().CopyString(SelName)); | |
3474 else { | |
3475 Result.AddInformativeChunk(Result.getAllocator().CopyString(SelName)); | |
3476 | |
3477 // If there is only one parameter, and we're past it, add an empty | |
3478 // typed-text chunk since there is nothing to type. | |
3479 if (Method->param_size() == 1) | |
3480 Result.AddTypedTextChunk(""); | |
3481 } | |
3482 unsigned Idx = 0; | |
3483 for (ObjCMethodDecl::param_const_iterator P = Method->param_begin(), | |
3484 PEnd = Method->param_end(); | |
3485 P != PEnd; (void)++P, ++Idx) { | |
3486 if (Idx > 0) { | |
3487 std::string Keyword; | |
3488 if (Idx > StartParameter) | |
3489 Result.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
3490 if (IdentifierInfo *II = Sel.getIdentifierInfoForSlot(Idx)) | |
3491 Keyword += II->getName(); | |
3492 Keyword += ":"; | |
3493 if (Idx < StartParameter || AllParametersAreInformative) | |
3494 Result.AddInformativeChunk(Result.getAllocator().CopyString(Keyword)); | |
3495 else | |
3496 Result.AddTypedTextChunk(Result.getAllocator().CopyString(Keyword)); | |
3497 } | |
3498 | |
3499 // If we're before the starting parameter, skip the placeholder. | |
3500 if (Idx < StartParameter) | |
3501 continue; | |
3502 | |
3503 std::string Arg; | |
3504 QualType ParamType = (*P)->getType(); | |
3505 Optional<ArrayRef<QualType>> ObjCSubsts; | |
3506 if (!CCContext.getBaseType().isNull()) | |
3507 ObjCSubsts = CCContext.getBaseType()->getObjCSubstitutions(Method); | |
3508 | |
3509 if (ParamType->isBlockPointerType() && !DeclaringEntity) | |
3510 Arg = FormatFunctionParameter(Policy, *P, true, | |
3511 /*SuppressBlock=*/false, ObjCSubsts); | |
3512 else { | |
3513 if (ObjCSubsts) | |
3514 ParamType = ParamType.substObjCTypeArgs( | |
3515 Ctx, *ObjCSubsts, ObjCSubstitutionContext::Parameter); | |
3516 Arg = "(" + formatObjCParamQualifiers((*P)->getObjCDeclQualifier(), | |
3517 ParamType); | |
3518 Arg += ParamType.getAsString(Policy) + ")"; | |
3519 if (IdentifierInfo *II = (*P)->getIdentifier()) | |
3520 if (DeclaringEntity || AllParametersAreInformative) | |
3521 Arg += II->getName(); | |
3522 } | |
3523 | |
3524 if (Method->isVariadic() && (P + 1) == PEnd) | |
3525 Arg += ", ..."; | |
3526 | |
3527 if (DeclaringEntity) | |
3528 Result.AddTextChunk(Result.getAllocator().CopyString(Arg)); | |
3529 else if (AllParametersAreInformative) | |
3530 Result.AddInformativeChunk(Result.getAllocator().CopyString(Arg)); | |
3531 else | |
3532 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Arg)); | |
3533 } | |
3534 | |
3535 if (Method->isVariadic()) { | |
3536 if (Method->param_size() == 0) { | |
3537 if (DeclaringEntity) | |
3538 Result.AddTextChunk(", ..."); | |
3539 else if (AllParametersAreInformative) | |
3540 Result.AddInformativeChunk(", ..."); | |
3541 else | |
3542 Result.AddPlaceholderChunk(", ..."); | |
3543 } | |
3544 | |
3545 MaybeAddSentinel(PP, Method, Result); | |
3546 } | |
3547 | |
3548 return Result.TakeString(); | |
3549 } | |
3550 | |
3551 if (Qualifier) | |
3552 AddQualifierToCompletionString(Result, Qualifier, QualifierIsInformative, | |
3553 Ctx, Policy); | |
3554 | |
3555 Result.AddTypedTextChunk( | |
3556 Result.getAllocator().CopyString(ND->getNameAsString())); | |
3557 return Result.TakeString(); | |
3558 } | |
3559 | |
3560 const RawComment *clang::getCompletionComment(const ASTContext &Ctx, | |
3561 const NamedDecl *ND) { | |
3562 if (!ND) | |
3563 return nullptr; | |
3564 if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND)) | |
3565 return RC; | |
3566 | |
3567 // Try to find comment from a property for ObjC methods. | |
3568 const auto *M = dyn_cast<ObjCMethodDecl>(ND); | |
3569 if (!M) | |
3570 return nullptr; | |
3571 const ObjCPropertyDecl *PDecl = M->findPropertyDecl(); | |
3572 if (!PDecl) | |
3573 return nullptr; | |
3574 | |
3575 return Ctx.getRawCommentForAnyRedecl(PDecl); | |
3576 } | |
3577 | |
3578 const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx, | |
3579 const NamedDecl *ND) { | |
3580 const auto *M = dyn_cast_or_null<ObjCMethodDecl>(ND); | |
3581 if (!M || !M->isPropertyAccessor()) | |
3582 return nullptr; | |
3583 | |
3584 // Provide code completion comment for self.GetterName where | |
3585 // GetterName is the getter method for a property with name | |
3586 // different from the property name (declared via a property | |
3587 // getter attribute. | |
3588 const ObjCPropertyDecl *PDecl = M->findPropertyDecl(); | |
3589 if (!PDecl) | |
3590 return nullptr; | |
3591 if (PDecl->getGetterName() == M->getSelector() && | |
3592 PDecl->getIdentifier() != M->getIdentifier()) { | |
3593 if (auto *RC = Ctx.getRawCommentForAnyRedecl(M)) | |
3594 return RC; | |
3595 if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl)) | |
3596 return RC; | |
3597 } | |
3598 return nullptr; | |
3599 } | |
3600 | |
3601 const RawComment *clang::getParameterComment( | |
3602 const ASTContext &Ctx, | |
3603 const CodeCompleteConsumer::OverloadCandidate &Result, unsigned ArgIndex) { | |
3604 auto FDecl = Result.getFunction(); | |
3605 if (!FDecl) | |
3606 return nullptr; | |
3607 if (ArgIndex < FDecl->getNumParams()) | |
3608 return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(ArgIndex)); | |
3609 return nullptr; | |
3610 } | |
3611 | |
3612 /// Add function overload parameter chunks to the given code completion | |
3613 /// string. | |
3614 static void AddOverloadParameterChunks(ASTContext &Context, | |
3615 const PrintingPolicy &Policy, | |
3616 const FunctionDecl *Function, | |
3617 const FunctionProtoType *Prototype, | |
3618 CodeCompletionBuilder &Result, | |
3619 unsigned CurrentArg, unsigned Start = 0, | |
3620 bool InOptional = false) { | |
3621 bool FirstParameter = true; | |
3622 unsigned NumParams = | |
3623 Function ? Function->getNumParams() : Prototype->getNumParams(); | |
3624 | |
3625 for (unsigned P = Start; P != NumParams; ++P) { | |
3626 if (Function && Function->getParamDecl(P)->hasDefaultArg() && !InOptional) { | |
3627 // When we see an optional default argument, put that argument and | |
3628 // the remaining default arguments into a new, optional string. | |
3629 CodeCompletionBuilder Opt(Result.getAllocator(), | |
3630 Result.getCodeCompletionTUInfo()); | |
3631 if (!FirstParameter) | |
3632 Opt.AddChunk(CodeCompletionString::CK_Comma); | |
3633 // Optional sections are nested. | |
3634 AddOverloadParameterChunks(Context, Policy, Function, Prototype, Opt, | |
3635 CurrentArg, P, /*InOptional=*/true); | |
3636 Result.AddOptionalChunk(Opt.TakeString()); | |
3637 return; | |
3638 } | |
3639 | |
3640 if (FirstParameter) | |
3641 FirstParameter = false; | |
3642 else | |
3643 Result.AddChunk(CodeCompletionString::CK_Comma); | |
3644 | |
3645 InOptional = false; | |
3646 | |
3647 // Format the placeholder string. | |
3648 std::string Placeholder; | |
3649 if (Function) { | |
3650 const ParmVarDecl *Param = Function->getParamDecl(P); | |
3651 Placeholder = FormatFunctionParameter(Policy, Param); | |
3652 if (Param->hasDefaultArg()) | |
3653 Placeholder += GetDefaultValueString(Param, Context.getSourceManager(), | |
3654 Context.getLangOpts()); | |
3655 } else { | |
3656 Placeholder = Prototype->getParamType(P).getAsString(Policy); | |
3657 } | |
3658 | |
3659 if (P == CurrentArg) | |
3660 Result.AddCurrentParameterChunk( | |
3661 Result.getAllocator().CopyString(Placeholder)); | |
3662 else | |
3663 Result.AddPlaceholderChunk(Result.getAllocator().CopyString(Placeholder)); | |
3664 } | |
3665 | |
3666 if (Prototype && Prototype->isVariadic()) { | |
3667 CodeCompletionBuilder Opt(Result.getAllocator(), | |
3668 Result.getCodeCompletionTUInfo()); | |
3669 if (!FirstParameter) | |
3670 Opt.AddChunk(CodeCompletionString::CK_Comma); | |
3671 | |
3672 if (CurrentArg < NumParams) | |
3673 Opt.AddPlaceholderChunk("..."); | |
3674 else | |
3675 Opt.AddCurrentParameterChunk("..."); | |
3676 | |
3677 Result.AddOptionalChunk(Opt.TakeString()); | |
3678 } | |
3679 } | |
3680 | |
3681 CodeCompletionString * | |
3682 CodeCompleteConsumer::OverloadCandidate::CreateSignatureString( | |
3683 unsigned CurrentArg, Sema &S, CodeCompletionAllocator &Allocator, | |
3684 CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments) const { | |
3685 PrintingPolicy Policy = getCompletionPrintingPolicy(S); | |
3686 // Show signatures of constructors as they are declared: | |
3687 // vector(int n) rather than vector<string>(int n) | |
3688 // This is less noisy without being less clear, and avoids tricky cases. | |
3689 Policy.SuppressTemplateArgsInCXXConstructors = true; | |
3690 | |
3691 // FIXME: Set priority, availability appropriately. | |
3692 CodeCompletionBuilder Result(Allocator, CCTUInfo, 1, | |
3693 CXAvailability_Available); | |
3694 FunctionDecl *FDecl = getFunction(); | |
3695 const FunctionProtoType *Proto = | |
3696 dyn_cast<FunctionProtoType>(getFunctionType()); | |
3697 if (!FDecl && !Proto) { | |
3698 // Function without a prototype. Just give the return type and a | |
3699 // highlighted ellipsis. | |
3700 const FunctionType *FT = getFunctionType(); | |
3701 Result.AddResultTypeChunk(Result.getAllocator().CopyString( | |
3702 FT->getReturnType().getAsString(Policy))); | |
3703 Result.AddChunk(CodeCompletionString::CK_LeftParen); | |
3704 Result.AddChunk(CodeCompletionString::CK_CurrentParameter, "..."); | |
3705 Result.AddChunk(CodeCompletionString::CK_RightParen); | |
3706 return Result.TakeString(); | |
3707 } | |
3708 | |
3709 if (FDecl) { | |
3710 if (IncludeBriefComments) { | |
3711 if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg)) | |
3712 Result.addBriefComment(RC->getBriefText(S.getASTContext())); | |
3713 } | |
3714 AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result); | |
3715 | |
3716 std::string Name; | |
3717 llvm::raw_string_ostream OS(Name); | |
3718 FDecl->getDeclName().print(OS, Policy); | |
3719 Result.AddTextChunk(Result.getAllocator().CopyString(OS.str())); | |
3720 } else { | |
3721 Result.AddResultTypeChunk(Result.getAllocator().CopyString( | |
3722 Proto->getReturnType().getAsString(Policy))); | |
3723 } | |
3724 | |
3725 Result.AddChunk(CodeCompletionString::CK_LeftParen); | |
3726 AddOverloadParameterChunks(S.getASTContext(), Policy, FDecl, Proto, Result, | |
3727 CurrentArg); | |
3728 Result.AddChunk(CodeCompletionString::CK_RightParen); | |
3729 | |
3730 return Result.TakeString(); | |
3731 } | |
3732 | |
3733 unsigned clang::getMacroUsagePriority(StringRef MacroName, | |
3734 const LangOptions &LangOpts, | |
3735 bool PreferredTypeIsPointer) { | |
3736 unsigned Priority = CCP_Macro; | |
3737 | |
3738 // Treat the "nil", "Nil" and "NULL" macros as null pointer constants. | |
3739 if (MacroName.equals("nil") || MacroName.equals("NULL") || | |
3740 MacroName.equals("Nil")) { | |
3741 Priority = CCP_Constant; | |
3742 if (PreferredTypeIsPointer) | |
3743 Priority = Priority / CCF_SimilarTypeMatch; | |
3744 } | |
3745 // Treat "YES", "NO", "true", and "false" as constants. | |
3746 else if (MacroName.equals("YES") || MacroName.equals("NO") || | |
3747 MacroName.equals("true") || MacroName.equals("false")) | |
3748 Priority = CCP_Constant; | |
3749 // Treat "bool" as a type. | |
3750 else if (MacroName.equals("bool")) | |
3751 Priority = CCP_Type + (LangOpts.ObjC ? CCD_bool_in_ObjC : 0); | |
3752 | |
3753 return Priority; | |
3754 } | |
3755 | |
3756 CXCursorKind clang::getCursorKindForDecl(const Decl *D) { | |
3757 if (!D) | |
3758 return CXCursor_UnexposedDecl; | |
3759 | |
3760 switch (D->getKind()) { | |
3761 case Decl::Enum: | |
3762 return CXCursor_EnumDecl; | |
3763 case Decl::EnumConstant: | |
3764 return CXCursor_EnumConstantDecl; | |
3765 case Decl::Field: | |
3766 return CXCursor_FieldDecl; | |
3767 case Decl::Function: | |
3768 return CXCursor_FunctionDecl; | |
3769 case Decl::ObjCCategory: | |
3770 return CXCursor_ObjCCategoryDecl; | |
3771 case Decl::ObjCCategoryImpl: | |
3772 return CXCursor_ObjCCategoryImplDecl; | |
3773 case Decl::ObjCImplementation: | |
3774 return CXCursor_ObjCImplementationDecl; | |
3775 | |
3776 case Decl::ObjCInterface: | |
3777 return CXCursor_ObjCInterfaceDecl; | |
3778 case Decl::ObjCIvar: | |
3779 return CXCursor_ObjCIvarDecl; | |
3780 case Decl::ObjCMethod: | |
3781 return cast<ObjCMethodDecl>(D)->isInstanceMethod() | |
3782 ? CXCursor_ObjCInstanceMethodDecl | |
3783 : CXCursor_ObjCClassMethodDecl; | |
3784 case Decl::CXXMethod: | |
3785 return CXCursor_CXXMethod; | |
3786 case Decl::CXXConstructor: | |
3787 return CXCursor_Constructor; | |
3788 case Decl::CXXDestructor: | |
3789 return CXCursor_Destructor; | |
3790 case Decl::CXXConversion: | |
3791 return CXCursor_ConversionFunction; | |
3792 case Decl::ObjCProperty: | |
3793 return CXCursor_ObjCPropertyDecl; | |
3794 case Decl::ObjCProtocol: | |
3795 return CXCursor_ObjCProtocolDecl; | |
3796 case Decl::ParmVar: | |
3797 return CXCursor_ParmDecl; | |
3798 case Decl::Typedef: | |
3799 return CXCursor_TypedefDecl; | |
3800 case Decl::TypeAlias: | |
3801 return CXCursor_TypeAliasDecl; | |
3802 case Decl::TypeAliasTemplate: | |
3803 return CXCursor_TypeAliasTemplateDecl; | |
3804 case Decl::Var: | |
3805 return CXCursor_VarDecl; | |
3806 case Decl::Namespace: | |
3807 return CXCursor_Namespace; | |
3808 case Decl::NamespaceAlias: | |
3809 return CXCursor_NamespaceAlias; | |
3810 case Decl::TemplateTypeParm: | |
3811 return CXCursor_TemplateTypeParameter; | |
3812 case Decl::NonTypeTemplateParm: | |
3813 return CXCursor_NonTypeTemplateParameter; | |
3814 case Decl::TemplateTemplateParm: | |
3815 return CXCursor_TemplateTemplateParameter; | |
3816 case Decl::FunctionTemplate: | |
3817 return CXCursor_FunctionTemplate; | |
3818 case Decl::ClassTemplate: | |
3819 return CXCursor_ClassTemplate; | |
3820 case Decl::AccessSpec: | |
3821 return CXCursor_CXXAccessSpecifier; | |
3822 case Decl::ClassTemplatePartialSpecialization: | |
3823 return CXCursor_ClassTemplatePartialSpecialization; | |
3824 case Decl::UsingDirective: | |
3825 return CXCursor_UsingDirective; | |
3826 case Decl::StaticAssert: | |
3827 return CXCursor_StaticAssert; | |
3828 case Decl::Friend: | |
3829 return CXCursor_FriendDecl; | |
3830 case Decl::TranslationUnit: | |
3831 return CXCursor_TranslationUnit; | |
3832 | |
3833 case Decl::Using: | |
3834 case Decl::UnresolvedUsingValue: | |
3835 case Decl::UnresolvedUsingTypename: | |
3836 return CXCursor_UsingDeclaration; | |
3837 | |
3838 case Decl::ObjCPropertyImpl: | |
3839 switch (cast<ObjCPropertyImplDecl>(D)->getPropertyImplementation()) { | |
3840 case ObjCPropertyImplDecl::Dynamic: | |
3841 return CXCursor_ObjCDynamicDecl; | |
3842 | |
3843 case ObjCPropertyImplDecl::Synthesize: | |
3844 return CXCursor_ObjCSynthesizeDecl; | |
3845 } | |
3846 llvm_unreachable("Unexpected Kind!"); | |
3847 | |
3848 case Decl::Import: | |
3849 return CXCursor_ModuleImportDecl; | |
3850 | |
3851 case Decl::ObjCTypeParam: | |
3852 return CXCursor_TemplateTypeParameter; | |
3853 | |
3854 default: | |
3855 if (const auto *TD = dyn_cast<TagDecl>(D)) { | |
3856 switch (TD->getTagKind()) { | |
3857 case TTK_Interface: // fall through | |
3858 case TTK_Struct: | |
3859 return CXCursor_StructDecl; | |
3860 case TTK_Class: | |
3861 return CXCursor_ClassDecl; | |
3862 case TTK_Union: | |
3863 return CXCursor_UnionDecl; | |
3864 case TTK_Enum: | |
3865 return CXCursor_EnumDecl; | |
3866 } | |
3867 } | |
3868 } | |
3869 | |
3870 return CXCursor_UnexposedDecl; | |
3871 } | |
3872 | |
3873 static void AddMacroResults(Preprocessor &PP, ResultBuilder &Results, | |
3874 bool LoadExternal, bool IncludeUndefined, | |
3875 bool TargetTypeIsPointer = false) { | |
3876 typedef CodeCompletionResult Result; | |
3877 | |
3878 Results.EnterNewScope(); | |
3879 | |
3880 for (Preprocessor::macro_iterator M = PP.macro_begin(LoadExternal), | |
3881 MEnd = PP.macro_end(LoadExternal); | |
3882 M != MEnd; ++M) { | |
3883 auto MD = PP.getMacroDefinition(M->first); | |
3884 if (IncludeUndefined || MD) { | |
3885 MacroInfo *MI = MD.getMacroInfo(); | |
3886 if (MI && MI->isUsedForHeaderGuard()) | |
3887 continue; | |
3888 | |
3889 Results.AddResult( | |
3890 Result(M->first, MI, | |
3891 getMacroUsagePriority(M->first->getName(), PP.getLangOpts(), | |
3892 TargetTypeIsPointer))); | |
3893 } | |
3894 } | |
3895 | |
3896 Results.ExitScope(); | |
3897 } | |
3898 | |
3899 static void AddPrettyFunctionResults(const LangOptions &LangOpts, | |
3900 ResultBuilder &Results) { | |
3901 typedef CodeCompletionResult Result; | |
3902 | |
3903 Results.EnterNewScope(); | |
3904 | |
3905 Results.AddResult(Result("__PRETTY_FUNCTION__", CCP_Constant)); | |
3906 Results.AddResult(Result("__FUNCTION__", CCP_Constant)); | |
3907 if (LangOpts.C99 || LangOpts.CPlusPlus11) | |
3908 Results.AddResult(Result("__func__", CCP_Constant)); | |
3909 Results.ExitScope(); | |
3910 } | |
3911 | |
3912 static void HandleCodeCompleteResults(Sema *S, | |
3913 CodeCompleteConsumer *CodeCompleter, | |
3914 CodeCompletionContext Context, | |
3915 CodeCompletionResult *Results, | |
3916 unsigned NumResults) { | |
3917 if (CodeCompleter) | |
3918 CodeCompleter->ProcessCodeCompleteResults(*S, Context, Results, NumResults); | |
3919 } | |
3920 | |
3921 static CodeCompletionContext | |
3922 mapCodeCompletionContext(Sema &S, Sema::ParserCompletionContext PCC) { | |
3923 switch (PCC) { | |
3924 case Sema::PCC_Namespace: | |
3925 return CodeCompletionContext::CCC_TopLevel; | |
3926 | |
3927 case Sema::PCC_Class: | |
3928 return CodeCompletionContext::CCC_ClassStructUnion; | |
3929 | |
3930 case Sema::PCC_ObjCInterface: | |
3931 return CodeCompletionContext::CCC_ObjCInterface; | |
3932 | |
3933 case Sema::PCC_ObjCImplementation: | |
3934 return CodeCompletionContext::CCC_ObjCImplementation; | |
3935 | |
3936 case Sema::PCC_ObjCInstanceVariableList: | |
3937 return CodeCompletionContext::CCC_ObjCIvarList; | |
3938 | |
3939 case Sema::PCC_Template: | |
3940 case Sema::PCC_MemberTemplate: | |
3941 if (S.CurContext->isFileContext()) | |
3942 return CodeCompletionContext::CCC_TopLevel; | |
3943 if (S.CurContext->isRecord()) | |
3944 return CodeCompletionContext::CCC_ClassStructUnion; | |
3945 return CodeCompletionContext::CCC_Other; | |
3946 | |
3947 case Sema::PCC_RecoveryInFunction: | |
3948 return CodeCompletionContext::CCC_Recovery; | |
3949 | |
3950 case Sema::PCC_ForInit: | |
3951 if (S.getLangOpts().CPlusPlus || S.getLangOpts().C99 || | |
3952 S.getLangOpts().ObjC) | |
3953 return CodeCompletionContext::CCC_ParenthesizedExpression; | |
3954 else | |
3955 return CodeCompletionContext::CCC_Expression; | |
3956 | |
3957 case Sema::PCC_Expression: | |
3958 return CodeCompletionContext::CCC_Expression; | |
3959 case Sema::PCC_Condition: | |
3960 return CodeCompletionContext(CodeCompletionContext::CCC_Expression, | |
3961 S.getASTContext().BoolTy); | |
3962 | |
3963 case Sema::PCC_Statement: | |
3964 return CodeCompletionContext::CCC_Statement; | |
3965 | |
3966 case Sema::PCC_Type: | |
3967 return CodeCompletionContext::CCC_Type; | |
3968 | |
3969 case Sema::PCC_ParenthesizedExpression: | |
3970 return CodeCompletionContext::CCC_ParenthesizedExpression; | |
3971 | |
3972 case Sema::PCC_LocalDeclarationSpecifiers: | |
3973 return CodeCompletionContext::CCC_Type; | |
3974 } | |
3975 | |
3976 llvm_unreachable("Invalid ParserCompletionContext!"); | |
3977 } | |
3978 | |
3979 /// If we're in a C++ virtual member function, add completion results | |
3980 /// that invoke the functions we override, since it's common to invoke the | |
3981 /// overridden function as well as adding new functionality. | |
3982 /// | |
3983 /// \param S The semantic analysis object for which we are generating results. | |
3984 /// | |
3985 /// \param InContext This context in which the nested-name-specifier preceding | |
3986 /// the code-completion point | |
3987 static void MaybeAddOverrideCalls(Sema &S, DeclContext *InContext, | |
3988 ResultBuilder &Results) { | |
3989 // Look through blocks. | |
3990 DeclContext *CurContext = S.CurContext; | |
3991 while (isa<BlockDecl>(CurContext)) | |
3992 CurContext = CurContext->getParent(); | |
3993 | |
3994 CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(CurContext); | |
3995 if (!Method || !Method->isVirtual()) | |
3996 return; | |
3997 | |
3998 // We need to have names for all of the parameters, if we're going to | |
3999 // generate a forwarding call. | |
4000 for (auto P : Method->parameters()) | |
4001 if (!P->getDeclName()) | |
4002 return; | |
4003 | |
4004 PrintingPolicy Policy = getCompletionPrintingPolicy(S); | |
4005 for (const CXXMethodDecl *Overridden : Method->overridden_methods()) { | |
4006 CodeCompletionBuilder Builder(Results.getAllocator(), | |
4007 Results.getCodeCompletionTUInfo()); | |
4008 if (Overridden->getCanonicalDecl() == Method->getCanonicalDecl()) | |
4009 continue; | |
4010 | |
4011 // If we need a nested-name-specifier, add one now. | |
4012 if (!InContext) { | |
4013 NestedNameSpecifier *NNS = getRequiredQualification( | |
4014 S.Context, CurContext, Overridden->getDeclContext()); | |
4015 if (NNS) { | |
4016 std::string Str; | |
4017 llvm::raw_string_ostream OS(Str); | |
4018 NNS->print(OS, Policy); | |
4019 Builder.AddTextChunk(Results.getAllocator().CopyString(OS.str())); | |
4020 } | |
4021 } else if (!InContext->Equals(Overridden->getDeclContext())) | |
4022 continue; | |
4023 | |
4024 Builder.AddTypedTextChunk( | |
4025 Results.getAllocator().CopyString(Overridden->getNameAsString())); | |
4026 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
4027 bool FirstParam = true; | |
4028 for (auto P : Method->parameters()) { | |
4029 if (FirstParam) | |
4030 FirstParam = false; | |
4031 else | |
4032 Builder.AddChunk(CodeCompletionString::CK_Comma); | |
4033 | |
4034 Builder.AddPlaceholderChunk( | |
4035 Results.getAllocator().CopyString(P->getIdentifier()->getName())); | |
4036 } | |
4037 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
4038 Results.AddResult(CodeCompletionResult( | |
4039 Builder.TakeString(), CCP_SuperCompletion, CXCursor_CXXMethod, | |
4040 CXAvailability_Available, Overridden)); | |
4041 Results.Ignore(Overridden); | |
4042 } | |
4043 } | |
4044 | |
4045 void Sema::CodeCompleteModuleImport(SourceLocation ImportLoc, | |
4046 ModuleIdPath Path) { | |
4047 typedef CodeCompletionResult Result; | |
4048 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
4049 CodeCompleter->getCodeCompletionTUInfo(), | |
4050 CodeCompletionContext::CCC_Other); | |
4051 Results.EnterNewScope(); | |
4052 | |
4053 CodeCompletionAllocator &Allocator = Results.getAllocator(); | |
4054 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); | |
4055 typedef CodeCompletionResult Result; | |
4056 if (Path.empty()) { | |
4057 // Enumerate all top-level modules. | |
4058 SmallVector<Module *, 8> Modules; | |
4059 PP.getHeaderSearchInfo().collectAllModules(Modules); | |
4060 for (unsigned I = 0, N = Modules.size(); I != N; ++I) { | |
4061 Builder.AddTypedTextChunk( | |
4062 Builder.getAllocator().CopyString(Modules[I]->Name)); | |
4063 Results.AddResult(Result( | |
4064 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl, | |
4065 Modules[I]->isAvailable() ? CXAvailability_Available | |
4066 : CXAvailability_NotAvailable)); | |
4067 } | |
4068 } else if (getLangOpts().Modules) { | |
4069 // Load the named module. | |
4070 Module *Mod = | |
4071 PP.getModuleLoader().loadModule(ImportLoc, Path, Module::AllVisible, | |
4072 /*IsInclusionDirective=*/false); | |
4073 // Enumerate submodules. | |
4074 if (Mod) { | |
4075 for (Module::submodule_iterator Sub = Mod->submodule_begin(), | |
4076 SubEnd = Mod->submodule_end(); | |
4077 Sub != SubEnd; ++Sub) { | |
4078 | |
4079 Builder.AddTypedTextChunk( | |
4080 Builder.getAllocator().CopyString((*Sub)->Name)); | |
4081 Results.AddResult(Result( | |
4082 Builder.TakeString(), CCP_Declaration, CXCursor_ModuleImportDecl, | |
4083 (*Sub)->isAvailable() ? CXAvailability_Available | |
4084 : CXAvailability_NotAvailable)); | |
4085 } | |
4086 } | |
4087 } | |
4088 Results.ExitScope(); | |
4089 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
4090 Results.data(), Results.size()); | |
4091 } | |
4092 | |
4093 void Sema::CodeCompleteOrdinaryName(Scope *S, | |
4094 ParserCompletionContext CompletionContext) { | |
4095 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
4096 CodeCompleter->getCodeCompletionTUInfo(), | |
4097 mapCodeCompletionContext(*this, CompletionContext)); | |
4098 Results.EnterNewScope(); | |
4099 | |
4100 // Determine how to filter results, e.g., so that the names of | |
4101 // values (functions, enumerators, function templates, etc.) are | |
4102 // only allowed where we can have an expression. | |
4103 switch (CompletionContext) { | |
4104 case PCC_Namespace: | |
4105 case PCC_Class: | |
4106 case PCC_ObjCInterface: | |
4107 case PCC_ObjCImplementation: | |
4108 case PCC_ObjCInstanceVariableList: | |
4109 case PCC_Template: | |
4110 case PCC_MemberTemplate: | |
4111 case PCC_Type: | |
4112 case PCC_LocalDeclarationSpecifiers: | |
4113 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); | |
4114 break; | |
4115 | |
4116 case PCC_Statement: | |
4117 case PCC_ParenthesizedExpression: | |
4118 case PCC_Expression: | |
4119 case PCC_ForInit: | |
4120 case PCC_Condition: | |
4121 if (WantTypesInContext(CompletionContext, getLangOpts())) | |
4122 Results.setFilter(&ResultBuilder::IsOrdinaryName); | |
4123 else | |
4124 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); | |
4125 | |
4126 if (getLangOpts().CPlusPlus) | |
4127 MaybeAddOverrideCalls(*this, /*InContext=*/nullptr, Results); | |
4128 break; | |
4129 | |
4130 case PCC_RecoveryInFunction: | |
4131 // Unfiltered | |
4132 break; | |
4133 } | |
4134 | |
4135 // If we are in a C++ non-static member function, check the qualifiers on | |
4136 // the member function to filter/prioritize the results list. | |
4137 auto ThisType = getCurrentThisType(); | |
4138 if (!ThisType.isNull()) | |
4139 Results.setObjectTypeQualifiers(ThisType->getPointeeType().getQualifiers(), | |
4140 VK_LValue); | |
4141 | |
4142 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
4143 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
4144 CodeCompleter->includeGlobals(), | |
4145 CodeCompleter->loadExternal()); | |
4146 | |
4147 AddOrdinaryNameResults(CompletionContext, S, *this, Results); | |
4148 Results.ExitScope(); | |
4149 | |
4150 switch (CompletionContext) { | |
4151 case PCC_ParenthesizedExpression: | |
4152 case PCC_Expression: | |
4153 case PCC_Statement: | |
4154 case PCC_RecoveryInFunction: | |
4155 if (S->getFnParent()) | |
4156 AddPrettyFunctionResults(getLangOpts(), Results); | |
4157 break; | |
4158 | |
4159 case PCC_Namespace: | |
4160 case PCC_Class: | |
4161 case PCC_ObjCInterface: | |
4162 case PCC_ObjCImplementation: | |
4163 case PCC_ObjCInstanceVariableList: | |
4164 case PCC_Template: | |
4165 case PCC_MemberTemplate: | |
4166 case PCC_ForInit: | |
4167 case PCC_Condition: | |
4168 case PCC_Type: | |
4169 case PCC_LocalDeclarationSpecifiers: | |
4170 break; | |
4171 } | |
4172 | |
4173 if (CodeCompleter->includeMacros()) | |
4174 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); | |
4175 | |
4176 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
4177 Results.data(), Results.size()); | |
4178 } | |
4179 | |
4180 static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, | |
4181 ParsedType Receiver, | |
4182 ArrayRef<IdentifierInfo *> SelIdents, | |
4183 bool AtArgumentExpression, bool IsSuper, | |
4184 ResultBuilder &Results); | |
4185 | |
4186 void Sema::CodeCompleteDeclSpec(Scope *S, DeclSpec &DS, | |
4187 bool AllowNonIdentifiers, | |
4188 bool AllowNestedNameSpecifiers) { | |
4189 typedef CodeCompletionResult Result; | |
4190 ResultBuilder Results( | |
4191 *this, CodeCompleter->getAllocator(), | |
4192 CodeCompleter->getCodeCompletionTUInfo(), | |
4193 AllowNestedNameSpecifiers | |
4194 // FIXME: Try to separate codepath leading here to deduce whether we | |
4195 // need an existing symbol or a new one. | |
4196 ? CodeCompletionContext::CCC_SymbolOrNewName | |
4197 : CodeCompletionContext::CCC_NewName); | |
4198 Results.EnterNewScope(); | |
4199 | |
4200 // Type qualifiers can come after names. | |
4201 Results.AddResult(Result("const")); | |
4202 Results.AddResult(Result("volatile")); | |
4203 if (getLangOpts().C99) | |
4204 Results.AddResult(Result("restrict")); | |
4205 | |
4206 if (getLangOpts().CPlusPlus) { | |
4207 if (getLangOpts().CPlusPlus11 && | |
4208 (DS.getTypeSpecType() == DeclSpec::TST_class || | |
4209 DS.getTypeSpecType() == DeclSpec::TST_struct)) | |
4210 Results.AddResult("final"); | |
4211 | |
4212 if (AllowNonIdentifiers) { | |
4213 Results.AddResult(Result("operator")); | |
4214 } | |
4215 | |
4216 // Add nested-name-specifiers. | |
4217 if (AllowNestedNameSpecifiers) { | |
4218 Results.allowNestedNameSpecifiers(); | |
4219 Results.setFilter(&ResultBuilder::IsImpossibleToSatisfy); | |
4220 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
4221 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, | |
4222 CodeCompleter->includeGlobals(), | |
4223 CodeCompleter->loadExternal()); | |
4224 Results.setFilter(nullptr); | |
4225 } | |
4226 } | |
4227 Results.ExitScope(); | |
4228 | |
4229 // If we're in a context where we might have an expression (rather than a | |
4230 // declaration), and what we've seen so far is an Objective-C type that could | |
4231 // be a receiver of a class message, this may be a class message send with | |
4232 // the initial opening bracket '[' missing. Add appropriate completions. | |
4233 if (AllowNonIdentifiers && !AllowNestedNameSpecifiers && | |
4234 DS.getParsedSpecifiers() == DeclSpec::PQ_TypeSpecifier && | |
4235 DS.getTypeSpecType() == DeclSpec::TST_typename && | |
4236 DS.getTypeSpecComplex() == DeclSpec::TSC_unspecified && | |
4237 DS.getTypeSpecSign() == DeclSpec::TSS_unspecified && | |
4238 !DS.isTypeAltiVecVector() && S && | |
4239 (S->getFlags() & Scope::DeclScope) != 0 && | |
4240 (S->getFlags() & (Scope::ClassScope | Scope::TemplateParamScope | | |
4241 Scope::FunctionPrototypeScope | Scope::AtCatchScope)) == | |
4242 0) { | |
4243 ParsedType T = DS.getRepAsType(); | |
4244 if (!T.get().isNull() && T.get()->isObjCObjectOrInterfaceType()) | |
4245 AddClassMessageCompletions(*this, S, T, None, false, false, Results); | |
4246 } | |
4247 | |
4248 // Note that we intentionally suppress macro results here, since we do not | |
4249 // encourage using macros to produce the names of entities. | |
4250 | |
4251 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
4252 Results.data(), Results.size()); | |
4253 } | |
4254 | |
4255 struct Sema::CodeCompleteExpressionData { | |
4256 CodeCompleteExpressionData(QualType PreferredType = QualType(), | |
4257 bool IsParenthesized = false) | |
4258 : PreferredType(PreferredType), IntegralConstantExpression(false), | |
4259 ObjCCollection(false), IsParenthesized(IsParenthesized) {} | |
4260 | |
4261 QualType PreferredType; | |
4262 bool IntegralConstantExpression; | |
4263 bool ObjCCollection; | |
4264 bool IsParenthesized; | |
4265 SmallVector<Decl *, 4> IgnoreDecls; | |
4266 }; | |
4267 | |
4268 namespace { | |
4269 /// Information that allows to avoid completing redundant enumerators. | |
4270 struct CoveredEnumerators { | |
4271 llvm::SmallPtrSet<EnumConstantDecl *, 8> Seen; | |
4272 NestedNameSpecifier *SuggestedQualifier = nullptr; | |
4273 }; | |
4274 } // namespace | |
4275 | |
4276 static void AddEnumerators(ResultBuilder &Results, ASTContext &Context, | |
4277 EnumDecl *Enum, DeclContext *CurContext, | |
4278 const CoveredEnumerators &Enumerators) { | |
4279 NestedNameSpecifier *Qualifier = Enumerators.SuggestedQualifier; | |
4280 if (Context.getLangOpts().CPlusPlus && !Qualifier && Enumerators.Seen.empty()) { | |
4281 // If there are no prior enumerators in C++, check whether we have to | |
4282 // qualify the names of the enumerators that we suggest, because they | |
4283 // may not be visible in this scope. | |
4284 Qualifier = getRequiredQualification(Context, CurContext, Enum); | |
4285 } | |
4286 | |
4287 Results.EnterNewScope(); | |
4288 for (auto *E : Enum->enumerators()) { | |
4289 if (Enumerators.Seen.count(E)) | |
4290 continue; | |
4291 | |
4292 CodeCompletionResult R(E, CCP_EnumInCase, Qualifier); | |
4293 Results.AddResult(R, CurContext, nullptr, false); | |
4294 } | |
4295 Results.ExitScope(); | |
4296 } | |
4297 | |
4298 /// Try to find a corresponding FunctionProtoType for function-like types (e.g. | |
4299 /// function pointers, std::function, etc). | |
4300 static const FunctionProtoType *TryDeconstructFunctionLike(QualType T) { | |
4301 assert(!T.isNull()); | |
4302 // Try to extract first template argument from std::function<> and similar. | |
4303 // Note we only handle the sugared types, they closely match what users wrote. | |
4304 // We explicitly choose to not handle ClassTemplateSpecializationDecl. | |
4305 if (auto *Specialization = T->getAs<TemplateSpecializationType>()) { | |
4306 if (Specialization->getNumArgs() != 1) | |
4307 return nullptr; | |
4308 const TemplateArgument &Argument = Specialization->getArg(0); | |
4309 if (Argument.getKind() != TemplateArgument::Type) | |
4310 return nullptr; | |
4311 return Argument.getAsType()->getAs<FunctionProtoType>(); | |
4312 } | |
4313 // Handle other cases. | |
4314 if (T->isPointerType()) | |
4315 T = T->getPointeeType(); | |
4316 return T->getAs<FunctionProtoType>(); | |
4317 } | |
4318 | |
4319 /// Adds a pattern completion for a lambda expression with the specified | |
4320 /// parameter types and placeholders for parameter names. | |
4321 static void AddLambdaCompletion(ResultBuilder &Results, | |
4322 llvm::ArrayRef<QualType> Parameters, | |
4323 const LangOptions &LangOpts) { | |
4324 if (!Results.includeCodePatterns()) | |
4325 return; | |
4326 CodeCompletionBuilder Completion(Results.getAllocator(), | |
4327 Results.getCodeCompletionTUInfo()); | |
4328 // [](<parameters>) {} | |
4329 Completion.AddChunk(CodeCompletionString::CK_LeftBracket); | |
4330 Completion.AddPlaceholderChunk("="); | |
4331 Completion.AddChunk(CodeCompletionString::CK_RightBracket); | |
4332 if (!Parameters.empty()) { | |
4333 Completion.AddChunk(CodeCompletionString::CK_LeftParen); | |
4334 bool First = true; | |
4335 for (auto Parameter : Parameters) { | |
4336 if (!First) | |
4337 Completion.AddChunk(CodeCompletionString::ChunkKind::CK_Comma); | |
4338 else | |
4339 First = false; | |
4340 | |
4341 constexpr llvm::StringLiteral NamePlaceholder = "!#!NAME_GOES_HERE!#!"; | |
4342 std::string Type = std::string(NamePlaceholder); | |
4343 Parameter.getAsStringInternal(Type, PrintingPolicy(LangOpts)); | |
4344 llvm::StringRef Prefix, Suffix; | |
4345 std::tie(Prefix, Suffix) = llvm::StringRef(Type).split(NamePlaceholder); | |
4346 Prefix = Prefix.rtrim(); | |
4347 Suffix = Suffix.ltrim(); | |
4348 | |
4349 Completion.AddTextChunk(Completion.getAllocator().CopyString(Prefix)); | |
4350 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
4351 Completion.AddPlaceholderChunk("parameter"); | |
4352 Completion.AddTextChunk(Completion.getAllocator().CopyString(Suffix)); | |
4353 }; | |
4354 Completion.AddChunk(CodeCompletionString::CK_RightParen); | |
4355 } | |
4356 Completion.AddChunk(clang::CodeCompletionString::CK_HorizontalSpace); | |
4357 Completion.AddChunk(CodeCompletionString::CK_LeftBrace); | |
4358 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
4359 Completion.AddPlaceholderChunk("body"); | |
4360 Completion.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
4361 Completion.AddChunk(CodeCompletionString::CK_RightBrace); | |
4362 | |
4363 Results.AddResult(Completion.TakeString()); | |
4364 } | |
4365 | |
4366 /// Perform code-completion in an expression context when we know what | |
4367 /// type we're looking for. | |
4368 void Sema::CodeCompleteExpression(Scope *S, | |
4369 const CodeCompleteExpressionData &Data) { | |
4370 ResultBuilder Results( | |
4371 *this, CodeCompleter->getAllocator(), | |
4372 CodeCompleter->getCodeCompletionTUInfo(), | |
4373 CodeCompletionContext( | |
4374 Data.IsParenthesized | |
4375 ? CodeCompletionContext::CCC_ParenthesizedExpression | |
4376 : CodeCompletionContext::CCC_Expression, | |
4377 Data.PreferredType)); | |
4378 auto PCC = | |
4379 Data.IsParenthesized ? PCC_ParenthesizedExpression : PCC_Expression; | |
4380 if (Data.ObjCCollection) | |
4381 Results.setFilter(&ResultBuilder::IsObjCCollection); | |
4382 else if (Data.IntegralConstantExpression) | |
4383 Results.setFilter(&ResultBuilder::IsIntegralConstantValue); | |
4384 else if (WantTypesInContext(PCC, getLangOpts())) | |
4385 Results.setFilter(&ResultBuilder::IsOrdinaryName); | |
4386 else | |
4387 Results.setFilter(&ResultBuilder::IsOrdinaryNonTypeName); | |
4388 | |
4389 if (!Data.PreferredType.isNull()) | |
4390 Results.setPreferredType(Data.PreferredType.getNonReferenceType()); | |
4391 | |
4392 // Ignore any declarations that we were told that we don't care about. | |
4393 for (unsigned I = 0, N = Data.IgnoreDecls.size(); I != N; ++I) | |
4394 Results.Ignore(Data.IgnoreDecls[I]); | |
4395 | |
4396 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
4397 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
4398 CodeCompleter->includeGlobals(), | |
4399 CodeCompleter->loadExternal()); | |
4400 | |
4401 Results.EnterNewScope(); | |
4402 AddOrdinaryNameResults(PCC, S, *this, Results); | |
4403 Results.ExitScope(); | |
4404 | |
4405 bool PreferredTypeIsPointer = false; | |
4406 if (!Data.PreferredType.isNull()) { | |
4407 PreferredTypeIsPointer = Data.PreferredType->isAnyPointerType() || | |
4408 Data.PreferredType->isMemberPointerType() || | |
4409 Data.PreferredType->isBlockPointerType(); | |
4410 if (Data.PreferredType->isEnumeralType()) { | |
4411 EnumDecl *Enum = Data.PreferredType->castAs<EnumType>()->getDecl(); | |
4412 if (auto *Def = Enum->getDefinition()) | |
4413 Enum = Def; | |
4414 // FIXME: collect covered enumerators in cases like: | |
4415 // if (x == my_enum::one) { ... } else if (x == ^) {} | |
4416 AddEnumerators(Results, Context, Enum, CurContext, CoveredEnumerators()); | |
4417 } | |
4418 } | |
4419 | |
4420 if (S->getFnParent() && !Data.ObjCCollection && | |
4421 !Data.IntegralConstantExpression) | |
4422 AddPrettyFunctionResults(getLangOpts(), Results); | |
4423 | |
4424 if (CodeCompleter->includeMacros()) | |
4425 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false, | |
4426 PreferredTypeIsPointer); | |
4427 | |
4428 // Complete a lambda expression when preferred type is a function. | |
4429 if (!Data.PreferredType.isNull() && getLangOpts().CPlusPlus11) { | |
4430 if (const FunctionProtoType *F = | |
4431 TryDeconstructFunctionLike(Data.PreferredType)) | |
4432 AddLambdaCompletion(Results, F->getParamTypes(), getLangOpts()); | |
4433 } | |
4434 | |
4435 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
4436 Results.data(), Results.size()); | |
4437 } | |
4438 | |
4439 void Sema::CodeCompleteExpression(Scope *S, QualType PreferredType, | |
4440 bool IsParenthesized) { | |
4441 return CodeCompleteExpression( | |
4442 S, CodeCompleteExpressionData(PreferredType, IsParenthesized)); | |
4443 } | |
4444 | |
4445 void Sema::CodeCompletePostfixExpression(Scope *S, ExprResult E, | |
4446 QualType PreferredType) { | |
4447 if (E.isInvalid()) | |
4448 CodeCompleteExpression(S, PreferredType); | |
4449 else if (getLangOpts().ObjC) | |
4450 CodeCompleteObjCInstanceMessage(S, E.get(), None, false); | |
4451 } | |
4452 | |
4453 /// The set of properties that have already been added, referenced by | |
4454 /// property name. | |
4455 typedef llvm::SmallPtrSet<IdentifierInfo *, 16> AddedPropertiesSet; | |
4456 | |
4457 /// Retrieve the container definition, if any? | |
4458 static ObjCContainerDecl *getContainerDef(ObjCContainerDecl *Container) { | |
4459 if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { | |
4460 if (Interface->hasDefinition()) | |
4461 return Interface->getDefinition(); | |
4462 | |
4463 return Interface; | |
4464 } | |
4465 | |
4466 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { | |
4467 if (Protocol->hasDefinition()) | |
4468 return Protocol->getDefinition(); | |
4469 | |
4470 return Protocol; | |
4471 } | |
4472 return Container; | |
4473 } | |
4474 | |
4475 /// Adds a block invocation code completion result for the given block | |
4476 /// declaration \p BD. | |
4477 static void AddObjCBlockCall(ASTContext &Context, const PrintingPolicy &Policy, | |
4478 CodeCompletionBuilder &Builder, | |
4479 const NamedDecl *BD, | |
4480 const FunctionTypeLoc &BlockLoc, | |
4481 const FunctionProtoTypeLoc &BlockProtoLoc) { | |
4482 Builder.AddResultTypeChunk( | |
4483 GetCompletionTypeString(BlockLoc.getReturnLoc().getType(), Context, | |
4484 Policy, Builder.getAllocator())); | |
4485 | |
4486 AddTypedNameChunk(Context, Policy, BD, Builder); | |
4487 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
4488 | |
4489 if (BlockProtoLoc && BlockProtoLoc.getTypePtr()->isVariadic()) { | |
4490 Builder.AddPlaceholderChunk("..."); | |
4491 } else { | |
4492 for (unsigned I = 0, N = BlockLoc.getNumParams(); I != N; ++I) { | |
4493 if (I) | |
4494 Builder.AddChunk(CodeCompletionString::CK_Comma); | |
4495 | |
4496 // Format the placeholder string. | |
4497 std::string PlaceholderStr = | |
4498 FormatFunctionParameter(Policy, BlockLoc.getParam(I)); | |
4499 | |
4500 if (I == N - 1 && BlockProtoLoc && | |
4501 BlockProtoLoc.getTypePtr()->isVariadic()) | |
4502 PlaceholderStr += ", ..."; | |
4503 | |
4504 // Add the placeholder string. | |
4505 Builder.AddPlaceholderChunk( | |
4506 Builder.getAllocator().CopyString(PlaceholderStr)); | |
4507 } | |
4508 } | |
4509 | |
4510 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
4511 } | |
4512 | |
4513 static void | |
4514 AddObjCProperties(const CodeCompletionContext &CCContext, | |
4515 ObjCContainerDecl *Container, bool AllowCategories, | |
4516 bool AllowNullaryMethods, DeclContext *CurContext, | |
4517 AddedPropertiesSet &AddedProperties, ResultBuilder &Results, | |
4518 bool IsBaseExprStatement = false, | |
4519 bool IsClassProperty = false, bool InOriginalClass = true) { | |
4520 typedef CodeCompletionResult Result; | |
4521 | |
4522 // Retrieve the definition. | |
4523 Container = getContainerDef(Container); | |
4524 | |
4525 // Add properties in this container. | |
4526 const auto AddProperty = [&](const ObjCPropertyDecl *P) { | |
4527 if (!AddedProperties.insert(P->getIdentifier()).second) | |
4528 return; | |
4529 | |
4530 // FIXME: Provide block invocation completion for non-statement | |
4531 // expressions. | |
4532 if (!P->getType().getTypePtr()->isBlockPointerType() || | |
4533 !IsBaseExprStatement) { | |
4534 Result R = Result(P, Results.getBasePriority(P), nullptr); | |
4535 if (!InOriginalClass) | |
4536 setInBaseClass(R); | |
4537 Results.MaybeAddResult(R, CurContext); | |
4538 return; | |
4539 } | |
4540 | |
4541 // Block setter and invocation completion is provided only when we are able | |
4542 // to find the FunctionProtoTypeLoc with parameter names for the block. | |
4543 FunctionTypeLoc BlockLoc; | |
4544 FunctionProtoTypeLoc BlockProtoLoc; | |
4545 findTypeLocationForBlockDecl(P->getTypeSourceInfo(), BlockLoc, | |
4546 BlockProtoLoc); | |
4547 if (!BlockLoc) { | |
4548 Result R = Result(P, Results.getBasePriority(P), nullptr); | |
4549 if (!InOriginalClass) | |
4550 setInBaseClass(R); | |
4551 Results.MaybeAddResult(R, CurContext); | |
4552 return; | |
4553 } | |
4554 | |
4555 // The default completion result for block properties should be the block | |
4556 // invocation completion when the base expression is a statement. | |
4557 CodeCompletionBuilder Builder(Results.getAllocator(), | |
4558 Results.getCodeCompletionTUInfo()); | |
4559 AddObjCBlockCall(Container->getASTContext(), | |
4560 getCompletionPrintingPolicy(Results.getSema()), Builder, P, | |
4561 BlockLoc, BlockProtoLoc); | |
4562 Result R = Result(Builder.TakeString(), P, Results.getBasePriority(P)); | |
4563 if (!InOriginalClass) | |
4564 setInBaseClass(R); | |
4565 Results.MaybeAddResult(R, CurContext); | |
4566 | |
4567 // Provide additional block setter completion iff the base expression is a | |
4568 // statement and the block property is mutable. | |
4569 if (!P->isReadOnly()) { | |
4570 CodeCompletionBuilder Builder(Results.getAllocator(), | |
4571 Results.getCodeCompletionTUInfo()); | |
4572 AddResultTypeChunk(Container->getASTContext(), | |
4573 getCompletionPrintingPolicy(Results.getSema()), P, | |
4574 CCContext.getBaseType(), Builder); | |
4575 Builder.AddTypedTextChunk( | |
4576 Results.getAllocator().CopyString(P->getName())); | |
4577 Builder.AddChunk(CodeCompletionString::CK_Equal); | |
4578 | |
4579 std::string PlaceholderStr = formatBlockPlaceholder( | |
4580 getCompletionPrintingPolicy(Results.getSema()), P, BlockLoc, | |
4581 BlockProtoLoc, /*SuppressBlockName=*/true); | |
4582 // Add the placeholder string. | |
4583 Builder.AddPlaceholderChunk( | |
4584 Builder.getAllocator().CopyString(PlaceholderStr)); | |
4585 | |
4586 // When completing blocks properties that return void the default | |
4587 // property completion result should show up before the setter, | |
4588 // otherwise the setter completion should show up before the default | |
4589 // property completion, as we normally want to use the result of the | |
4590 // call. | |
4591 Result R = | |
4592 Result(Builder.TakeString(), P, | |
4593 Results.getBasePriority(P) + | |
4594 (BlockLoc.getTypePtr()->getReturnType()->isVoidType() | |
4595 ? CCD_BlockPropertySetter | |
4596 : -CCD_BlockPropertySetter)); | |
4597 if (!InOriginalClass) | |
4598 setInBaseClass(R); | |
4599 Results.MaybeAddResult(R, CurContext); | |
4600 } | |
4601 }; | |
4602 | |
4603 if (IsClassProperty) { | |
4604 for (const auto *P : Container->class_properties()) | |
4605 AddProperty(P); | |
4606 } else { | |
4607 for (const auto *P : Container->instance_properties()) | |
4608 AddProperty(P); | |
4609 } | |
4610 | |
4611 // Add nullary methods or implicit class properties | |
4612 if (AllowNullaryMethods) { | |
4613 ASTContext &Context = Container->getASTContext(); | |
4614 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema()); | |
4615 // Adds a method result | |
4616 const auto AddMethod = [&](const ObjCMethodDecl *M) { | |
4617 IdentifierInfo *Name = M->getSelector().getIdentifierInfoForSlot(0); | |
4618 if (!Name) | |
4619 return; | |
4620 if (!AddedProperties.insert(Name).second) | |
4621 return; | |
4622 CodeCompletionBuilder Builder(Results.getAllocator(), | |
4623 Results.getCodeCompletionTUInfo()); | |
4624 AddResultTypeChunk(Context, Policy, M, CCContext.getBaseType(), Builder); | |
4625 Builder.AddTypedTextChunk( | |
4626 Results.getAllocator().CopyString(Name->getName())); | |
4627 Result R = Result(Builder.TakeString(), M, | |
4628 CCP_MemberDeclaration + CCD_MethodAsProperty); | |
4629 if (!InOriginalClass) | |
4630 setInBaseClass(R); | |
4631 Results.MaybeAddResult(R, CurContext); | |
4632 }; | |
4633 | |
4634 if (IsClassProperty) { | |
4635 for (const auto *M : Container->methods()) { | |
4636 // Gather the class method that can be used as implicit property | |
4637 // getters. Methods with arguments or methods that return void aren't | |
4638 // added to the results as they can't be used as a getter. | |
4639 if (!M->getSelector().isUnarySelector() || | |
4640 M->getReturnType()->isVoidType() || M->isInstanceMethod()) | |
4641 continue; | |
4642 AddMethod(M); | |
4643 } | |
4644 } else { | |
4645 for (auto *M : Container->methods()) { | |
4646 if (M->getSelector().isUnarySelector()) | |
4647 AddMethod(M); | |
4648 } | |
4649 } | |
4650 } | |
4651 | |
4652 // Add properties in referenced protocols. | |
4653 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { | |
4654 for (auto *P : Protocol->protocols()) | |
4655 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods, | |
4656 CurContext, AddedProperties, Results, | |
4657 IsBaseExprStatement, IsClassProperty, | |
4658 /*InOriginalClass*/ false); | |
4659 } else if (ObjCInterfaceDecl *IFace = | |
4660 dyn_cast<ObjCInterfaceDecl>(Container)) { | |
4661 if (AllowCategories) { | |
4662 // Look through categories. | |
4663 for (auto *Cat : IFace->known_categories()) | |
4664 AddObjCProperties(CCContext, Cat, AllowCategories, AllowNullaryMethods, | |
4665 CurContext, AddedProperties, Results, | |
4666 IsBaseExprStatement, IsClassProperty, | |
4667 InOriginalClass); | |
4668 } | |
4669 | |
4670 // Look through protocols. | |
4671 for (auto *I : IFace->all_referenced_protocols()) | |
4672 AddObjCProperties(CCContext, I, AllowCategories, AllowNullaryMethods, | |
4673 CurContext, AddedProperties, Results, | |
4674 IsBaseExprStatement, IsClassProperty, | |
4675 /*InOriginalClass*/ false); | |
4676 | |
4677 // Look in the superclass. | |
4678 if (IFace->getSuperClass()) | |
4679 AddObjCProperties(CCContext, IFace->getSuperClass(), AllowCategories, | |
4680 AllowNullaryMethods, CurContext, AddedProperties, | |
4681 Results, IsBaseExprStatement, IsClassProperty, | |
4682 /*InOriginalClass*/ false); | |
4683 } else if (const auto *Category = | |
4684 dyn_cast<ObjCCategoryDecl>(Container)) { | |
4685 // Look through protocols. | |
4686 for (auto *P : Category->protocols()) | |
4687 AddObjCProperties(CCContext, P, AllowCategories, AllowNullaryMethods, | |
4688 CurContext, AddedProperties, Results, | |
4689 IsBaseExprStatement, IsClassProperty, | |
4690 /*InOriginalClass*/ false); | |
4691 } | |
4692 } | |
4693 | |
4694 static void AddRecordMembersCompletionResults( | |
4695 Sema &SemaRef, ResultBuilder &Results, Scope *S, QualType BaseType, | |
4696 ExprValueKind BaseKind, RecordDecl *RD, Optional<FixItHint> AccessOpFixIt) { | |
4697 // Indicate that we are performing a member access, and the cv-qualifiers | |
4698 // for the base object type. | |
4699 Results.setObjectTypeQualifiers(BaseType.getQualifiers(), BaseKind); | |
4700 | |
4701 // Access to a C/C++ class, struct, or union. | |
4702 Results.allowNestedNameSpecifiers(); | |
4703 std::vector<FixItHint> FixIts; | |
4704 if (AccessOpFixIt) | |
4705 FixIts.emplace_back(AccessOpFixIt.getValue()); | |
4706 CodeCompletionDeclConsumer Consumer(Results, RD, BaseType, std::move(FixIts)); | |
4707 SemaRef.LookupVisibleDecls(RD, Sema::LookupMemberName, Consumer, | |
4708 SemaRef.CodeCompleter->includeGlobals(), | |
4709 /*IncludeDependentBases=*/true, | |
4710 SemaRef.CodeCompleter->loadExternal()); | |
4711 | |
4712 if (SemaRef.getLangOpts().CPlusPlus) { | |
4713 if (!Results.empty()) { | |
4714 // The "template" keyword can follow "->" or "." in the grammar. | |
4715 // However, we only want to suggest the template keyword if something | |
4716 // is dependent. | |
4717 bool IsDependent = BaseType->isDependentType(); | |
4718 if (!IsDependent) { | |
4719 for (Scope *DepScope = S; DepScope; DepScope = DepScope->getParent()) | |
4720 if (DeclContext *Ctx = DepScope->getEntity()) { | |
4721 IsDependent = Ctx->isDependentContext(); | |
4722 break; | |
4723 } | |
4724 } | |
4725 | |
4726 if (IsDependent) | |
4727 Results.AddResult(CodeCompletionResult("template")); | |
4728 } | |
4729 } | |
4730 } | |
4731 | |
4732 // Returns the RecordDecl inside the BaseType, falling back to primary template | |
4733 // in case of specializations. Since we might not have a decl for the | |
4734 // instantiation/specialization yet, e.g. dependent code. | |
4735 static RecordDecl *getAsRecordDecl(const QualType BaseType) { | |
4736 if (auto *RD = BaseType->getAsRecordDecl()) | |
4737 return RD; | |
4738 | |
4739 if (const auto *TST = BaseType->getAs<TemplateSpecializationType>()) { | |
4740 if (const auto *TD = dyn_cast_or_null<ClassTemplateDecl>( | |
4741 TST->getTemplateName().getAsTemplateDecl())) { | |
4742 return TD->getTemplatedDecl(); | |
4743 } | |
4744 } | |
4745 | |
4746 return nullptr; | |
4747 } | |
4748 | |
4749 void Sema::CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, | |
4750 Expr *OtherOpBase, | |
4751 SourceLocation OpLoc, bool IsArrow, | |
4752 bool IsBaseExprStatement, | |
4753 QualType PreferredType) { | |
4754 if (!Base || !CodeCompleter) | |
4755 return; | |
4756 | |
4757 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); | |
4758 if (ConvertedBase.isInvalid()) | |
4759 return; | |
4760 QualType ConvertedBaseType = ConvertedBase.get()->getType(); | |
4761 | |
4762 enum CodeCompletionContext::Kind contextKind; | |
4763 | |
4764 if (IsArrow) { | |
4765 if (const auto *Ptr = ConvertedBaseType->getAs<PointerType>()) | |
4766 ConvertedBaseType = Ptr->getPointeeType(); | |
4767 } | |
4768 | |
4769 if (IsArrow) { | |
4770 contextKind = CodeCompletionContext::CCC_ArrowMemberAccess; | |
4771 } else { | |
4772 if (ConvertedBaseType->isObjCObjectPointerType() || | |
4773 ConvertedBaseType->isObjCObjectOrInterfaceType()) { | |
4774 contextKind = CodeCompletionContext::CCC_ObjCPropertyAccess; | |
4775 } else { | |
4776 contextKind = CodeCompletionContext::CCC_DotMemberAccess; | |
4777 } | |
4778 } | |
4779 | |
4780 CodeCompletionContext CCContext(contextKind, ConvertedBaseType); | |
4781 CCContext.setPreferredType(PreferredType); | |
4782 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
4783 CodeCompleter->getCodeCompletionTUInfo(), CCContext, | |
4784 &ResultBuilder::IsMember); | |
4785 | |
4786 auto DoCompletion = [&](Expr *Base, bool IsArrow, | |
4787 Optional<FixItHint> AccessOpFixIt) -> bool { | |
4788 if (!Base) | |
4789 return false; | |
4790 | |
4791 ExprResult ConvertedBase = PerformMemberExprBaseConversion(Base, IsArrow); | |
4792 if (ConvertedBase.isInvalid()) | |
4793 return false; | |
4794 Base = ConvertedBase.get(); | |
4795 | |
4796 QualType BaseType = Base->getType(); | |
4797 if (BaseType.isNull()) | |
4798 return false; | |
4799 ExprValueKind BaseKind = Base->getValueKind(); | |
4800 | |
4801 if (IsArrow) { | |
4802 if (const PointerType *Ptr = BaseType->getAs<PointerType>()) { | |
4803 BaseType = Ptr->getPointeeType(); | |
4804 BaseKind = VK_LValue; | |
4805 } else if (BaseType->isObjCObjectPointerType()) | |
4806 /*Do nothing*/; | |
4807 else | |
4808 return false; | |
4809 } | |
4810 | |
4811 if (RecordDecl *RD = getAsRecordDecl(BaseType)) { | |
4812 AddRecordMembersCompletionResults(*this, Results, S, BaseType, BaseKind, | |
4813 RD, std::move(AccessOpFixIt)); | |
4814 } else if (!IsArrow && BaseType->isObjCObjectPointerType()) { | |
4815 // Objective-C property reference. | |
4816 AddedPropertiesSet AddedProperties; | |
4817 | |
4818 if (const ObjCObjectPointerType *ObjCPtr = | |
4819 BaseType->getAsObjCInterfacePointerType()) { | |
4820 // Add property results based on our interface. | |
4821 assert(ObjCPtr && "Non-NULL pointer guaranteed above!"); | |
4822 AddObjCProperties(CCContext, ObjCPtr->getInterfaceDecl(), true, | |
4823 /*AllowNullaryMethods=*/true, CurContext, | |
4824 AddedProperties, Results, IsBaseExprStatement); | |
4825 } | |
4826 | |
4827 // Add properties from the protocols in a qualified interface. | |
4828 for (auto *I : BaseType->castAs<ObjCObjectPointerType>()->quals()) | |
4829 AddObjCProperties(CCContext, I, true, /*AllowNullaryMethods=*/true, | |
4830 CurContext, AddedProperties, Results, | |
4831 IsBaseExprStatement, /*IsClassProperty*/ false, | |
4832 /*InOriginalClass*/ false); | |
4833 } else if ((IsArrow && BaseType->isObjCObjectPointerType()) || | |
4834 (!IsArrow && BaseType->isObjCObjectType())) { | |
4835 // Objective-C instance variable access. | |
4836 ObjCInterfaceDecl *Class = nullptr; | |
4837 if (const ObjCObjectPointerType *ObjCPtr = | |
4838 BaseType->getAs<ObjCObjectPointerType>()) | |
4839 Class = ObjCPtr->getInterfaceDecl(); | |
4840 else | |
4841 Class = BaseType->castAs<ObjCObjectType>()->getInterface(); | |
4842 | |
4843 // Add all ivars from this class and its superclasses. | |
4844 if (Class) { | |
4845 CodeCompletionDeclConsumer Consumer(Results, Class, BaseType); | |
4846 Results.setFilter(&ResultBuilder::IsObjCIvar); | |
4847 LookupVisibleDecls( | |
4848 Class, LookupMemberName, Consumer, CodeCompleter->includeGlobals(), | |
4849 /*IncludeDependentBases=*/false, CodeCompleter->loadExternal()); | |
4850 } | |
4851 } | |
4852 | |
4853 // FIXME: How do we cope with isa? | |
4854 return true; | |
4855 }; | |
4856 | |
4857 Results.EnterNewScope(); | |
4858 | |
4859 bool CompletionSucceded = DoCompletion(Base, IsArrow, None); | |
4860 if (CodeCompleter->includeFixIts()) { | |
4861 const CharSourceRange OpRange = | |
4862 CharSourceRange::getTokenRange(OpLoc, OpLoc); | |
4863 CompletionSucceded |= DoCompletion( | |
4864 OtherOpBase, !IsArrow, | |
4865 FixItHint::CreateReplacement(OpRange, IsArrow ? "." : "->")); | |
4866 } | |
4867 | |
4868 Results.ExitScope(); | |
4869 | |
4870 if (!CompletionSucceded) | |
4871 return; | |
4872 | |
4873 // Hand off the results found for code completion. | |
4874 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
4875 Results.data(), Results.size()); | |
4876 } | |
4877 | |
4878 void Sema::CodeCompleteObjCClassPropertyRefExpr(Scope *S, | |
4879 IdentifierInfo &ClassName, | |
4880 SourceLocation ClassNameLoc, | |
4881 bool IsBaseExprStatement) { | |
4882 IdentifierInfo *ClassNamePtr = &ClassName; | |
4883 ObjCInterfaceDecl *IFace = getObjCInterfaceDecl(ClassNamePtr, ClassNameLoc); | |
4884 if (!IFace) | |
4885 return; | |
4886 CodeCompletionContext CCContext( | |
4887 CodeCompletionContext::CCC_ObjCPropertyAccess); | |
4888 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
4889 CodeCompleter->getCodeCompletionTUInfo(), CCContext, | |
4890 &ResultBuilder::IsMember); | |
4891 Results.EnterNewScope(); | |
4892 AddedPropertiesSet AddedProperties; | |
4893 AddObjCProperties(CCContext, IFace, true, | |
4894 /*AllowNullaryMethods=*/true, CurContext, AddedProperties, | |
4895 Results, IsBaseExprStatement, | |
4896 /*IsClassProperty=*/true); | |
4897 Results.ExitScope(); | |
4898 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
4899 Results.data(), Results.size()); | |
4900 } | |
4901 | |
4902 void Sema::CodeCompleteTag(Scope *S, unsigned TagSpec) { | |
4903 if (!CodeCompleter) | |
4904 return; | |
4905 | |
4906 ResultBuilder::LookupFilter Filter = nullptr; | |
4907 enum CodeCompletionContext::Kind ContextKind = | |
4908 CodeCompletionContext::CCC_Other; | |
4909 switch ((DeclSpec::TST)TagSpec) { | |
4910 case DeclSpec::TST_enum: | |
4911 Filter = &ResultBuilder::IsEnum; | |
4912 ContextKind = CodeCompletionContext::CCC_EnumTag; | |
4913 break; | |
4914 | |
4915 case DeclSpec::TST_union: | |
4916 Filter = &ResultBuilder::IsUnion; | |
4917 ContextKind = CodeCompletionContext::CCC_UnionTag; | |
4918 break; | |
4919 | |
4920 case DeclSpec::TST_struct: | |
4921 case DeclSpec::TST_class: | |
4922 case DeclSpec::TST_interface: | |
4923 Filter = &ResultBuilder::IsClassOrStruct; | |
4924 ContextKind = CodeCompletionContext::CCC_ClassOrStructTag; | |
4925 break; | |
4926 | |
4927 default: | |
4928 llvm_unreachable("Unknown type specifier kind in CodeCompleteTag"); | |
4929 } | |
4930 | |
4931 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
4932 CodeCompleter->getCodeCompletionTUInfo(), ContextKind); | |
4933 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
4934 | |
4935 // First pass: look for tags. | |
4936 Results.setFilter(Filter); | |
4937 LookupVisibleDecls(S, LookupTagName, Consumer, | |
4938 CodeCompleter->includeGlobals(), | |
4939 CodeCompleter->loadExternal()); | |
4940 | |
4941 if (CodeCompleter->includeGlobals()) { | |
4942 // Second pass: look for nested name specifiers. | |
4943 Results.setFilter(&ResultBuilder::IsNestedNameSpecifier); | |
4944 LookupVisibleDecls(S, LookupNestedNameSpecifierName, Consumer, | |
4945 CodeCompleter->includeGlobals(), | |
4946 CodeCompleter->loadExternal()); | |
4947 } | |
4948 | |
4949 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
4950 Results.data(), Results.size()); | |
4951 } | |
4952 | |
4953 static void AddTypeQualifierResults(DeclSpec &DS, ResultBuilder &Results, | |
4954 const LangOptions &LangOpts) { | |
4955 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_const)) | |
4956 Results.AddResult("const"); | |
4957 if (!(DS.getTypeQualifiers() & DeclSpec::TQ_volatile)) | |
4958 Results.AddResult("volatile"); | |
4959 if (LangOpts.C99 && !(DS.getTypeQualifiers() & DeclSpec::TQ_restrict)) | |
4960 Results.AddResult("restrict"); | |
4961 if (LangOpts.C11 && !(DS.getTypeQualifiers() & DeclSpec::TQ_atomic)) | |
4962 Results.AddResult("_Atomic"); | |
4963 if (LangOpts.MSVCCompat && !(DS.getTypeQualifiers() & DeclSpec::TQ_unaligned)) | |
4964 Results.AddResult("__unaligned"); | |
4965 } | |
4966 | |
4967 void Sema::CodeCompleteTypeQualifiers(DeclSpec &DS) { | |
4968 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
4969 CodeCompleter->getCodeCompletionTUInfo(), | |
4970 CodeCompletionContext::CCC_TypeQualifiers); | |
4971 Results.EnterNewScope(); | |
4972 AddTypeQualifierResults(DS, Results, LangOpts); | |
4973 Results.ExitScope(); | |
4974 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
4975 Results.data(), Results.size()); | |
4976 } | |
4977 | |
4978 void Sema::CodeCompleteFunctionQualifiers(DeclSpec &DS, Declarator &D, | |
4979 const VirtSpecifiers *VS) { | |
4980 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
4981 CodeCompleter->getCodeCompletionTUInfo(), | |
4982 CodeCompletionContext::CCC_TypeQualifiers); | |
4983 Results.EnterNewScope(); | |
4984 AddTypeQualifierResults(DS, Results, LangOpts); | |
4985 if (LangOpts.CPlusPlus11) { | |
4986 Results.AddResult("noexcept"); | |
4987 if (D.getContext() == DeclaratorContext::MemberContext && | |
4988 !D.isCtorOrDtor() && !D.isStaticMember()) { | |
4989 if (!VS || !VS->isFinalSpecified()) | |
4990 Results.AddResult("final"); | |
4991 if (!VS || !VS->isOverrideSpecified()) | |
4992 Results.AddResult("override"); | |
4993 } | |
4994 } | |
4995 Results.ExitScope(); | |
4996 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
4997 Results.data(), Results.size()); | |
4998 } | |
4999 | |
5000 void Sema::CodeCompleteBracketDeclarator(Scope *S) { | |
5001 CodeCompleteExpression(S, QualType(getASTContext().getSizeType())); | |
5002 } | |
5003 | |
5004 void Sema::CodeCompleteCase(Scope *S) { | |
5005 if (getCurFunction()->SwitchStack.empty() || !CodeCompleter) | |
5006 return; | |
5007 | |
5008 SwitchStmt *Switch = getCurFunction()->SwitchStack.back().getPointer(); | |
5009 // Condition expression might be invalid, do not continue in this case. | |
5010 if (!Switch->getCond()) | |
5011 return; | |
5012 QualType type = Switch->getCond()->IgnoreImplicit()->getType(); | |
5013 if (!type->isEnumeralType()) { | |
5014 CodeCompleteExpressionData Data(type); | |
5015 Data.IntegralConstantExpression = true; | |
5016 CodeCompleteExpression(S, Data); | |
5017 return; | |
5018 } | |
5019 | |
5020 // Code-complete the cases of a switch statement over an enumeration type | |
5021 // by providing the list of | |
5022 EnumDecl *Enum = type->castAs<EnumType>()->getDecl(); | |
5023 if (EnumDecl *Def = Enum->getDefinition()) | |
5024 Enum = Def; | |
5025 | |
5026 // Determine which enumerators we have already seen in the switch statement. | |
5027 // FIXME: Ideally, we would also be able to look *past* the code-completion | |
5028 // token, in case we are code-completing in the middle of the switch and not | |
5029 // at the end. However, we aren't able to do so at the moment. | |
5030 CoveredEnumerators Enumerators; | |
5031 for (SwitchCase *SC = Switch->getSwitchCaseList(); SC; | |
5032 SC = SC->getNextSwitchCase()) { | |
5033 CaseStmt *Case = dyn_cast<CaseStmt>(SC); | |
5034 if (!Case) | |
5035 continue; | |
5036 | |
5037 Expr *CaseVal = Case->getLHS()->IgnoreParenCasts(); | |
5038 if (auto *DRE = dyn_cast<DeclRefExpr>(CaseVal)) | |
5039 if (auto *Enumerator = | |
5040 dyn_cast<EnumConstantDecl>(DRE->getDecl())) { | |
5041 // We look into the AST of the case statement to determine which | |
5042 // enumerator was named. Alternatively, we could compute the value of | |
5043 // the integral constant expression, then compare it against the | |
5044 // values of each enumerator. However, value-based approach would not | |
5045 // work as well with C++ templates where enumerators declared within a | |
5046 // template are type- and value-dependent. | |
5047 Enumerators.Seen.insert(Enumerator); | |
5048 | |
5049 // If this is a qualified-id, keep track of the nested-name-specifier | |
5050 // so that we can reproduce it as part of code completion, e.g., | |
5051 // | |
5052 // switch (TagD.getKind()) { | |
5053 // case TagDecl::TK_enum: | |
5054 // break; | |
5055 // case XXX | |
5056 // | |
5057 // At the XXX, our completions are TagDecl::TK_union, | |
5058 // TagDecl::TK_struct, and TagDecl::TK_class, rather than TK_union, | |
5059 // TK_struct, and TK_class. | |
5060 Enumerators.SuggestedQualifier = DRE->getQualifier(); | |
5061 } | |
5062 } | |
5063 | |
5064 // Add any enumerators that have not yet been mentioned. | |
5065 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5066 CodeCompleter->getCodeCompletionTUInfo(), | |
5067 CodeCompletionContext::CCC_Expression); | |
5068 AddEnumerators(Results, Context, Enum, CurContext, Enumerators); | |
5069 | |
5070 if (CodeCompleter->includeMacros()) { | |
5071 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); | |
5072 } | |
5073 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5074 Results.data(), Results.size()); | |
5075 } | |
5076 | |
5077 static bool anyNullArguments(ArrayRef<Expr *> Args) { | |
5078 if (Args.size() && !Args.data()) | |
5079 return true; | |
5080 | |
5081 for (unsigned I = 0; I != Args.size(); ++I) | |
5082 if (!Args[I]) | |
5083 return true; | |
5084 | |
5085 return false; | |
5086 } | |
5087 | |
5088 typedef CodeCompleteConsumer::OverloadCandidate ResultCandidate; | |
5089 | |
5090 static void mergeCandidatesWithResults( | |
5091 Sema &SemaRef, SmallVectorImpl<ResultCandidate> &Results, | |
5092 OverloadCandidateSet &CandidateSet, SourceLocation Loc) { | |
5093 // Sort the overload candidate set by placing the best overloads first. | |
5094 llvm::stable_sort(CandidateSet, [&](const OverloadCandidate &X, | |
5095 const OverloadCandidate &Y) { | |
5096 return isBetterOverloadCandidate(SemaRef, X, Y, Loc, | |
5097 CandidateSet.getKind()); | |
5098 }); | |
5099 | |
5100 // Add the remaining viable overload candidates as code-completion results. | |
5101 for (OverloadCandidate &Candidate : CandidateSet) { | |
5102 if (Candidate.Function && Candidate.Function->isDeleted()) | |
5103 continue; | |
5104 if (Candidate.Viable) | |
5105 Results.push_back(ResultCandidate(Candidate.Function)); | |
5106 } | |
5107 } | |
5108 | |
5109 /// Get the type of the Nth parameter from a given set of overload | |
5110 /// candidates. | |
5111 static QualType getParamType(Sema &SemaRef, | |
5112 ArrayRef<ResultCandidate> Candidates, unsigned N) { | |
5113 | |
5114 // Given the overloads 'Candidates' for a function call matching all arguments | |
5115 // up to N, return the type of the Nth parameter if it is the same for all | |
5116 // overload candidates. | |
5117 QualType ParamType; | |
5118 for (auto &Candidate : Candidates) { | |
5119 if (const auto *FType = Candidate.getFunctionType()) | |
5120 if (const auto *Proto = dyn_cast<FunctionProtoType>(FType)) | |
5121 if (N < Proto->getNumParams()) { | |
5122 if (ParamType.isNull()) | |
5123 ParamType = Proto->getParamType(N); | |
5124 else if (!SemaRef.Context.hasSameUnqualifiedType( | |
5125 ParamType.getNonReferenceType(), | |
5126 Proto->getParamType(N).getNonReferenceType())) | |
5127 // Otherwise return a default-constructed QualType. | |
5128 return QualType(); | |
5129 } | |
5130 } | |
5131 | |
5132 return ParamType; | |
5133 } | |
5134 | |
5135 static QualType | |
5136 ProduceSignatureHelp(Sema &SemaRef, Scope *S, | |
5137 MutableArrayRef<ResultCandidate> Candidates, | |
5138 unsigned CurrentArg, SourceLocation OpenParLoc) { | |
5139 if (Candidates.empty()) | |
5140 return QualType(); | |
5141 SemaRef.CodeCompleter->ProcessOverloadCandidates( | |
5142 SemaRef, CurrentArg, Candidates.data(), Candidates.size(), OpenParLoc); | |
5143 return getParamType(SemaRef, Candidates, CurrentArg); | |
5144 } | |
5145 | |
5146 QualType Sema::ProduceCallSignatureHelp(Scope *S, Expr *Fn, | |
5147 ArrayRef<Expr *> Args, | |
5148 SourceLocation OpenParLoc) { | |
5149 if (!CodeCompleter) | |
5150 return QualType(); | |
5151 | |
5152 // FIXME: Provide support for variadic template functions. | |
5153 // Ignore type-dependent call expressions entirely. | |
5154 if (!Fn || Fn->isTypeDependent() || anyNullArguments(Args) || | |
5155 Expr::hasAnyTypeDependentArguments(Args)) { | |
5156 return QualType(); | |
5157 } | |
5158 | |
5159 // Build an overload candidate set based on the functions we find. | |
5160 SourceLocation Loc = Fn->getExprLoc(); | |
5161 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); | |
5162 | |
5163 SmallVector<ResultCandidate, 8> Results; | |
5164 | |
5165 Expr *NakedFn = Fn->IgnoreParenCasts(); | |
5166 if (auto ULE = dyn_cast<UnresolvedLookupExpr>(NakedFn)) | |
5167 AddOverloadedCallCandidates(ULE, Args, CandidateSet, | |
5168 /*PartialOverloading=*/true); | |
5169 else if (auto UME = dyn_cast<UnresolvedMemberExpr>(NakedFn)) { | |
5170 TemplateArgumentListInfo TemplateArgsBuffer, *TemplateArgs = nullptr; | |
5171 if (UME->hasExplicitTemplateArgs()) { | |
5172 UME->copyTemplateArgumentsInto(TemplateArgsBuffer); | |
5173 TemplateArgs = &TemplateArgsBuffer; | |
5174 } | |
5175 | |
5176 // Add the base as first argument (use a nullptr if the base is implicit). | |
5177 SmallVector<Expr *, 12> ArgExprs( | |
5178 1, UME->isImplicitAccess() ? nullptr : UME->getBase()); | |
5179 ArgExprs.append(Args.begin(), Args.end()); | |
5180 UnresolvedSet<8> Decls; | |
5181 Decls.append(UME->decls_begin(), UME->decls_end()); | |
5182 const bool FirstArgumentIsBase = !UME->isImplicitAccess() && UME->getBase(); | |
5183 AddFunctionCandidates(Decls, ArgExprs, CandidateSet, TemplateArgs, | |
5184 /*SuppressUserConversions=*/false, | |
5185 /*PartialOverloading=*/true, FirstArgumentIsBase); | |
5186 } else { | |
5187 FunctionDecl *FD = nullptr; | |
5188 if (auto *MCE = dyn_cast<MemberExpr>(NakedFn)) | |
5189 FD = dyn_cast<FunctionDecl>(MCE->getMemberDecl()); | |
5190 else if (auto *DRE = dyn_cast<DeclRefExpr>(NakedFn)) | |
5191 FD = dyn_cast<FunctionDecl>(DRE->getDecl()); | |
5192 if (FD) { // We check whether it's a resolved function declaration. | |
5193 if (!getLangOpts().CPlusPlus || | |
5194 !FD->getType()->getAs<FunctionProtoType>()) | |
5195 Results.push_back(ResultCandidate(FD)); | |
5196 else | |
5197 AddOverloadCandidate(FD, DeclAccessPair::make(FD, FD->getAccess()), | |
5198 Args, CandidateSet, | |
5199 /*SuppressUserConversions=*/false, | |
5200 /*PartialOverloading=*/true); | |
5201 | |
5202 } else if (auto DC = NakedFn->getType()->getAsCXXRecordDecl()) { | |
5203 // If expression's type is CXXRecordDecl, it may overload the function | |
5204 // call operator, so we check if it does and add them as candidates. | |
5205 // A complete type is needed to lookup for member function call operators. | |
5206 if (isCompleteType(Loc, NakedFn->getType())) { | |
5207 DeclarationName OpName = | |
5208 Context.DeclarationNames.getCXXOperatorName(OO_Call); | |
5209 LookupResult R(*this, OpName, Loc, LookupOrdinaryName); | |
5210 LookupQualifiedName(R, DC); | |
5211 R.suppressDiagnostics(); | |
5212 SmallVector<Expr *, 12> ArgExprs(1, NakedFn); | |
5213 ArgExprs.append(Args.begin(), Args.end()); | |
5214 AddFunctionCandidates(R.asUnresolvedSet(), ArgExprs, CandidateSet, | |
5215 /*ExplicitArgs=*/nullptr, | |
5216 /*SuppressUserConversions=*/false, | |
5217 /*PartialOverloading=*/true); | |
5218 } | |
5219 } else { | |
5220 // Lastly we check whether expression's type is function pointer or | |
5221 // function. | |
5222 QualType T = NakedFn->getType(); | |
5223 if (!T->getPointeeType().isNull()) | |
5224 T = T->getPointeeType(); | |
5225 | |
5226 if (auto FP = T->getAs<FunctionProtoType>()) { | |
5227 if (!TooManyArguments(FP->getNumParams(), Args.size(), | |
5228 /*PartialOverloading=*/true) || | |
5229 FP->isVariadic()) | |
5230 Results.push_back(ResultCandidate(FP)); | |
5231 } else if (auto FT = T->getAs<FunctionType>()) | |
5232 // No prototype and declaration, it may be a K & R style function. | |
5233 Results.push_back(ResultCandidate(FT)); | |
5234 } | |
5235 } | |
5236 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); | |
5237 QualType ParamType = | |
5238 ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); | |
5239 return !CandidateSet.empty() ? ParamType : QualType(); | |
5240 } | |
5241 | |
5242 QualType Sema::ProduceConstructorSignatureHelp(Scope *S, QualType Type, | |
5243 SourceLocation Loc, | |
5244 ArrayRef<Expr *> Args, | |
5245 SourceLocation OpenParLoc) { | |
5246 if (!CodeCompleter) | |
5247 return QualType(); | |
5248 | |
5249 // A complete type is needed to lookup for constructors. | |
5250 CXXRecordDecl *RD = | |
5251 isCompleteType(Loc, Type) ? Type->getAsCXXRecordDecl() : nullptr; | |
5252 if (!RD) | |
5253 return Type; | |
5254 | |
5255 // FIXME: Provide support for member initializers. | |
5256 // FIXME: Provide support for variadic template constructors. | |
5257 | |
5258 OverloadCandidateSet CandidateSet(Loc, OverloadCandidateSet::CSK_Normal); | |
5259 | |
5260 for (NamedDecl *C : LookupConstructors(RD)) { | |
5261 if (auto *FD = dyn_cast<FunctionDecl>(C)) { | |
5262 AddOverloadCandidate(FD, DeclAccessPair::make(FD, C->getAccess()), Args, | |
5263 CandidateSet, | |
5264 /*SuppressUserConversions=*/false, | |
5265 /*PartialOverloading=*/true, | |
5266 /*AllowExplicit*/ true); | |
5267 } else if (auto *FTD = dyn_cast<FunctionTemplateDecl>(C)) { | |
5268 AddTemplateOverloadCandidate( | |
5269 FTD, DeclAccessPair::make(FTD, C->getAccess()), | |
5270 /*ExplicitTemplateArgs=*/nullptr, Args, CandidateSet, | |
5271 /*SuppressUserConversions=*/false, | |
5272 /*PartialOverloading=*/true); | |
5273 } | |
5274 } | |
5275 | |
5276 SmallVector<ResultCandidate, 8> Results; | |
5277 mergeCandidatesWithResults(*this, Results, CandidateSet, Loc); | |
5278 return ProduceSignatureHelp(*this, S, Results, Args.size(), OpenParLoc); | |
5279 } | |
5280 | |
5281 QualType Sema::ProduceCtorInitMemberSignatureHelp( | |
5282 Scope *S, Decl *ConstructorDecl, CXXScopeSpec SS, ParsedType TemplateTypeTy, | |
5283 ArrayRef<Expr *> ArgExprs, IdentifierInfo *II, SourceLocation OpenParLoc) { | |
5284 if (!CodeCompleter) | |
5285 return QualType(); | |
5286 | |
5287 CXXConstructorDecl *Constructor = | |
5288 dyn_cast<CXXConstructorDecl>(ConstructorDecl); | |
5289 if (!Constructor) | |
5290 return QualType(); | |
5291 // FIXME: Add support for Base class constructors as well. | |
5292 if (ValueDecl *MemberDecl = tryLookupCtorInitMemberDecl( | |
5293 Constructor->getParent(), SS, TemplateTypeTy, II)) | |
5294 return ProduceConstructorSignatureHelp(getCurScope(), MemberDecl->getType(), | |
5295 MemberDecl->getLocation(), ArgExprs, | |
5296 OpenParLoc); | |
5297 return QualType(); | |
5298 } | |
5299 | |
5300 void Sema::CodeCompleteDesignator(const QualType BaseType, | |
5301 llvm::ArrayRef<Expr *> InitExprs, | |
5302 const Designation &D) { | |
5303 if (BaseType.isNull()) | |
5304 return; | |
5305 // FIXME: Handle nested designations, e.g. : .x.^ | |
5306 if (!D.empty()) | |
5307 return; | |
5308 | |
5309 const auto *RD = getAsRecordDecl(BaseType); | |
5310 if (!RD) | |
5311 return; | |
5312 if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(RD)) { | |
5313 // Template might not be instantiated yet, fall back to primary template in | |
5314 // such cases. | |
5315 if (CTSD->getTemplateSpecializationKind() == TSK_Undeclared) | |
5316 RD = CTSD->getSpecializedTemplate()->getTemplatedDecl(); | |
5317 } | |
5318 if (RD->fields().empty()) | |
5319 return; | |
5320 | |
5321 CodeCompletionContext CCC(CodeCompletionContext::CCC_DotMemberAccess, | |
5322 BaseType); | |
5323 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5324 CodeCompleter->getCodeCompletionTUInfo(), CCC); | |
5325 | |
5326 Results.EnterNewScope(); | |
5327 for (const auto *FD : RD->fields()) { | |
5328 // FIXME: Make use of previous designators to mark any fields before those | |
5329 // inaccessible, and also compute the next initializer priority. | |
5330 ResultBuilder::Result Result(FD, Results.getBasePriority(FD)); | |
5331 Results.AddResult(Result, CurContext, /*Hiding=*/nullptr); | |
5332 } | |
5333 Results.ExitScope(); | |
5334 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5335 Results.data(), Results.size()); | |
5336 } | |
5337 | |
5338 void Sema::CodeCompleteInitializer(Scope *S, Decl *D) { | |
5339 ValueDecl *VD = dyn_cast_or_null<ValueDecl>(D); | |
5340 if (!VD) { | |
5341 CodeCompleteOrdinaryName(S, PCC_Expression); | |
5342 return; | |
5343 } | |
5344 | |
5345 CodeCompleteExpressionData Data; | |
5346 Data.PreferredType = VD->getType(); | |
5347 // Ignore VD to avoid completing the variable itself, e.g. in 'int foo = ^'. | |
5348 Data.IgnoreDecls.push_back(VD); | |
5349 | |
5350 CodeCompleteExpression(S, Data); | |
5351 } | |
5352 | |
5353 void Sema::CodeCompleteAfterIf(Scope *S) { | |
5354 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5355 CodeCompleter->getCodeCompletionTUInfo(), | |
5356 mapCodeCompletionContext(*this, PCC_Statement)); | |
5357 Results.setFilter(&ResultBuilder::IsOrdinaryName); | |
5358 Results.EnterNewScope(); | |
5359 | |
5360 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
5361 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
5362 CodeCompleter->includeGlobals(), | |
5363 CodeCompleter->loadExternal()); | |
5364 | |
5365 AddOrdinaryNameResults(PCC_Statement, S, *this, Results); | |
5366 | |
5367 // "else" block | |
5368 CodeCompletionBuilder Builder(Results.getAllocator(), | |
5369 Results.getCodeCompletionTUInfo()); | |
5370 Builder.AddTypedTextChunk("else"); | |
5371 if (Results.includeCodePatterns()) { | |
5372 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5373 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
5374 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
5375 Builder.AddPlaceholderChunk("statements"); | |
5376 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
5377 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
5378 } | |
5379 Results.AddResult(Builder.TakeString()); | |
5380 | |
5381 // "else if" block | |
5382 Builder.AddTypedTextChunk("else if"); | |
5383 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5384 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
5385 if (getLangOpts().CPlusPlus) | |
5386 Builder.AddPlaceholderChunk("condition"); | |
5387 else | |
5388 Builder.AddPlaceholderChunk("expression"); | |
5389 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
5390 if (Results.includeCodePatterns()) { | |
5391 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5392 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
5393 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
5394 Builder.AddPlaceholderChunk("statements"); | |
5395 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
5396 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
5397 } | |
5398 Results.AddResult(Builder.TakeString()); | |
5399 | |
5400 Results.ExitScope(); | |
5401 | |
5402 if (S->getFnParent()) | |
5403 AddPrettyFunctionResults(getLangOpts(), Results); | |
5404 | |
5405 if (CodeCompleter->includeMacros()) | |
5406 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); | |
5407 | |
5408 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5409 Results.data(), Results.size()); | |
5410 } | |
5411 | |
5412 void Sema::CodeCompleteQualifiedId(Scope *S, CXXScopeSpec &SS, | |
5413 bool EnteringContext, | |
5414 bool IsUsingDeclaration, QualType BaseType, | |
5415 QualType PreferredType) { | |
5416 if (SS.isEmpty() || !CodeCompleter) | |
5417 return; | |
5418 | |
5419 CodeCompletionContext CC(CodeCompletionContext::CCC_Symbol, PreferredType); | |
5420 CC.setIsUsingDeclaration(IsUsingDeclaration); | |
5421 CC.setCXXScopeSpecifier(SS); | |
5422 | |
5423 // We want to keep the scope specifier even if it's invalid (e.g. the scope | |
5424 // "a::b::" is not corresponding to any context/namespace in the AST), since | |
5425 // it can be useful for global code completion which have information about | |
5426 // contexts/symbols that are not in the AST. | |
5427 if (SS.isInvalid()) { | |
5428 // As SS is invalid, we try to collect accessible contexts from the current | |
5429 // scope with a dummy lookup so that the completion consumer can try to | |
5430 // guess what the specified scope is. | |
5431 ResultBuilder DummyResults(*this, CodeCompleter->getAllocator(), | |
5432 CodeCompleter->getCodeCompletionTUInfo(), CC); | |
5433 if (!PreferredType.isNull()) | |
5434 DummyResults.setPreferredType(PreferredType); | |
5435 if (S->getEntity()) { | |
5436 CodeCompletionDeclConsumer Consumer(DummyResults, S->getEntity(), | |
5437 BaseType); | |
5438 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
5439 /*IncludeGlobalScope=*/false, | |
5440 /*LoadExternal=*/false); | |
5441 } | |
5442 HandleCodeCompleteResults(this, CodeCompleter, | |
5443 DummyResults.getCompletionContext(), nullptr, 0); | |
5444 return; | |
5445 } | |
5446 // Always pretend to enter a context to ensure that a dependent type | |
5447 // resolves to a dependent record. | |
5448 DeclContext *Ctx = computeDeclContext(SS, /*EnteringContext=*/true); | |
5449 if (!Ctx) | |
5450 return; | |
5451 | |
5452 // Try to instantiate any non-dependent declaration contexts before | |
5453 // we look in them. | |
5454 if (!isDependentScopeSpecifier(SS) && RequireCompleteDeclContext(SS, Ctx)) | |
5455 return; | |
5456 | |
5457 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5458 CodeCompleter->getCodeCompletionTUInfo(), CC); | |
5459 if (!PreferredType.isNull()) | |
5460 Results.setPreferredType(PreferredType); | |
5461 Results.EnterNewScope(); | |
5462 | |
5463 // The "template" keyword can follow "::" in the grammar, but only | |
5464 // put it into the grammar if the nested-name-specifier is dependent. | |
5465 NestedNameSpecifier *NNS = SS.getScopeRep(); | |
5466 if (!Results.empty() && NNS->isDependent()) | |
5467 Results.AddResult("template"); | |
5468 | |
5469 // Add calls to overridden virtual functions, if there are any. | |
5470 // | |
5471 // FIXME: This isn't wonderful, because we don't know whether we're actually | |
5472 // in a context that permits expressions. This is a general issue with | |
5473 // qualified-id completions. | |
5474 if (!EnteringContext) | |
5475 MaybeAddOverrideCalls(*this, Ctx, Results); | |
5476 Results.ExitScope(); | |
5477 | |
5478 if (CodeCompleter->includeNamespaceLevelDecls() || | |
5479 (!Ctx->isNamespace() && !Ctx->isTranslationUnit())) { | |
5480 CodeCompletionDeclConsumer Consumer(Results, Ctx, BaseType); | |
5481 LookupVisibleDecls(Ctx, LookupOrdinaryName, Consumer, | |
5482 /*IncludeGlobalScope=*/true, | |
5483 /*IncludeDependentBases=*/true, | |
5484 CodeCompleter->loadExternal()); | |
5485 } | |
5486 | |
5487 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5488 Results.data(), Results.size()); | |
5489 } | |
5490 | |
5491 void Sema::CodeCompleteUsing(Scope *S) { | |
5492 if (!CodeCompleter) | |
5493 return; | |
5494 | |
5495 // This can be both a using alias or using declaration, in the former we | |
5496 // expect a new name and a symbol in the latter case. | |
5497 CodeCompletionContext Context(CodeCompletionContext::CCC_SymbolOrNewName); | |
5498 Context.setIsUsingDeclaration(true); | |
5499 | |
5500 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5501 CodeCompleter->getCodeCompletionTUInfo(), Context, | |
5502 &ResultBuilder::IsNestedNameSpecifier); | |
5503 Results.EnterNewScope(); | |
5504 | |
5505 // If we aren't in class scope, we could see the "namespace" keyword. | |
5506 if (!S->isClassScope()) | |
5507 Results.AddResult(CodeCompletionResult("namespace")); | |
5508 | |
5509 // After "using", we can see anything that would start a | |
5510 // nested-name-specifier. | |
5511 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
5512 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
5513 CodeCompleter->includeGlobals(), | |
5514 CodeCompleter->loadExternal()); | |
5515 Results.ExitScope(); | |
5516 | |
5517 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5518 Results.data(), Results.size()); | |
5519 } | |
5520 | |
5521 void Sema::CodeCompleteUsingDirective(Scope *S) { | |
5522 if (!CodeCompleter) | |
5523 return; | |
5524 | |
5525 // After "using namespace", we expect to see a namespace name or namespace | |
5526 // alias. | |
5527 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5528 CodeCompleter->getCodeCompletionTUInfo(), | |
5529 CodeCompletionContext::CCC_Namespace, | |
5530 &ResultBuilder::IsNamespaceOrAlias); | |
5531 Results.EnterNewScope(); | |
5532 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
5533 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
5534 CodeCompleter->includeGlobals(), | |
5535 CodeCompleter->loadExternal()); | |
5536 Results.ExitScope(); | |
5537 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5538 Results.data(), Results.size()); | |
5539 } | |
5540 | |
5541 void Sema::CodeCompleteNamespaceDecl(Scope *S) { | |
5542 if (!CodeCompleter) | |
5543 return; | |
5544 | |
5545 DeclContext *Ctx = S->getEntity(); | |
5546 if (!S->getParent()) | |
5547 Ctx = Context.getTranslationUnitDecl(); | |
5548 | |
5549 bool SuppressedGlobalResults = | |
5550 Ctx && !CodeCompleter->includeGlobals() && isa<TranslationUnitDecl>(Ctx); | |
5551 | |
5552 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5553 CodeCompleter->getCodeCompletionTUInfo(), | |
5554 SuppressedGlobalResults | |
5555 ? CodeCompletionContext::CCC_Namespace | |
5556 : CodeCompletionContext::CCC_Other, | |
5557 &ResultBuilder::IsNamespace); | |
5558 | |
5559 if (Ctx && Ctx->isFileContext() && !SuppressedGlobalResults) { | |
5560 // We only want to see those namespaces that have already been defined | |
5561 // within this scope, because its likely that the user is creating an | |
5562 // extended namespace declaration. Keep track of the most recent | |
5563 // definition of each namespace. | |
5564 std::map<NamespaceDecl *, NamespaceDecl *> OrigToLatest; | |
5565 for (DeclContext::specific_decl_iterator<NamespaceDecl> | |
5566 NS(Ctx->decls_begin()), | |
5567 NSEnd(Ctx->decls_end()); | |
5568 NS != NSEnd; ++NS) | |
5569 OrigToLatest[NS->getOriginalNamespace()] = *NS; | |
5570 | |
5571 // Add the most recent definition (or extended definition) of each | |
5572 // namespace to the list of results. | |
5573 Results.EnterNewScope(); | |
5574 for (std::map<NamespaceDecl *, NamespaceDecl *>::iterator | |
5575 NS = OrigToLatest.begin(), | |
5576 NSEnd = OrigToLatest.end(); | |
5577 NS != NSEnd; ++NS) | |
5578 Results.AddResult( | |
5579 CodeCompletionResult(NS->second, Results.getBasePriority(NS->second), | |
5580 nullptr), | |
5581 CurContext, nullptr, false); | |
5582 Results.ExitScope(); | |
5583 } | |
5584 | |
5585 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5586 Results.data(), Results.size()); | |
5587 } | |
5588 | |
5589 void Sema::CodeCompleteNamespaceAliasDecl(Scope *S) { | |
5590 if (!CodeCompleter) | |
5591 return; | |
5592 | |
5593 // After "namespace", we expect to see a namespace or alias. | |
5594 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5595 CodeCompleter->getCodeCompletionTUInfo(), | |
5596 CodeCompletionContext::CCC_Namespace, | |
5597 &ResultBuilder::IsNamespaceOrAlias); | |
5598 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
5599 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
5600 CodeCompleter->includeGlobals(), | |
5601 CodeCompleter->loadExternal()); | |
5602 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5603 Results.data(), Results.size()); | |
5604 } | |
5605 | |
5606 void Sema::CodeCompleteOperatorName(Scope *S) { | |
5607 if (!CodeCompleter) | |
5608 return; | |
5609 | |
5610 typedef CodeCompletionResult Result; | |
5611 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5612 CodeCompleter->getCodeCompletionTUInfo(), | |
5613 CodeCompletionContext::CCC_Type, | |
5614 &ResultBuilder::IsType); | |
5615 Results.EnterNewScope(); | |
5616 | |
5617 // Add the names of overloadable operators. Note that OO_Conditional is not | |
5618 // actually overloadable. | |
5619 #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ | |
5620 if (OO_##Name != OO_Conditional) \ | |
5621 Results.AddResult(Result(Spelling)); | |
5622 #include "clang/Basic/OperatorKinds.def" | |
5623 | |
5624 // Add any type names visible from the current scope | |
5625 Results.allowNestedNameSpecifiers(); | |
5626 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
5627 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
5628 CodeCompleter->includeGlobals(), | |
5629 CodeCompleter->loadExternal()); | |
5630 | |
5631 // Add any type specifiers | |
5632 AddTypeSpecifierResults(getLangOpts(), Results); | |
5633 Results.ExitScope(); | |
5634 | |
5635 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5636 Results.data(), Results.size()); | |
5637 } | |
5638 | |
5639 void Sema::CodeCompleteConstructorInitializer( | |
5640 Decl *ConstructorD, ArrayRef<CXXCtorInitializer *> Initializers) { | |
5641 if (!ConstructorD) | |
5642 return; | |
5643 | |
5644 AdjustDeclIfTemplate(ConstructorD); | |
5645 | |
5646 auto *Constructor = dyn_cast<CXXConstructorDecl>(ConstructorD); | |
5647 if (!Constructor) | |
5648 return; | |
5649 | |
5650 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5651 CodeCompleter->getCodeCompletionTUInfo(), | |
5652 CodeCompletionContext::CCC_Symbol); | |
5653 Results.EnterNewScope(); | |
5654 | |
5655 // Fill in any already-initialized fields or base classes. | |
5656 llvm::SmallPtrSet<FieldDecl *, 4> InitializedFields; | |
5657 llvm::SmallPtrSet<CanQualType, 4> InitializedBases; | |
5658 for (unsigned I = 0, E = Initializers.size(); I != E; ++I) { | |
5659 if (Initializers[I]->isBaseInitializer()) | |
5660 InitializedBases.insert(Context.getCanonicalType( | |
5661 QualType(Initializers[I]->getBaseClass(), 0))); | |
5662 else | |
5663 InitializedFields.insert( | |
5664 cast<FieldDecl>(Initializers[I]->getAnyMember())); | |
5665 } | |
5666 | |
5667 // Add completions for base classes. | |
5668 PrintingPolicy Policy = getCompletionPrintingPolicy(*this); | |
5669 bool SawLastInitializer = Initializers.empty(); | |
5670 CXXRecordDecl *ClassDecl = Constructor->getParent(); | |
5671 | |
5672 auto GenerateCCS = [&](const NamedDecl *ND, const char *Name) { | |
5673 CodeCompletionBuilder Builder(Results.getAllocator(), | |
5674 Results.getCodeCompletionTUInfo()); | |
5675 Builder.AddTypedTextChunk(Name); | |
5676 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
5677 if (const auto *Function = dyn_cast<FunctionDecl>(ND)) | |
5678 AddFunctionParameterChunks(PP, Policy, Function, Builder); | |
5679 else if (const auto *FunTemplDecl = dyn_cast<FunctionTemplateDecl>(ND)) | |
5680 AddFunctionParameterChunks(PP, Policy, FunTemplDecl->getTemplatedDecl(), | |
5681 Builder); | |
5682 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
5683 return Builder.TakeString(); | |
5684 }; | |
5685 auto AddDefaultCtorInit = [&](const char *Name, const char *Type, | |
5686 const NamedDecl *ND) { | |
5687 CodeCompletionBuilder Builder(Results.getAllocator(), | |
5688 Results.getCodeCompletionTUInfo()); | |
5689 Builder.AddTypedTextChunk(Name); | |
5690 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
5691 Builder.AddPlaceholderChunk(Type); | |
5692 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
5693 if (ND) { | |
5694 auto CCR = CodeCompletionResult( | |
5695 Builder.TakeString(), ND, | |
5696 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration); | |
5697 if (isa<FieldDecl>(ND)) | |
5698 CCR.CursorKind = CXCursor_MemberRef; | |
5699 return Results.AddResult(CCR); | |
5700 } | |
5701 return Results.AddResult(CodeCompletionResult( | |
5702 Builder.TakeString(), | |
5703 SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration)); | |
5704 }; | |
5705 auto AddCtorsWithName = [&](const CXXRecordDecl *RD, unsigned int Priority, | |
5706 const char *Name, const FieldDecl *FD) { | |
5707 if (!RD) | |
5708 return AddDefaultCtorInit(Name, | |
5709 FD ? Results.getAllocator().CopyString( | |
5710 FD->getType().getAsString(Policy)) | |
5711 : Name, | |
5712 FD); | |
5713 auto Ctors = getConstructors(Context, RD); | |
5714 if (Ctors.begin() == Ctors.end()) | |
5715 return AddDefaultCtorInit(Name, Name, RD); | |
5716 for (const NamedDecl *Ctor : Ctors) { | |
5717 auto CCR = CodeCompletionResult(GenerateCCS(Ctor, Name), RD, Priority); | |
5718 CCR.CursorKind = getCursorKindForDecl(Ctor); | |
5719 Results.AddResult(CCR); | |
5720 } | |
5721 }; | |
5722 auto AddBase = [&](const CXXBaseSpecifier &Base) { | |
5723 const char *BaseName = | |
5724 Results.getAllocator().CopyString(Base.getType().getAsString(Policy)); | |
5725 const auto *RD = Base.getType()->getAsCXXRecordDecl(); | |
5726 AddCtorsWithName( | |
5727 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration, | |
5728 BaseName, nullptr); | |
5729 }; | |
5730 auto AddField = [&](const FieldDecl *FD) { | |
5731 const char *FieldName = | |
5732 Results.getAllocator().CopyString(FD->getIdentifier()->getName()); | |
5733 const CXXRecordDecl *RD = FD->getType()->getAsCXXRecordDecl(); | |
5734 AddCtorsWithName( | |
5735 RD, SawLastInitializer ? CCP_NextInitializer : CCP_MemberDeclaration, | |
5736 FieldName, FD); | |
5737 }; | |
5738 | |
5739 for (const auto &Base : ClassDecl->bases()) { | |
5740 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) | |
5741 .second) { | |
5742 SawLastInitializer = | |
5743 !Initializers.empty() && Initializers.back()->isBaseInitializer() && | |
5744 Context.hasSameUnqualifiedType( | |
5745 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); | |
5746 continue; | |
5747 } | |
5748 | |
5749 AddBase(Base); | |
5750 SawLastInitializer = false; | |
5751 } | |
5752 | |
5753 // Add completions for virtual base classes. | |
5754 for (const auto &Base : ClassDecl->vbases()) { | |
5755 if (!InitializedBases.insert(Context.getCanonicalType(Base.getType())) | |
5756 .second) { | |
5757 SawLastInitializer = | |
5758 !Initializers.empty() && Initializers.back()->isBaseInitializer() && | |
5759 Context.hasSameUnqualifiedType( | |
5760 Base.getType(), QualType(Initializers.back()->getBaseClass(), 0)); | |
5761 continue; | |
5762 } | |
5763 | |
5764 AddBase(Base); | |
5765 SawLastInitializer = false; | |
5766 } | |
5767 | |
5768 // Add completions for members. | |
5769 for (auto *Field : ClassDecl->fields()) { | |
5770 if (!InitializedFields.insert(cast<FieldDecl>(Field->getCanonicalDecl())) | |
5771 .second) { | |
5772 SawLastInitializer = !Initializers.empty() && | |
5773 Initializers.back()->isAnyMemberInitializer() && | |
5774 Initializers.back()->getAnyMember() == Field; | |
5775 continue; | |
5776 } | |
5777 | |
5778 if (!Field->getDeclName()) | |
5779 continue; | |
5780 | |
5781 AddField(Field); | |
5782 SawLastInitializer = false; | |
5783 } | |
5784 Results.ExitScope(); | |
5785 | |
5786 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5787 Results.data(), Results.size()); | |
5788 } | |
5789 | |
5790 /// Determine whether this scope denotes a namespace. | |
5791 static bool isNamespaceScope(Scope *S) { | |
5792 DeclContext *DC = S->getEntity(); | |
5793 if (!DC) | |
5794 return false; | |
5795 | |
5796 return DC->isFileContext(); | |
5797 } | |
5798 | |
5799 void Sema::CodeCompleteLambdaIntroducer(Scope *S, LambdaIntroducer &Intro, | |
5800 bool AfterAmpersand) { | |
5801 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5802 CodeCompleter->getCodeCompletionTUInfo(), | |
5803 CodeCompletionContext::CCC_Other); | |
5804 Results.EnterNewScope(); | |
5805 | |
5806 // Note what has already been captured. | |
5807 llvm::SmallPtrSet<IdentifierInfo *, 4> Known; | |
5808 bool IncludedThis = false; | |
5809 for (const auto &C : Intro.Captures) { | |
5810 if (C.Kind == LCK_This) { | |
5811 IncludedThis = true; | |
5812 continue; | |
5813 } | |
5814 | |
5815 Known.insert(C.Id); | |
5816 } | |
5817 | |
5818 // Look for other capturable variables. | |
5819 for (; S && !isNamespaceScope(S); S = S->getParent()) { | |
5820 for (const auto *D : S->decls()) { | |
5821 const auto *Var = dyn_cast<VarDecl>(D); | |
5822 if (!Var || !Var->hasLocalStorage() || Var->hasAttr<BlocksAttr>()) | |
5823 continue; | |
5824 | |
5825 if (Known.insert(Var->getIdentifier()).second) | |
5826 Results.AddResult(CodeCompletionResult(Var, CCP_LocalDeclaration), | |
5827 CurContext, nullptr, false); | |
5828 } | |
5829 } | |
5830 | |
5831 // Add 'this', if it would be valid. | |
5832 if (!IncludedThis && !AfterAmpersand && Intro.Default != LCD_ByCopy) | |
5833 addThisCompletion(*this, Results); | |
5834 | |
5835 Results.ExitScope(); | |
5836 | |
5837 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5838 Results.data(), Results.size()); | |
5839 } | |
5840 | |
5841 /// Macro that optionally prepends an "@" to the string literal passed in via | |
5842 /// Keyword, depending on whether NeedAt is true or false. | |
5843 #define OBJC_AT_KEYWORD_NAME(NeedAt, Keyword) ((NeedAt) ? "@" Keyword : Keyword) | |
5844 | |
5845 static void AddObjCImplementationResults(const LangOptions &LangOpts, | |
5846 ResultBuilder &Results, bool NeedAt) { | |
5847 typedef CodeCompletionResult Result; | |
5848 // Since we have an implementation, we can end it. | |
5849 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end"))); | |
5850 | |
5851 CodeCompletionBuilder Builder(Results.getAllocator(), | |
5852 Results.getCodeCompletionTUInfo()); | |
5853 if (LangOpts.ObjC) { | |
5854 // @dynamic | |
5855 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "dynamic")); | |
5856 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5857 Builder.AddPlaceholderChunk("property"); | |
5858 Results.AddResult(Result(Builder.TakeString())); | |
5859 | |
5860 // @synthesize | |
5861 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synthesize")); | |
5862 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5863 Builder.AddPlaceholderChunk("property"); | |
5864 Results.AddResult(Result(Builder.TakeString())); | |
5865 } | |
5866 } | |
5867 | |
5868 static void AddObjCInterfaceResults(const LangOptions &LangOpts, | |
5869 ResultBuilder &Results, bool NeedAt) { | |
5870 typedef CodeCompletionResult Result; | |
5871 | |
5872 // Since we have an interface or protocol, we can end it. | |
5873 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "end"))); | |
5874 | |
5875 if (LangOpts.ObjC) { | |
5876 // @property | |
5877 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "property"))); | |
5878 | |
5879 // @required | |
5880 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "required"))); | |
5881 | |
5882 // @optional | |
5883 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "optional"))); | |
5884 } | |
5885 } | |
5886 | |
5887 static void AddObjCTopLevelResults(ResultBuilder &Results, bool NeedAt) { | |
5888 typedef CodeCompletionResult Result; | |
5889 CodeCompletionBuilder Builder(Results.getAllocator(), | |
5890 Results.getCodeCompletionTUInfo()); | |
5891 | |
5892 // @class name ; | |
5893 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "class")); | |
5894 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5895 Builder.AddPlaceholderChunk("name"); | |
5896 Results.AddResult(Result(Builder.TakeString())); | |
5897 | |
5898 if (Results.includeCodePatterns()) { | |
5899 // @interface name | |
5900 // FIXME: Could introduce the whole pattern, including superclasses and | |
5901 // such. | |
5902 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "interface")); | |
5903 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5904 Builder.AddPlaceholderChunk("class"); | |
5905 Results.AddResult(Result(Builder.TakeString())); | |
5906 | |
5907 // @protocol name | |
5908 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol")); | |
5909 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5910 Builder.AddPlaceholderChunk("protocol"); | |
5911 Results.AddResult(Result(Builder.TakeString())); | |
5912 | |
5913 // @implementation name | |
5914 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "implementation")); | |
5915 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5916 Builder.AddPlaceholderChunk("class"); | |
5917 Results.AddResult(Result(Builder.TakeString())); | |
5918 } | |
5919 | |
5920 // @compatibility_alias name | |
5921 Builder.AddTypedTextChunk( | |
5922 OBJC_AT_KEYWORD_NAME(NeedAt, "compatibility_alias")); | |
5923 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5924 Builder.AddPlaceholderChunk("alias"); | |
5925 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5926 Builder.AddPlaceholderChunk("class"); | |
5927 Results.AddResult(Result(Builder.TakeString())); | |
5928 | |
5929 if (Results.getSema().getLangOpts().Modules) { | |
5930 // @import name | |
5931 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "import")); | |
5932 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
5933 Builder.AddPlaceholderChunk("module"); | |
5934 Results.AddResult(Result(Builder.TakeString())); | |
5935 } | |
5936 } | |
5937 | |
5938 void Sema::CodeCompleteObjCAtDirective(Scope *S) { | |
5939 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
5940 CodeCompleter->getCodeCompletionTUInfo(), | |
5941 CodeCompletionContext::CCC_Other); | |
5942 Results.EnterNewScope(); | |
5943 if (isa<ObjCImplDecl>(CurContext)) | |
5944 AddObjCImplementationResults(getLangOpts(), Results, false); | |
5945 else if (CurContext->isObjCContainer()) | |
5946 AddObjCInterfaceResults(getLangOpts(), Results, false); | |
5947 else | |
5948 AddObjCTopLevelResults(Results, false); | |
5949 Results.ExitScope(); | |
5950 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
5951 Results.data(), Results.size()); | |
5952 } | |
5953 | |
5954 static void AddObjCExpressionResults(ResultBuilder &Results, bool NeedAt) { | |
5955 typedef CodeCompletionResult Result; | |
5956 CodeCompletionBuilder Builder(Results.getAllocator(), | |
5957 Results.getCodeCompletionTUInfo()); | |
5958 | |
5959 // @encode ( type-name ) | |
5960 const char *EncodeType = "char[]"; | |
5961 if (Results.getSema().getLangOpts().CPlusPlus || | |
5962 Results.getSema().getLangOpts().ConstStrings) | |
5963 EncodeType = "const char[]"; | |
5964 Builder.AddResultTypeChunk(EncodeType); | |
5965 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "encode")); | |
5966 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
5967 Builder.AddPlaceholderChunk("type-name"); | |
5968 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
5969 Results.AddResult(Result(Builder.TakeString())); | |
5970 | |
5971 // @protocol ( protocol-name ) | |
5972 Builder.AddResultTypeChunk("Protocol *"); | |
5973 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "protocol")); | |
5974 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
5975 Builder.AddPlaceholderChunk("protocol-name"); | |
5976 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
5977 Results.AddResult(Result(Builder.TakeString())); | |
5978 | |
5979 // @selector ( selector ) | |
5980 Builder.AddResultTypeChunk("SEL"); | |
5981 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "selector")); | |
5982 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
5983 Builder.AddPlaceholderChunk("selector"); | |
5984 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
5985 Results.AddResult(Result(Builder.TakeString())); | |
5986 | |
5987 // @"string" | |
5988 Builder.AddResultTypeChunk("NSString *"); | |
5989 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "\"")); | |
5990 Builder.AddPlaceholderChunk("string"); | |
5991 Builder.AddTextChunk("\""); | |
5992 Results.AddResult(Result(Builder.TakeString())); | |
5993 | |
5994 // @[objects, ...] | |
5995 Builder.AddResultTypeChunk("NSArray *"); | |
5996 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "[")); | |
5997 Builder.AddPlaceholderChunk("objects, ..."); | |
5998 Builder.AddChunk(CodeCompletionString::CK_RightBracket); | |
5999 Results.AddResult(Result(Builder.TakeString())); | |
6000 | |
6001 // @{key : object, ...} | |
6002 Builder.AddResultTypeChunk("NSDictionary *"); | |
6003 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "{")); | |
6004 Builder.AddPlaceholderChunk("key"); | |
6005 Builder.AddChunk(CodeCompletionString::CK_Colon); | |
6006 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
6007 Builder.AddPlaceholderChunk("object, ..."); | |
6008 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
6009 Results.AddResult(Result(Builder.TakeString())); | |
6010 | |
6011 // @(expression) | |
6012 Builder.AddResultTypeChunk("id"); | |
6013 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "(")); | |
6014 Builder.AddPlaceholderChunk("expression"); | |
6015 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
6016 Results.AddResult(Result(Builder.TakeString())); | |
6017 } | |
6018 | |
6019 static void AddObjCStatementResults(ResultBuilder &Results, bool NeedAt) { | |
6020 typedef CodeCompletionResult Result; | |
6021 CodeCompletionBuilder Builder(Results.getAllocator(), | |
6022 Results.getCodeCompletionTUInfo()); | |
6023 | |
6024 if (Results.includeCodePatterns()) { | |
6025 // @try { statements } @catch ( declaration ) { statements } @finally | |
6026 // { statements } | |
6027 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "try")); | |
6028 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
6029 Builder.AddPlaceholderChunk("statements"); | |
6030 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
6031 Builder.AddTextChunk("@catch"); | |
6032 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
6033 Builder.AddPlaceholderChunk("parameter"); | |
6034 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
6035 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
6036 Builder.AddPlaceholderChunk("statements"); | |
6037 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
6038 Builder.AddTextChunk("@finally"); | |
6039 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
6040 Builder.AddPlaceholderChunk("statements"); | |
6041 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
6042 Results.AddResult(Result(Builder.TakeString())); | |
6043 } | |
6044 | |
6045 // @throw | |
6046 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "throw")); | |
6047 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
6048 Builder.AddPlaceholderChunk("expression"); | |
6049 Results.AddResult(Result(Builder.TakeString())); | |
6050 | |
6051 if (Results.includeCodePatterns()) { | |
6052 // @synchronized ( expression ) { statements } | |
6053 Builder.AddTypedTextChunk(OBJC_AT_KEYWORD_NAME(NeedAt, "synchronized")); | |
6054 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
6055 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
6056 Builder.AddPlaceholderChunk("expression"); | |
6057 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
6058 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
6059 Builder.AddPlaceholderChunk("statements"); | |
6060 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
6061 Results.AddResult(Result(Builder.TakeString())); | |
6062 } | |
6063 } | |
6064 | |
6065 static void AddObjCVisibilityResults(const LangOptions &LangOpts, | |
6066 ResultBuilder &Results, bool NeedAt) { | |
6067 typedef CodeCompletionResult Result; | |
6068 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "private"))); | |
6069 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "protected"))); | |
6070 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "public"))); | |
6071 if (LangOpts.ObjC) | |
6072 Results.AddResult(Result(OBJC_AT_KEYWORD_NAME(NeedAt, "package"))); | |
6073 } | |
6074 | |
6075 void Sema::CodeCompleteObjCAtVisibility(Scope *S) { | |
6076 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
6077 CodeCompleter->getCodeCompletionTUInfo(), | |
6078 CodeCompletionContext::CCC_Other); | |
6079 Results.EnterNewScope(); | |
6080 AddObjCVisibilityResults(getLangOpts(), Results, false); | |
6081 Results.ExitScope(); | |
6082 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
6083 Results.data(), Results.size()); | |
6084 } | |
6085 | |
6086 void Sema::CodeCompleteObjCAtStatement(Scope *S) { | |
6087 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
6088 CodeCompleter->getCodeCompletionTUInfo(), | |
6089 CodeCompletionContext::CCC_Other); | |
6090 Results.EnterNewScope(); | |
6091 AddObjCStatementResults(Results, false); | |
6092 AddObjCExpressionResults(Results, false); | |
6093 Results.ExitScope(); | |
6094 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
6095 Results.data(), Results.size()); | |
6096 } | |
6097 | |
6098 void Sema::CodeCompleteObjCAtExpression(Scope *S) { | |
6099 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
6100 CodeCompleter->getCodeCompletionTUInfo(), | |
6101 CodeCompletionContext::CCC_Other); | |
6102 Results.EnterNewScope(); | |
6103 AddObjCExpressionResults(Results, false); | |
6104 Results.ExitScope(); | |
6105 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
6106 Results.data(), Results.size()); | |
6107 } | |
6108 | |
6109 /// Determine whether the addition of the given flag to an Objective-C | |
6110 /// property's attributes will cause a conflict. | |
6111 static bool ObjCPropertyFlagConflicts(unsigned Attributes, unsigned NewFlag) { | |
6112 // Check if we've already added this flag. | |
6113 if (Attributes & NewFlag) | |
6114 return true; | |
6115 | |
6116 Attributes |= NewFlag; | |
6117 | |
6118 // Check for collisions with "readonly". | |
6119 if ((Attributes & ObjCDeclSpec::DQ_PR_readonly) && | |
6120 (Attributes & ObjCDeclSpec::DQ_PR_readwrite)) | |
6121 return true; | |
6122 | |
6123 // Check for more than one of { assign, copy, retain, strong, weak }. | |
6124 unsigned AssignCopyRetMask = | |
6125 Attributes & | |
6126 (ObjCDeclSpec::DQ_PR_assign | ObjCDeclSpec::DQ_PR_unsafe_unretained | | |
6127 ObjCDeclSpec::DQ_PR_copy | ObjCDeclSpec::DQ_PR_retain | | |
6128 ObjCDeclSpec::DQ_PR_strong | ObjCDeclSpec::DQ_PR_weak); | |
6129 if (AssignCopyRetMask && AssignCopyRetMask != ObjCDeclSpec::DQ_PR_assign && | |
6130 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_unsafe_unretained && | |
6131 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_copy && | |
6132 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_retain && | |
6133 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_strong && | |
6134 AssignCopyRetMask != ObjCDeclSpec::DQ_PR_weak) | |
6135 return true; | |
6136 | |
6137 return false; | |
6138 } | |
6139 | |
6140 void Sema::CodeCompleteObjCPropertyFlags(Scope *S, ObjCDeclSpec &ODS) { | |
6141 if (!CodeCompleter) | |
6142 return; | |
6143 | |
6144 unsigned Attributes = ODS.getPropertyAttributes(); | |
6145 | |
6146 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
6147 CodeCompleter->getCodeCompletionTUInfo(), | |
6148 CodeCompletionContext::CCC_Other); | |
6149 Results.EnterNewScope(); | |
6150 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readonly)) | |
6151 Results.AddResult(CodeCompletionResult("readonly")); | |
6152 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_assign)) | |
6153 Results.AddResult(CodeCompletionResult("assign")); | |
6154 if (!ObjCPropertyFlagConflicts(Attributes, | |
6155 ObjCDeclSpec::DQ_PR_unsafe_unretained)) | |
6156 Results.AddResult(CodeCompletionResult("unsafe_unretained")); | |
6157 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_readwrite)) | |
6158 Results.AddResult(CodeCompletionResult("readwrite")); | |
6159 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_retain)) | |
6160 Results.AddResult(CodeCompletionResult("retain")); | |
6161 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_strong)) | |
6162 Results.AddResult(CodeCompletionResult("strong")); | |
6163 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_copy)) | |
6164 Results.AddResult(CodeCompletionResult("copy")); | |
6165 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nonatomic)) | |
6166 Results.AddResult(CodeCompletionResult("nonatomic")); | |
6167 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_atomic)) | |
6168 Results.AddResult(CodeCompletionResult("atomic")); | |
6169 | |
6170 // Only suggest "weak" if we're compiling for ARC-with-weak-references or GC. | |
6171 if (getLangOpts().ObjCWeak || getLangOpts().getGC() != LangOptions::NonGC) | |
6172 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_weak)) | |
6173 Results.AddResult(CodeCompletionResult("weak")); | |
6174 | |
6175 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_setter)) { | |
6176 CodeCompletionBuilder Setter(Results.getAllocator(), | |
6177 Results.getCodeCompletionTUInfo()); | |
6178 Setter.AddTypedTextChunk("setter"); | |
6179 Setter.AddTextChunk("="); | |
6180 Setter.AddPlaceholderChunk("method"); | |
6181 Results.AddResult(CodeCompletionResult(Setter.TakeString())); | |
6182 } | |
6183 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_getter)) { | |
6184 CodeCompletionBuilder Getter(Results.getAllocator(), | |
6185 Results.getCodeCompletionTUInfo()); | |
6186 Getter.AddTypedTextChunk("getter"); | |
6187 Getter.AddTextChunk("="); | |
6188 Getter.AddPlaceholderChunk("method"); | |
6189 Results.AddResult(CodeCompletionResult(Getter.TakeString())); | |
6190 } | |
6191 if (!ObjCPropertyFlagConflicts(Attributes, ObjCDeclSpec::DQ_PR_nullability)) { | |
6192 Results.AddResult(CodeCompletionResult("nonnull")); | |
6193 Results.AddResult(CodeCompletionResult("nullable")); | |
6194 Results.AddResult(CodeCompletionResult("null_unspecified")); | |
6195 Results.AddResult(CodeCompletionResult("null_resettable")); | |
6196 } | |
6197 Results.ExitScope(); | |
6198 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
6199 Results.data(), Results.size()); | |
6200 } | |
6201 | |
6202 /// Describes the kind of Objective-C method that we want to find | |
6203 /// via code completion. | |
6204 enum ObjCMethodKind { | |
6205 MK_Any, ///< Any kind of method, provided it means other specified criteria. | |
6206 MK_ZeroArgSelector, ///< Zero-argument (unary) selector. | |
6207 MK_OneArgSelector ///< One-argument selector. | |
6208 }; | |
6209 | |
6210 static bool isAcceptableObjCSelector(Selector Sel, ObjCMethodKind WantKind, | |
6211 ArrayRef<IdentifierInfo *> SelIdents, | |
6212 bool AllowSameLength = true) { | |
6213 unsigned NumSelIdents = SelIdents.size(); | |
6214 if (NumSelIdents > Sel.getNumArgs()) | |
6215 return false; | |
6216 | |
6217 switch (WantKind) { | |
6218 case MK_Any: | |
6219 break; | |
6220 case MK_ZeroArgSelector: | |
6221 return Sel.isUnarySelector(); | |
6222 case MK_OneArgSelector: | |
6223 return Sel.getNumArgs() == 1; | |
6224 } | |
6225 | |
6226 if (!AllowSameLength && NumSelIdents && NumSelIdents == Sel.getNumArgs()) | |
6227 return false; | |
6228 | |
6229 for (unsigned I = 0; I != NumSelIdents; ++I) | |
6230 if (SelIdents[I] != Sel.getIdentifierInfoForSlot(I)) | |
6231 return false; | |
6232 | |
6233 return true; | |
6234 } | |
6235 | |
6236 static bool isAcceptableObjCMethod(ObjCMethodDecl *Method, | |
6237 ObjCMethodKind WantKind, | |
6238 ArrayRef<IdentifierInfo *> SelIdents, | |
6239 bool AllowSameLength = true) { | |
6240 return isAcceptableObjCSelector(Method->getSelector(), WantKind, SelIdents, | |
6241 AllowSameLength); | |
6242 } | |
6243 | |
6244 /// A set of selectors, which is used to avoid introducing multiple | |
6245 /// completions with the same selector into the result set. | |
6246 typedef llvm::SmallPtrSet<Selector, 16> VisitedSelectorSet; | |
6247 | |
6248 /// Add all of the Objective-C methods in the given Objective-C | |
6249 /// container to the set of results. | |
6250 /// | |
6251 /// The container will be a class, protocol, category, or implementation of | |
6252 /// any of the above. This mether will recurse to include methods from | |
6253 /// the superclasses of classes along with their categories, protocols, and | |
6254 /// implementations. | |
6255 /// | |
6256 /// \param Container the container in which we'll look to find methods. | |
6257 /// | |
6258 /// \param WantInstanceMethods Whether to add instance methods (only); if | |
6259 /// false, this routine will add factory methods (only). | |
6260 /// | |
6261 /// \param CurContext the context in which we're performing the lookup that | |
6262 /// finds methods. | |
6263 /// | |
6264 /// \param AllowSameLength Whether we allow a method to be added to the list | |
6265 /// when it has the same number of parameters as we have selector identifiers. | |
6266 /// | |
6267 /// \param Results the structure into which we'll add results. | |
6268 static void AddObjCMethods(ObjCContainerDecl *Container, | |
6269 bool WantInstanceMethods, ObjCMethodKind WantKind, | |
6270 ArrayRef<IdentifierInfo *> SelIdents, | |
6271 DeclContext *CurContext, | |
6272 VisitedSelectorSet &Selectors, bool AllowSameLength, | |
6273 ResultBuilder &Results, bool InOriginalClass = true, | |
6274 bool IsRootClass = false) { | |
6275 typedef CodeCompletionResult Result; | |
6276 Container = getContainerDef(Container); | |
6277 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container); | |
6278 IsRootClass = IsRootClass || (IFace && !IFace->getSuperClass()); | |
6279 for (ObjCMethodDecl *M : Container->methods()) { | |
6280 // The instance methods on the root class can be messaged via the | |
6281 // metaclass. | |
6282 if (M->isInstanceMethod() == WantInstanceMethods || | |
6283 (IsRootClass && !WantInstanceMethods)) { | |
6284 // Check whether the selector identifiers we've been given are a | |
6285 // subset of the identifiers for this particular method. | |
6286 if (!isAcceptableObjCMethod(M, WantKind, SelIdents, AllowSameLength)) | |
6287 continue; | |
6288 | |
6289 if (!Selectors.insert(M->getSelector()).second) | |
6290 continue; | |
6291 | |
6292 Result R = Result(M, Results.getBasePriority(M), nullptr); | |
6293 R.StartParameter = SelIdents.size(); | |
6294 R.AllParametersAreInformative = (WantKind != MK_Any); | |
6295 if (!InOriginalClass) | |
6296 setInBaseClass(R); | |
6297 Results.MaybeAddResult(R, CurContext); | |
6298 } | |
6299 } | |
6300 | |
6301 // Visit the protocols of protocols. | |
6302 if (const auto *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { | |
6303 if (Protocol->hasDefinition()) { | |
6304 const ObjCList<ObjCProtocolDecl> &Protocols = | |
6305 Protocol->getReferencedProtocols(); | |
6306 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), | |
6307 E = Protocols.end(); | |
6308 I != E; ++I) | |
6309 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext, | |
6310 Selectors, AllowSameLength, Results, false, IsRootClass); | |
6311 } | |
6312 } | |
6313 | |
6314 if (!IFace || !IFace->hasDefinition()) | |
6315 return; | |
6316 | |
6317 // Add methods in protocols. | |
6318 for (ObjCProtocolDecl *I : IFace->protocols()) | |
6319 AddObjCMethods(I, WantInstanceMethods, WantKind, SelIdents, CurContext, | |
6320 Selectors, AllowSameLength, Results, false, IsRootClass); | |
6321 | |
6322 // Add methods in categories. | |
6323 for (ObjCCategoryDecl *CatDecl : IFace->known_categories()) { | |
6324 AddObjCMethods(CatDecl, WantInstanceMethods, WantKind, SelIdents, | |
6325 CurContext, Selectors, AllowSameLength, Results, | |
6326 InOriginalClass, IsRootClass); | |
6327 | |
6328 // Add a categories protocol methods. | |
6329 const ObjCList<ObjCProtocolDecl> &Protocols = | |
6330 CatDecl->getReferencedProtocols(); | |
6331 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), | |
6332 E = Protocols.end(); | |
6333 I != E; ++I) | |
6334 AddObjCMethods(*I, WantInstanceMethods, WantKind, SelIdents, CurContext, | |
6335 Selectors, AllowSameLength, Results, false, IsRootClass); | |
6336 | |
6337 // Add methods in category implementations. | |
6338 if (ObjCCategoryImplDecl *Impl = CatDecl->getImplementation()) | |
6339 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext, | |
6340 Selectors, AllowSameLength, Results, InOriginalClass, | |
6341 IsRootClass); | |
6342 } | |
6343 | |
6344 // Add methods in superclass. | |
6345 // Avoid passing in IsRootClass since root classes won't have super classes. | |
6346 if (IFace->getSuperClass()) | |
6347 AddObjCMethods(IFace->getSuperClass(), WantInstanceMethods, WantKind, | |
6348 SelIdents, CurContext, Selectors, AllowSameLength, Results, | |
6349 /*IsRootClass=*/false); | |
6350 | |
6351 // Add methods in our implementation, if any. | |
6352 if (ObjCImplementationDecl *Impl = IFace->getImplementation()) | |
6353 AddObjCMethods(Impl, WantInstanceMethods, WantKind, SelIdents, CurContext, | |
6354 Selectors, AllowSameLength, Results, InOriginalClass, | |
6355 IsRootClass); | |
6356 } | |
6357 | |
6358 void Sema::CodeCompleteObjCPropertyGetter(Scope *S) { | |
6359 // Try to find the interface where getters might live. | |
6360 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); | |
6361 if (!Class) { | |
6362 if (ObjCCategoryDecl *Category = | |
6363 dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) | |
6364 Class = Category->getClassInterface(); | |
6365 | |
6366 if (!Class) | |
6367 return; | |
6368 } | |
6369 | |
6370 // Find all of the potential getters. | |
6371 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
6372 CodeCompleter->getCodeCompletionTUInfo(), | |
6373 CodeCompletionContext::CCC_Other); | |
6374 Results.EnterNewScope(); | |
6375 | |
6376 VisitedSelectorSet Selectors; | |
6377 AddObjCMethods(Class, true, MK_ZeroArgSelector, None, CurContext, Selectors, | |
6378 /*AllowSameLength=*/true, Results); | |
6379 Results.ExitScope(); | |
6380 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
6381 Results.data(), Results.size()); | |
6382 } | |
6383 | |
6384 void Sema::CodeCompleteObjCPropertySetter(Scope *S) { | |
6385 // Try to find the interface where setters might live. | |
6386 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurContext); | |
6387 if (!Class) { | |
6388 if (ObjCCategoryDecl *Category = | |
6389 dyn_cast_or_null<ObjCCategoryDecl>(CurContext)) | |
6390 Class = Category->getClassInterface(); | |
6391 | |
6392 if (!Class) | |
6393 return; | |
6394 } | |
6395 | |
6396 // Find all of the potential getters. | |
6397 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
6398 CodeCompleter->getCodeCompletionTUInfo(), | |
6399 CodeCompletionContext::CCC_Other); | |
6400 Results.EnterNewScope(); | |
6401 | |
6402 VisitedSelectorSet Selectors; | |
6403 AddObjCMethods(Class, true, MK_OneArgSelector, None, CurContext, Selectors, | |
6404 /*AllowSameLength=*/true, Results); | |
6405 | |
6406 Results.ExitScope(); | |
6407 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
6408 Results.data(), Results.size()); | |
6409 } | |
6410 | |
6411 void Sema::CodeCompleteObjCPassingType(Scope *S, ObjCDeclSpec &DS, | |
6412 bool IsParameter) { | |
6413 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
6414 CodeCompleter->getCodeCompletionTUInfo(), | |
6415 CodeCompletionContext::CCC_Type); | |
6416 Results.EnterNewScope(); | |
6417 | |
6418 // Add context-sensitive, Objective-C parameter-passing keywords. | |
6419 bool AddedInOut = false; | |
6420 if ((DS.getObjCDeclQualifier() & | |
6421 (ObjCDeclSpec::DQ_In | ObjCDeclSpec::DQ_Inout)) == 0) { | |
6422 Results.AddResult("in"); | |
6423 Results.AddResult("inout"); | |
6424 AddedInOut = true; | |
6425 } | |
6426 if ((DS.getObjCDeclQualifier() & | |
6427 (ObjCDeclSpec::DQ_Out | ObjCDeclSpec::DQ_Inout)) == 0) { | |
6428 Results.AddResult("out"); | |
6429 if (!AddedInOut) | |
6430 Results.AddResult("inout"); | |
6431 } | |
6432 if ((DS.getObjCDeclQualifier() & | |
6433 (ObjCDeclSpec::DQ_Bycopy | ObjCDeclSpec::DQ_Byref | | |
6434 ObjCDeclSpec::DQ_Oneway)) == 0) { | |
6435 Results.AddResult("bycopy"); | |
6436 Results.AddResult("byref"); | |
6437 Results.AddResult("oneway"); | |
6438 } | |
6439 if ((DS.getObjCDeclQualifier() & ObjCDeclSpec::DQ_CSNullability) == 0) { | |
6440 Results.AddResult("nonnull"); | |
6441 Results.AddResult("nullable"); | |
6442 Results.AddResult("null_unspecified"); | |
6443 } | |
6444 | |
6445 // If we're completing the return type of an Objective-C method and the | |
6446 // identifier IBAction refers to a macro, provide a completion item for | |
6447 // an action, e.g., | |
6448 // IBAction)<#selector#>:(id)sender | |
6449 if (DS.getObjCDeclQualifier() == 0 && !IsParameter && | |
6450 PP.isMacroDefined("IBAction")) { | |
6451 CodeCompletionBuilder Builder(Results.getAllocator(), | |
6452 Results.getCodeCompletionTUInfo(), | |
6453 CCP_CodePattern, CXAvailability_Available); | |
6454 Builder.AddTypedTextChunk("IBAction"); | |
6455 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
6456 Builder.AddPlaceholderChunk("selector"); | |
6457 Builder.AddChunk(CodeCompletionString::CK_Colon); | |
6458 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
6459 Builder.AddTextChunk("id"); | |
6460 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
6461 Builder.AddTextChunk("sender"); | |
6462 Results.AddResult(CodeCompletionResult(Builder.TakeString())); | |
6463 } | |
6464 | |
6465 // If we're completing the return type, provide 'instancetype'. | |
6466 if (!IsParameter) { | |
6467 Results.AddResult(CodeCompletionResult("instancetype")); | |
6468 } | |
6469 | |
6470 // Add various builtin type names and specifiers. | |
6471 AddOrdinaryNameResults(PCC_Type, S, *this, Results); | |
6472 Results.ExitScope(); | |
6473 | |
6474 // Add the various type names | |
6475 Results.setFilter(&ResultBuilder::IsOrdinaryNonValueName); | |
6476 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
6477 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
6478 CodeCompleter->includeGlobals(), | |
6479 CodeCompleter->loadExternal()); | |
6480 | |
6481 if (CodeCompleter->includeMacros()) | |
6482 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); | |
6483 | |
6484 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
6485 Results.data(), Results.size()); | |
6486 } | |
6487 | |
6488 /// When we have an expression with type "id", we may assume | |
6489 /// that it has some more-specific class type based on knowledge of | |
6490 /// common uses of Objective-C. This routine returns that class type, | |
6491 /// or NULL if no better result could be determined. | |
6492 static ObjCInterfaceDecl *GetAssumedMessageSendExprType(Expr *E) { | |
6493 auto *Msg = dyn_cast_or_null<ObjCMessageExpr>(E); | |
6494 if (!Msg) | |
6495 return nullptr; | |
6496 | |
6497 Selector Sel = Msg->getSelector(); | |
6498 if (Sel.isNull()) | |
6499 return nullptr; | |
6500 | |
6501 IdentifierInfo *Id = Sel.getIdentifierInfoForSlot(0); | |
6502 if (!Id) | |
6503 return nullptr; | |
6504 | |
6505 ObjCMethodDecl *Method = Msg->getMethodDecl(); | |
6506 if (!Method) | |
6507 return nullptr; | |
6508 | |
6509 // Determine the class that we're sending the message to. | |
6510 ObjCInterfaceDecl *IFace = nullptr; | |
6511 switch (Msg->getReceiverKind()) { | |
6512 case ObjCMessageExpr::Class: | |
6513 if (const ObjCObjectType *ObjType = | |
6514 Msg->getClassReceiver()->getAs<ObjCObjectType>()) | |
6515 IFace = ObjType->getInterface(); | |
6516 break; | |
6517 | |
6518 case ObjCMessageExpr::Instance: { | |
6519 QualType T = Msg->getInstanceReceiver()->getType(); | |
6520 if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>()) | |
6521 IFace = Ptr->getInterfaceDecl(); | |
6522 break; | |
6523 } | |
6524 | |
6525 case ObjCMessageExpr::SuperInstance: | |
6526 case ObjCMessageExpr::SuperClass: | |
6527 break; | |
6528 } | |
6529 | |
6530 if (!IFace) | |
6531 return nullptr; | |
6532 | |
6533 ObjCInterfaceDecl *Super = IFace->getSuperClass(); | |
6534 if (Method->isInstanceMethod()) | |
6535 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) | |
6536 .Case("retain", IFace) | |
6537 .Case("strong", IFace) | |
6538 .Case("autorelease", IFace) | |
6539 .Case("copy", IFace) | |
6540 .Case("copyWithZone", IFace) | |
6541 .Case("mutableCopy", IFace) | |
6542 .Case("mutableCopyWithZone", IFace) | |
6543 .Case("awakeFromCoder", IFace) | |
6544 .Case("replacementObjectFromCoder", IFace) | |
6545 .Case("class", IFace) | |
6546 .Case("classForCoder", IFace) | |
6547 .Case("superclass", Super) | |
6548 .Default(nullptr); | |
6549 | |
6550 return llvm::StringSwitch<ObjCInterfaceDecl *>(Id->getName()) | |
6551 .Case("new", IFace) | |
6552 .Case("alloc", IFace) | |
6553 .Case("allocWithZone", IFace) | |
6554 .Case("class", IFace) | |
6555 .Case("superclass", Super) | |
6556 .Default(nullptr); | |
6557 } | |
6558 | |
6559 // Add a special completion for a message send to "super", which fills in the | |
6560 // most likely case of forwarding all of our arguments to the superclass | |
6561 // function. | |
6562 /// | |
6563 /// \param S The semantic analysis object. | |
6564 /// | |
6565 /// \param NeedSuperKeyword Whether we need to prefix this completion with | |
6566 /// the "super" keyword. Otherwise, we just need to provide the arguments. | |
6567 /// | |
6568 /// \param SelIdents The identifiers in the selector that have already been | |
6569 /// provided as arguments for a send to "super". | |
6570 /// | |
6571 /// \param Results The set of results to augment. | |
6572 /// | |
6573 /// \returns the Objective-C method declaration that would be invoked by | |
6574 /// this "super" completion. If NULL, no completion was added. | |
6575 static ObjCMethodDecl * | |
6576 AddSuperSendCompletion(Sema &S, bool NeedSuperKeyword, | |
6577 ArrayRef<IdentifierInfo *> SelIdents, | |
6578 ResultBuilder &Results) { | |
6579 ObjCMethodDecl *CurMethod = S.getCurMethodDecl(); | |
6580 if (!CurMethod) | |
6581 return nullptr; | |
6582 | |
6583 ObjCInterfaceDecl *Class = CurMethod->getClassInterface(); | |
6584 if (!Class) | |
6585 return nullptr; | |
6586 | |
6587 // Try to find a superclass method with the same selector. | |
6588 ObjCMethodDecl *SuperMethod = nullptr; | |
6589 while ((Class = Class->getSuperClass()) && !SuperMethod) { | |
6590 // Check in the class | |
6591 SuperMethod = Class->getMethod(CurMethod->getSelector(), | |
6592 CurMethod->isInstanceMethod()); | |
6593 | |
6594 // Check in categories or class extensions. | |
6595 if (!SuperMethod) { | |
6596 for (const auto *Cat : Class->known_categories()) { | |
6597 if ((SuperMethod = Cat->getMethod(CurMethod->getSelector(), | |
6598 CurMethod->isInstanceMethod()))) | |
6599 break; | |
6600 } | |
6601 } | |
6602 } | |
6603 | |
6604 if (!SuperMethod) | |
6605 return nullptr; | |
6606 | |
6607 // Check whether the superclass method has the same signature. | |
6608 if (CurMethod->param_size() != SuperMethod->param_size() || | |
6609 CurMethod->isVariadic() != SuperMethod->isVariadic()) | |
6610 return nullptr; | |
6611 | |
6612 for (ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(), | |
6613 CurPEnd = CurMethod->param_end(), | |
6614 SuperP = SuperMethod->param_begin(); | |
6615 CurP != CurPEnd; ++CurP, ++SuperP) { | |
6616 // Make sure the parameter types are compatible. | |
6617 if (!S.Context.hasSameUnqualifiedType((*CurP)->getType(), | |
6618 (*SuperP)->getType())) | |
6619 return nullptr; | |
6620 | |
6621 // Make sure we have a parameter name to forward! | |
6622 if (!(*CurP)->getIdentifier()) | |
6623 return nullptr; | |
6624 } | |
6625 | |
6626 // We have a superclass method. Now, form the send-to-super completion. | |
6627 CodeCompletionBuilder Builder(Results.getAllocator(), | |
6628 Results.getCodeCompletionTUInfo()); | |
6629 | |
6630 // Give this completion a return type. | |
6631 AddResultTypeChunk(S.Context, getCompletionPrintingPolicy(S), SuperMethod, | |
6632 Results.getCompletionContext().getBaseType(), Builder); | |
6633 | |
6634 // If we need the "super" keyword, add it (plus some spacing). | |
6635 if (NeedSuperKeyword) { | |
6636 Builder.AddTypedTextChunk("super"); | |
6637 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
6638 } | |
6639 | |
6640 Selector Sel = CurMethod->getSelector(); | |
6641 if (Sel.isUnarySelector()) { | |
6642 if (NeedSuperKeyword) | |
6643 Builder.AddTextChunk( | |
6644 Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); | |
6645 else | |
6646 Builder.AddTypedTextChunk( | |
6647 Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); | |
6648 } else { | |
6649 ObjCMethodDecl::param_iterator CurP = CurMethod->param_begin(); | |
6650 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I, ++CurP) { | |
6651 if (I > SelIdents.size()) | |
6652 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
6653 | |
6654 if (I < SelIdents.size()) | |
6655 Builder.AddInformativeChunk( | |
6656 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); | |
6657 else if (NeedSuperKeyword || I > SelIdents.size()) { | |
6658 Builder.AddTextChunk( | |
6659 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); | |
6660 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( | |
6661 (*CurP)->getIdentifier()->getName())); | |
6662 } else { | |
6663 Builder.AddTypedTextChunk( | |
6664 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); | |
6665 Builder.AddPlaceholderChunk(Builder.getAllocator().CopyString( | |
6666 (*CurP)->getIdentifier()->getName())); | |
6667 } | |
6668 } | |
6669 } | |
6670 | |
6671 Results.AddResult(CodeCompletionResult(Builder.TakeString(), SuperMethod, | |
6672 CCP_SuperCompletion)); | |
6673 return SuperMethod; | |
6674 } | |
6675 | |
6676 void Sema::CodeCompleteObjCMessageReceiver(Scope *S) { | |
6677 typedef CodeCompletionResult Result; | |
6678 ResultBuilder Results( | |
6679 *this, CodeCompleter->getAllocator(), | |
6680 CodeCompleter->getCodeCompletionTUInfo(), | |
6681 CodeCompletionContext::CCC_ObjCMessageReceiver, | |
6682 getLangOpts().CPlusPlus11 | |
6683 ? &ResultBuilder::IsObjCMessageReceiverOrLambdaCapture | |
6684 : &ResultBuilder::IsObjCMessageReceiver); | |
6685 | |
6686 CodeCompletionDeclConsumer Consumer(Results, CurContext); | |
6687 Results.EnterNewScope(); | |
6688 LookupVisibleDecls(S, LookupOrdinaryName, Consumer, | |
6689 CodeCompleter->includeGlobals(), | |
6690 CodeCompleter->loadExternal()); | |
6691 | |
6692 // If we are in an Objective-C method inside a class that has a superclass, | |
6693 // add "super" as an option. | |
6694 if (ObjCMethodDecl *Method = getCurMethodDecl()) | |
6695 if (ObjCInterfaceDecl *Iface = Method->getClassInterface()) | |
6696 if (Iface->getSuperClass()) { | |
6697 Results.AddResult(Result("super")); | |
6698 | |
6699 AddSuperSendCompletion(*this, /*NeedSuperKeyword=*/true, None, Results); | |
6700 } | |
6701 | |
6702 if (getLangOpts().CPlusPlus11) | |
6703 addThisCompletion(*this, Results); | |
6704 | |
6705 Results.ExitScope(); | |
6706 | |
6707 if (CodeCompleter->includeMacros()) | |
6708 AddMacroResults(PP, Results, CodeCompleter->loadExternal(), false); | |
6709 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
6710 Results.data(), Results.size()); | |
6711 } | |
6712 | |
6713 void Sema::CodeCompleteObjCSuperMessage(Scope *S, SourceLocation SuperLoc, | |
6714 ArrayRef<IdentifierInfo *> SelIdents, | |
6715 bool AtArgumentExpression) { | |
6716 ObjCInterfaceDecl *CDecl = nullptr; | |
6717 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { | |
6718 // Figure out which interface we're in. | |
6719 CDecl = CurMethod->getClassInterface(); | |
6720 if (!CDecl) | |
6721 return; | |
6722 | |
6723 // Find the superclass of this class. | |
6724 CDecl = CDecl->getSuperClass(); | |
6725 if (!CDecl) | |
6726 return; | |
6727 | |
6728 if (CurMethod->isInstanceMethod()) { | |
6729 // We are inside an instance method, which means that the message | |
6730 // send [super ...] is actually calling an instance method on the | |
6731 // current object. | |
6732 return CodeCompleteObjCInstanceMessage(S, nullptr, SelIdents, | |
6733 AtArgumentExpression, CDecl); | |
6734 } | |
6735 | |
6736 // Fall through to send to the superclass in CDecl. | |
6737 } else { | |
6738 // "super" may be the name of a type or variable. Figure out which | |
6739 // it is. | |
6740 IdentifierInfo *Super = getSuperIdentifier(); | |
6741 NamedDecl *ND = LookupSingleName(S, Super, SuperLoc, LookupOrdinaryName); | |
6742 if ((CDecl = dyn_cast_or_null<ObjCInterfaceDecl>(ND))) { | |
6743 // "super" names an interface. Use it. | |
6744 } else if (TypeDecl *TD = dyn_cast_or_null<TypeDecl>(ND)) { | |
6745 if (const ObjCObjectType *Iface = | |
6746 Context.getTypeDeclType(TD)->getAs<ObjCObjectType>()) | |
6747 CDecl = Iface->getInterface(); | |
6748 } else if (ND && isa<UnresolvedUsingTypenameDecl>(ND)) { | |
6749 // "super" names an unresolved type; we can't be more specific. | |
6750 } else { | |
6751 // Assume that "super" names some kind of value and parse that way. | |
6752 CXXScopeSpec SS; | |
6753 SourceLocation TemplateKWLoc; | |
6754 UnqualifiedId id; | |
6755 id.setIdentifier(Super, SuperLoc); | |
6756 ExprResult SuperExpr = ActOnIdExpression(S, SS, TemplateKWLoc, id, | |
6757 /*HasTrailingLParen=*/false, | |
6758 /*IsAddressOfOperand=*/false); | |
6759 return CodeCompleteObjCInstanceMessage(S, (Expr *)SuperExpr.get(), | |
6760 SelIdents, AtArgumentExpression); | |
6761 } | |
6762 | |
6763 // Fall through | |
6764 } | |
6765 | |
6766 ParsedType Receiver; | |
6767 if (CDecl) | |
6768 Receiver = ParsedType::make(Context.getObjCInterfaceType(CDecl)); | |
6769 return CodeCompleteObjCClassMessage(S, Receiver, SelIdents, | |
6770 AtArgumentExpression, | |
6771 /*IsSuper=*/true); | |
6772 } | |
6773 | |
6774 /// Given a set of code-completion results for the argument of a message | |
6775 /// send, determine the preferred type (if any) for that argument expression. | |
6776 static QualType getPreferredArgumentTypeForMessageSend(ResultBuilder &Results, | |
6777 unsigned NumSelIdents) { | |
6778 typedef CodeCompletionResult Result; | |
6779 ASTContext &Context = Results.getSema().Context; | |
6780 | |
6781 QualType PreferredType; | |
6782 unsigned BestPriority = CCP_Unlikely * 2; | |
6783 Result *ResultsData = Results.data(); | |
6784 for (unsigned I = 0, N = Results.size(); I != N; ++I) { | |
6785 Result &R = ResultsData[I]; | |
6786 if (R.Kind == Result::RK_Declaration && | |
6787 isa<ObjCMethodDecl>(R.Declaration)) { | |
6788 if (R.Priority <= BestPriority) { | |
6789 const ObjCMethodDecl *Method = cast<ObjCMethodDecl>(R.Declaration); | |
6790 if (NumSelIdents <= Method->param_size()) { | |
6791 QualType MyPreferredType = | |
6792 Method->parameters()[NumSelIdents - 1]->getType(); | |
6793 if (R.Priority < BestPriority || PreferredType.isNull()) { | |
6794 BestPriority = R.Priority; | |
6795 PreferredType = MyPreferredType; | |
6796 } else if (!Context.hasSameUnqualifiedType(PreferredType, | |
6797 MyPreferredType)) { | |
6798 PreferredType = QualType(); | |
6799 } | |
6800 } | |
6801 } | |
6802 } | |
6803 } | |
6804 | |
6805 return PreferredType; | |
6806 } | |
6807 | |
6808 static void AddClassMessageCompletions(Sema &SemaRef, Scope *S, | |
6809 ParsedType Receiver, | |
6810 ArrayRef<IdentifierInfo *> SelIdents, | |
6811 bool AtArgumentExpression, bool IsSuper, | |
6812 ResultBuilder &Results) { | |
6813 typedef CodeCompletionResult Result; | |
6814 ObjCInterfaceDecl *CDecl = nullptr; | |
6815 | |
6816 // If the given name refers to an interface type, retrieve the | |
6817 // corresponding declaration. | |
6818 if (Receiver) { | |
6819 QualType T = SemaRef.GetTypeFromParser(Receiver, nullptr); | |
6820 if (!T.isNull()) | |
6821 if (const ObjCObjectType *Interface = T->getAs<ObjCObjectType>()) | |
6822 CDecl = Interface->getInterface(); | |
6823 } | |
6824 | |
6825 // Add all of the factory methods in this Objective-C class, its protocols, | |
6826 // superclasses, categories, implementation, etc. | |
6827 Results.EnterNewScope(); | |
6828 | |
6829 // If this is a send-to-super, try to add the special "super" send | |
6830 // completion. | |
6831 if (IsSuper) { | |
6832 if (ObjCMethodDecl *SuperMethod = | |
6833 AddSuperSendCompletion(SemaRef, false, SelIdents, Results)) | |
6834 Results.Ignore(SuperMethod); | |
6835 } | |
6836 | |
6837 // If we're inside an Objective-C method definition, prefer its selector to | |
6838 // others. | |
6839 if (ObjCMethodDecl *CurMethod = SemaRef.getCurMethodDecl()) | |
6840 Results.setPreferredSelector(CurMethod->getSelector()); | |
6841 | |
6842 VisitedSelectorSet Selectors; | |
6843 if (CDecl) | |
6844 AddObjCMethods(CDecl, false, MK_Any, SelIdents, SemaRef.CurContext, | |
6845 Selectors, AtArgumentExpression, Results); | |
6846 else { | |
6847 // We're messaging "id" as a type; provide all class/factory methods. | |
6848 | |
6849 // If we have an external source, load the entire class method | |
6850 // pool from the AST file. | |
6851 if (SemaRef.getExternalSource()) { | |
6852 for (uint32_t I = 0, | |
6853 N = SemaRef.getExternalSource()->GetNumExternalSelectors(); | |
6854 I != N; ++I) { | |
6855 Selector Sel = SemaRef.getExternalSource()->GetExternalSelector(I); | |
6856 if (Sel.isNull() || SemaRef.MethodPool.count(Sel)) | |
6857 continue; | |
6858 | |
6859 SemaRef.ReadMethodPool(Sel); | |
6860 } | |
6861 } | |
6862 | |
6863 for (Sema::GlobalMethodPool::iterator M = SemaRef.MethodPool.begin(), | |
6864 MEnd = SemaRef.MethodPool.end(); | |
6865 M != MEnd; ++M) { | |
6866 for (ObjCMethodList *MethList = &M->second.second; | |
6867 MethList && MethList->getMethod(); MethList = MethList->getNext()) { | |
6868 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) | |
6869 continue; | |
6870 | |
6871 Result R(MethList->getMethod(), | |
6872 Results.getBasePriority(MethList->getMethod()), nullptr); | |
6873 R.StartParameter = SelIdents.size(); | |
6874 R.AllParametersAreInformative = false; | |
6875 Results.MaybeAddResult(R, SemaRef.CurContext); | |
6876 } | |
6877 } | |
6878 } | |
6879 | |
6880 Results.ExitScope(); | |
6881 } | |
6882 | |
6883 void Sema::CodeCompleteObjCClassMessage(Scope *S, ParsedType Receiver, | |
6884 ArrayRef<IdentifierInfo *> SelIdents, | |
6885 bool AtArgumentExpression, | |
6886 bool IsSuper) { | |
6887 | |
6888 QualType T = this->GetTypeFromParser(Receiver); | |
6889 | |
6890 ResultBuilder Results( | |
6891 *this, CodeCompleter->getAllocator(), | |
6892 CodeCompleter->getCodeCompletionTUInfo(), | |
6893 CodeCompletionContext(CodeCompletionContext::CCC_ObjCClassMessage, T, | |
6894 SelIdents)); | |
6895 | |
6896 AddClassMessageCompletions(*this, S, Receiver, SelIdents, | |
6897 AtArgumentExpression, IsSuper, Results); | |
6898 | |
6899 // If we're actually at the argument expression (rather than prior to the | |
6900 // selector), we're actually performing code completion for an expression. | |
6901 // Determine whether we have a single, best method. If so, we can | |
6902 // code-complete the expression using the corresponding parameter type as | |
6903 // our preferred type, improving completion results. | |
6904 if (AtArgumentExpression) { | |
6905 QualType PreferredType = | |
6906 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size()); | |
6907 if (PreferredType.isNull()) | |
6908 CodeCompleteOrdinaryName(S, PCC_Expression); | |
6909 else | |
6910 CodeCompleteExpression(S, PreferredType); | |
6911 return; | |
6912 } | |
6913 | |
6914 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
6915 Results.data(), Results.size()); | |
6916 } | |
6917 | |
6918 void Sema::CodeCompleteObjCInstanceMessage(Scope *S, Expr *Receiver, | |
6919 ArrayRef<IdentifierInfo *> SelIdents, | |
6920 bool AtArgumentExpression, | |
6921 ObjCInterfaceDecl *Super) { | |
6922 typedef CodeCompletionResult Result; | |
6923 | |
6924 Expr *RecExpr = static_cast<Expr *>(Receiver); | |
6925 | |
6926 // If necessary, apply function/array conversion to the receiver. | |
6927 // C99 6.7.5.3p[7,8]. | |
6928 if (RecExpr) { | |
6929 ExprResult Conv = DefaultFunctionArrayLvalueConversion(RecExpr); | |
6930 if (Conv.isInvalid()) // conversion failed. bail. | |
6931 return; | |
6932 RecExpr = Conv.get(); | |
6933 } | |
6934 QualType ReceiverType = RecExpr | |
6935 ? RecExpr->getType() | |
6936 : Super ? Context.getObjCObjectPointerType( | |
6937 Context.getObjCInterfaceType(Super)) | |
6938 : Context.getObjCIdType(); | |
6939 | |
6940 // If we're messaging an expression with type "id" or "Class", check | |
6941 // whether we know something special about the receiver that allows | |
6942 // us to assume a more-specific receiver type. | |
6943 if (ReceiverType->isObjCIdType() || ReceiverType->isObjCClassType()) { | |
6944 if (ObjCInterfaceDecl *IFace = GetAssumedMessageSendExprType(RecExpr)) { | |
6945 if (ReceiverType->isObjCClassType()) | |
6946 return CodeCompleteObjCClassMessage( | |
6947 S, ParsedType::make(Context.getObjCInterfaceType(IFace)), SelIdents, | |
6948 AtArgumentExpression, Super); | |
6949 | |
6950 ReceiverType = | |
6951 Context.getObjCObjectPointerType(Context.getObjCInterfaceType(IFace)); | |
6952 } | |
6953 } else if (RecExpr && getLangOpts().CPlusPlus) { | |
6954 ExprResult Conv = PerformContextuallyConvertToObjCPointer(RecExpr); | |
6955 if (Conv.isUsable()) { | |
6956 RecExpr = Conv.get(); | |
6957 ReceiverType = RecExpr->getType(); | |
6958 } | |
6959 } | |
6960 | |
6961 // Build the set of methods we can see. | |
6962 ResultBuilder Results( | |
6963 *this, CodeCompleter->getAllocator(), | |
6964 CodeCompleter->getCodeCompletionTUInfo(), | |
6965 CodeCompletionContext(CodeCompletionContext::CCC_ObjCInstanceMessage, | |
6966 ReceiverType, SelIdents)); | |
6967 | |
6968 Results.EnterNewScope(); | |
6969 | |
6970 // If this is a send-to-super, try to add the special "super" send | |
6971 // completion. | |
6972 if (Super) { | |
6973 if (ObjCMethodDecl *SuperMethod = | |
6974 AddSuperSendCompletion(*this, false, SelIdents, Results)) | |
6975 Results.Ignore(SuperMethod); | |
6976 } | |
6977 | |
6978 // If we're inside an Objective-C method definition, prefer its selector to | |
6979 // others. | |
6980 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) | |
6981 Results.setPreferredSelector(CurMethod->getSelector()); | |
6982 | |
6983 // Keep track of the selectors we've already added. | |
6984 VisitedSelectorSet Selectors; | |
6985 | |
6986 // Handle messages to Class. This really isn't a message to an instance | |
6987 // method, so we treat it the same way we would treat a message send to a | |
6988 // class method. | |
6989 if (ReceiverType->isObjCClassType() || | |
6990 ReceiverType->isObjCQualifiedClassType()) { | |
6991 if (ObjCMethodDecl *CurMethod = getCurMethodDecl()) { | |
6992 if (ObjCInterfaceDecl *ClassDecl = CurMethod->getClassInterface()) | |
6993 AddObjCMethods(ClassDecl, false, MK_Any, SelIdents, CurContext, | |
6994 Selectors, AtArgumentExpression, Results); | |
6995 } | |
6996 } | |
6997 // Handle messages to a qualified ID ("id<foo>"). | |
6998 else if (const ObjCObjectPointerType *QualID = | |
6999 ReceiverType->getAsObjCQualifiedIdType()) { | |
7000 // Search protocols for instance methods. | |
7001 for (auto *I : QualID->quals()) | |
7002 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors, | |
7003 AtArgumentExpression, Results); | |
7004 } | |
7005 // Handle messages to a pointer to interface type. | |
7006 else if (const ObjCObjectPointerType *IFacePtr = | |
7007 ReceiverType->getAsObjCInterfacePointerType()) { | |
7008 // Search the class, its superclasses, etc., for instance methods. | |
7009 AddObjCMethods(IFacePtr->getInterfaceDecl(), true, MK_Any, SelIdents, | |
7010 CurContext, Selectors, AtArgumentExpression, Results); | |
7011 | |
7012 // Search protocols for instance methods. | |
7013 for (auto *I : IFacePtr->quals()) | |
7014 AddObjCMethods(I, true, MK_Any, SelIdents, CurContext, Selectors, | |
7015 AtArgumentExpression, Results); | |
7016 } | |
7017 // Handle messages to "id". | |
7018 else if (ReceiverType->isObjCIdType()) { | |
7019 // We're messaging "id", so provide all instance methods we know | |
7020 // about as code-completion results. | |
7021 | |
7022 // If we have an external source, load the entire class method | |
7023 // pool from the AST file. | |
7024 if (ExternalSource) { | |
7025 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); | |
7026 I != N; ++I) { | |
7027 Selector Sel = ExternalSource->GetExternalSelector(I); | |
7028 if (Sel.isNull() || MethodPool.count(Sel)) | |
7029 continue; | |
7030 | |
7031 ReadMethodPool(Sel); | |
7032 } | |
7033 } | |
7034 | |
7035 for (GlobalMethodPool::iterator M = MethodPool.begin(), | |
7036 MEnd = MethodPool.end(); | |
7037 M != MEnd; ++M) { | |
7038 for (ObjCMethodList *MethList = &M->second.first; | |
7039 MethList && MethList->getMethod(); MethList = MethList->getNext()) { | |
7040 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) | |
7041 continue; | |
7042 | |
7043 if (!Selectors.insert(MethList->getMethod()->getSelector()).second) | |
7044 continue; | |
7045 | |
7046 Result R(MethList->getMethod(), | |
7047 Results.getBasePriority(MethList->getMethod()), nullptr); | |
7048 R.StartParameter = SelIdents.size(); | |
7049 R.AllParametersAreInformative = false; | |
7050 Results.MaybeAddResult(R, CurContext); | |
7051 } | |
7052 } | |
7053 } | |
7054 Results.ExitScope(); | |
7055 | |
7056 // If we're actually at the argument expression (rather than prior to the | |
7057 // selector), we're actually performing code completion for an expression. | |
7058 // Determine whether we have a single, best method. If so, we can | |
7059 // code-complete the expression using the corresponding parameter type as | |
7060 // our preferred type, improving completion results. | |
7061 if (AtArgumentExpression) { | |
7062 QualType PreferredType = | |
7063 getPreferredArgumentTypeForMessageSend(Results, SelIdents.size()); | |
7064 if (PreferredType.isNull()) | |
7065 CodeCompleteOrdinaryName(S, PCC_Expression); | |
7066 else | |
7067 CodeCompleteExpression(S, PreferredType); | |
7068 return; | |
7069 } | |
7070 | |
7071 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7072 Results.data(), Results.size()); | |
7073 } | |
7074 | |
7075 void Sema::CodeCompleteObjCForCollection(Scope *S, | |
7076 DeclGroupPtrTy IterationVar) { | |
7077 CodeCompleteExpressionData Data; | |
7078 Data.ObjCCollection = true; | |
7079 | |
7080 if (IterationVar.getAsOpaquePtr()) { | |
7081 DeclGroupRef DG = IterationVar.get(); | |
7082 for (DeclGroupRef::iterator I = DG.begin(), End = DG.end(); I != End; ++I) { | |
7083 if (*I) | |
7084 Data.IgnoreDecls.push_back(*I); | |
7085 } | |
7086 } | |
7087 | |
7088 CodeCompleteExpression(S, Data); | |
7089 } | |
7090 | |
7091 void Sema::CodeCompleteObjCSelector(Scope *S, | |
7092 ArrayRef<IdentifierInfo *> SelIdents) { | |
7093 // If we have an external source, load the entire class method | |
7094 // pool from the AST file. | |
7095 if (ExternalSource) { | |
7096 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; | |
7097 ++I) { | |
7098 Selector Sel = ExternalSource->GetExternalSelector(I); | |
7099 if (Sel.isNull() || MethodPool.count(Sel)) | |
7100 continue; | |
7101 | |
7102 ReadMethodPool(Sel); | |
7103 } | |
7104 } | |
7105 | |
7106 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7107 CodeCompleter->getCodeCompletionTUInfo(), | |
7108 CodeCompletionContext::CCC_SelectorName); | |
7109 Results.EnterNewScope(); | |
7110 for (GlobalMethodPool::iterator M = MethodPool.begin(), | |
7111 MEnd = MethodPool.end(); | |
7112 M != MEnd; ++M) { | |
7113 | |
7114 Selector Sel = M->first; | |
7115 if (!isAcceptableObjCSelector(Sel, MK_Any, SelIdents)) | |
7116 continue; | |
7117 | |
7118 CodeCompletionBuilder Builder(Results.getAllocator(), | |
7119 Results.getCodeCompletionTUInfo()); | |
7120 if (Sel.isUnarySelector()) { | |
7121 Builder.AddTypedTextChunk( | |
7122 Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); | |
7123 Results.AddResult(Builder.TakeString()); | |
7124 continue; | |
7125 } | |
7126 | |
7127 std::string Accumulator; | |
7128 for (unsigned I = 0, N = Sel.getNumArgs(); I != N; ++I) { | |
7129 if (I == SelIdents.size()) { | |
7130 if (!Accumulator.empty()) { | |
7131 Builder.AddInformativeChunk( | |
7132 Builder.getAllocator().CopyString(Accumulator)); | |
7133 Accumulator.clear(); | |
7134 } | |
7135 } | |
7136 | |
7137 Accumulator += Sel.getNameForSlot(I); | |
7138 Accumulator += ':'; | |
7139 } | |
7140 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString(Accumulator)); | |
7141 Results.AddResult(Builder.TakeString()); | |
7142 } | |
7143 Results.ExitScope(); | |
7144 | |
7145 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7146 Results.data(), Results.size()); | |
7147 } | |
7148 | |
7149 /// Add all of the protocol declarations that we find in the given | |
7150 /// (translation unit) context. | |
7151 static void AddProtocolResults(DeclContext *Ctx, DeclContext *CurContext, | |
7152 bool OnlyForwardDeclarations, | |
7153 ResultBuilder &Results) { | |
7154 typedef CodeCompletionResult Result; | |
7155 | |
7156 for (const auto *D : Ctx->decls()) { | |
7157 // Record any protocols we find. | |
7158 if (const auto *Proto = dyn_cast<ObjCProtocolDecl>(D)) | |
7159 if (!OnlyForwardDeclarations || !Proto->hasDefinition()) | |
7160 Results.AddResult( | |
7161 Result(Proto, Results.getBasePriority(Proto), nullptr), CurContext, | |
7162 nullptr, false); | |
7163 } | |
7164 } | |
7165 | |
7166 void Sema::CodeCompleteObjCProtocolReferences( | |
7167 ArrayRef<IdentifierLocPair> Protocols) { | |
7168 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7169 CodeCompleter->getCodeCompletionTUInfo(), | |
7170 CodeCompletionContext::CCC_ObjCProtocolName); | |
7171 | |
7172 if (CodeCompleter->includeGlobals()) { | |
7173 Results.EnterNewScope(); | |
7174 | |
7175 // Tell the result set to ignore all of the protocols we have | |
7176 // already seen. | |
7177 // FIXME: This doesn't work when caching code-completion results. | |
7178 for (const IdentifierLocPair &Pair : Protocols) | |
7179 if (ObjCProtocolDecl *Protocol = LookupProtocol(Pair.first, Pair.second)) | |
7180 Results.Ignore(Protocol); | |
7181 | |
7182 // Add all protocols. | |
7183 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, false, | |
7184 Results); | |
7185 | |
7186 Results.ExitScope(); | |
7187 } | |
7188 | |
7189 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7190 Results.data(), Results.size()); | |
7191 } | |
7192 | |
7193 void Sema::CodeCompleteObjCProtocolDecl(Scope *) { | |
7194 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7195 CodeCompleter->getCodeCompletionTUInfo(), | |
7196 CodeCompletionContext::CCC_ObjCProtocolName); | |
7197 | |
7198 if (CodeCompleter->includeGlobals()) { | |
7199 Results.EnterNewScope(); | |
7200 | |
7201 // Add all protocols. | |
7202 AddProtocolResults(Context.getTranslationUnitDecl(), CurContext, true, | |
7203 Results); | |
7204 | |
7205 Results.ExitScope(); | |
7206 } | |
7207 | |
7208 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7209 Results.data(), Results.size()); | |
7210 } | |
7211 | |
7212 /// Add all of the Objective-C interface declarations that we find in | |
7213 /// the given (translation unit) context. | |
7214 static void AddInterfaceResults(DeclContext *Ctx, DeclContext *CurContext, | |
7215 bool OnlyForwardDeclarations, | |
7216 bool OnlyUnimplemented, | |
7217 ResultBuilder &Results) { | |
7218 typedef CodeCompletionResult Result; | |
7219 | |
7220 for (const auto *D : Ctx->decls()) { | |
7221 // Record any interfaces we find. | |
7222 if (const auto *Class = dyn_cast<ObjCInterfaceDecl>(D)) | |
7223 if ((!OnlyForwardDeclarations || !Class->hasDefinition()) && | |
7224 (!OnlyUnimplemented || !Class->getImplementation())) | |
7225 Results.AddResult( | |
7226 Result(Class, Results.getBasePriority(Class), nullptr), CurContext, | |
7227 nullptr, false); | |
7228 } | |
7229 } | |
7230 | |
7231 void Sema::CodeCompleteObjCInterfaceDecl(Scope *S) { | |
7232 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7233 CodeCompleter->getCodeCompletionTUInfo(), | |
7234 CodeCompletionContext::CCC_ObjCInterfaceName); | |
7235 Results.EnterNewScope(); | |
7236 | |
7237 if (CodeCompleter->includeGlobals()) { | |
7238 // Add all classes. | |
7239 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, | |
7240 false, Results); | |
7241 } | |
7242 | |
7243 Results.ExitScope(); | |
7244 | |
7245 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7246 Results.data(), Results.size()); | |
7247 } | |
7248 | |
7249 void Sema::CodeCompleteObjCSuperclass(Scope *S, IdentifierInfo *ClassName, | |
7250 SourceLocation ClassNameLoc) { | |
7251 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7252 CodeCompleter->getCodeCompletionTUInfo(), | |
7253 CodeCompletionContext::CCC_ObjCInterfaceName); | |
7254 Results.EnterNewScope(); | |
7255 | |
7256 // Make sure that we ignore the class we're currently defining. | |
7257 NamedDecl *CurClass = | |
7258 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); | |
7259 if (CurClass && isa<ObjCInterfaceDecl>(CurClass)) | |
7260 Results.Ignore(CurClass); | |
7261 | |
7262 if (CodeCompleter->includeGlobals()) { | |
7263 // Add all classes. | |
7264 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, | |
7265 false, Results); | |
7266 } | |
7267 | |
7268 Results.ExitScope(); | |
7269 | |
7270 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7271 Results.data(), Results.size()); | |
7272 } | |
7273 | |
7274 void Sema::CodeCompleteObjCImplementationDecl(Scope *S) { | |
7275 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7276 CodeCompleter->getCodeCompletionTUInfo(), | |
7277 CodeCompletionContext::CCC_ObjCImplementation); | |
7278 Results.EnterNewScope(); | |
7279 | |
7280 if (CodeCompleter->includeGlobals()) { | |
7281 // Add all unimplemented classes. | |
7282 AddInterfaceResults(Context.getTranslationUnitDecl(), CurContext, false, | |
7283 true, Results); | |
7284 } | |
7285 | |
7286 Results.ExitScope(); | |
7287 | |
7288 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7289 Results.data(), Results.size()); | |
7290 } | |
7291 | |
7292 void Sema::CodeCompleteObjCInterfaceCategory(Scope *S, | |
7293 IdentifierInfo *ClassName, | |
7294 SourceLocation ClassNameLoc) { | |
7295 typedef CodeCompletionResult Result; | |
7296 | |
7297 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7298 CodeCompleter->getCodeCompletionTUInfo(), | |
7299 CodeCompletionContext::CCC_ObjCCategoryName); | |
7300 | |
7301 // Ignore any categories we find that have already been implemented by this | |
7302 // interface. | |
7303 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; | |
7304 NamedDecl *CurClass = | |
7305 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); | |
7306 if (ObjCInterfaceDecl *Class = | |
7307 dyn_cast_or_null<ObjCInterfaceDecl>(CurClass)) { | |
7308 for (const auto *Cat : Class->visible_categories()) | |
7309 CategoryNames.insert(Cat->getIdentifier()); | |
7310 } | |
7311 | |
7312 // Add all of the categories we know about. | |
7313 Results.EnterNewScope(); | |
7314 TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); | |
7315 for (const auto *D : TU->decls()) | |
7316 if (const auto *Category = dyn_cast<ObjCCategoryDecl>(D)) | |
7317 if (CategoryNames.insert(Category->getIdentifier()).second) | |
7318 Results.AddResult( | |
7319 Result(Category, Results.getBasePriority(Category), nullptr), | |
7320 CurContext, nullptr, false); | |
7321 Results.ExitScope(); | |
7322 | |
7323 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7324 Results.data(), Results.size()); | |
7325 } | |
7326 | |
7327 void Sema::CodeCompleteObjCImplementationCategory(Scope *S, | |
7328 IdentifierInfo *ClassName, | |
7329 SourceLocation ClassNameLoc) { | |
7330 typedef CodeCompletionResult Result; | |
7331 | |
7332 // Find the corresponding interface. If we couldn't find the interface, the | |
7333 // program itself is ill-formed. However, we'll try to be helpful still by | |
7334 // providing the list of all of the categories we know about. | |
7335 NamedDecl *CurClass = | |
7336 LookupSingleName(TUScope, ClassName, ClassNameLoc, LookupOrdinaryName); | |
7337 ObjCInterfaceDecl *Class = dyn_cast_or_null<ObjCInterfaceDecl>(CurClass); | |
7338 if (!Class) | |
7339 return CodeCompleteObjCInterfaceCategory(S, ClassName, ClassNameLoc); | |
7340 | |
7341 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7342 CodeCompleter->getCodeCompletionTUInfo(), | |
7343 CodeCompletionContext::CCC_ObjCCategoryName); | |
7344 | |
7345 // Add all of the categories that have have corresponding interface | |
7346 // declarations in this class and any of its superclasses, except for | |
7347 // already-implemented categories in the class itself. | |
7348 llvm::SmallPtrSet<IdentifierInfo *, 16> CategoryNames; | |
7349 Results.EnterNewScope(); | |
7350 bool IgnoreImplemented = true; | |
7351 while (Class) { | |
7352 for (const auto *Cat : Class->visible_categories()) { | |
7353 if ((!IgnoreImplemented || !Cat->getImplementation()) && | |
7354 CategoryNames.insert(Cat->getIdentifier()).second) | |
7355 Results.AddResult(Result(Cat, Results.getBasePriority(Cat), nullptr), | |
7356 CurContext, nullptr, false); | |
7357 } | |
7358 | |
7359 Class = Class->getSuperClass(); | |
7360 IgnoreImplemented = false; | |
7361 } | |
7362 Results.ExitScope(); | |
7363 | |
7364 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7365 Results.data(), Results.size()); | |
7366 } | |
7367 | |
7368 void Sema::CodeCompleteObjCPropertyDefinition(Scope *S) { | |
7369 CodeCompletionContext CCContext(CodeCompletionContext::CCC_Other); | |
7370 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7371 CodeCompleter->getCodeCompletionTUInfo(), CCContext); | |
7372 | |
7373 // Figure out where this @synthesize lives. | |
7374 ObjCContainerDecl *Container = | |
7375 dyn_cast_or_null<ObjCContainerDecl>(CurContext); | |
7376 if (!Container || (!isa<ObjCImplementationDecl>(Container) && | |
7377 !isa<ObjCCategoryImplDecl>(Container))) | |
7378 return; | |
7379 | |
7380 // Ignore any properties that have already been implemented. | |
7381 Container = getContainerDef(Container); | |
7382 for (const auto *D : Container->decls()) | |
7383 if (const auto *PropertyImpl = dyn_cast<ObjCPropertyImplDecl>(D)) | |
7384 Results.Ignore(PropertyImpl->getPropertyDecl()); | |
7385 | |
7386 // Add any properties that we find. | |
7387 AddedPropertiesSet AddedProperties; | |
7388 Results.EnterNewScope(); | |
7389 if (ObjCImplementationDecl *ClassImpl = | |
7390 dyn_cast<ObjCImplementationDecl>(Container)) | |
7391 AddObjCProperties(CCContext, ClassImpl->getClassInterface(), false, | |
7392 /*AllowNullaryMethods=*/false, CurContext, | |
7393 AddedProperties, Results); | |
7394 else | |
7395 AddObjCProperties(CCContext, | |
7396 cast<ObjCCategoryImplDecl>(Container)->getCategoryDecl(), | |
7397 false, /*AllowNullaryMethods=*/false, CurContext, | |
7398 AddedProperties, Results); | |
7399 Results.ExitScope(); | |
7400 | |
7401 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7402 Results.data(), Results.size()); | |
7403 } | |
7404 | |
7405 void Sema::CodeCompleteObjCPropertySynthesizeIvar( | |
7406 Scope *S, IdentifierInfo *PropertyName) { | |
7407 typedef CodeCompletionResult Result; | |
7408 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
7409 CodeCompleter->getCodeCompletionTUInfo(), | |
7410 CodeCompletionContext::CCC_Other); | |
7411 | |
7412 // Figure out where this @synthesize lives. | |
7413 ObjCContainerDecl *Container = | |
7414 dyn_cast_or_null<ObjCContainerDecl>(CurContext); | |
7415 if (!Container || (!isa<ObjCImplementationDecl>(Container) && | |
7416 !isa<ObjCCategoryImplDecl>(Container))) | |
7417 return; | |
7418 | |
7419 // Figure out which interface we're looking into. | |
7420 ObjCInterfaceDecl *Class = nullptr; | |
7421 if (ObjCImplementationDecl *ClassImpl = | |
7422 dyn_cast<ObjCImplementationDecl>(Container)) | |
7423 Class = ClassImpl->getClassInterface(); | |
7424 else | |
7425 Class = cast<ObjCCategoryImplDecl>(Container) | |
7426 ->getCategoryDecl() | |
7427 ->getClassInterface(); | |
7428 | |
7429 // Determine the type of the property we're synthesizing. | |
7430 QualType PropertyType = Context.getObjCIdType(); | |
7431 if (Class) { | |
7432 if (ObjCPropertyDecl *Property = Class->FindPropertyDeclaration( | |
7433 PropertyName, ObjCPropertyQueryKind::OBJC_PR_query_instance)) { | |
7434 PropertyType = | |
7435 Property->getType().getNonReferenceType().getUnqualifiedType(); | |
7436 | |
7437 // Give preference to ivars | |
7438 Results.setPreferredType(PropertyType); | |
7439 } | |
7440 } | |
7441 | |
7442 // Add all of the instance variables in this class and its superclasses. | |
7443 Results.EnterNewScope(); | |
7444 bool SawSimilarlyNamedIvar = false; | |
7445 std::string NameWithPrefix; | |
7446 NameWithPrefix += '_'; | |
7447 NameWithPrefix += PropertyName->getName(); | |
7448 std::string NameWithSuffix = PropertyName->getName().str(); | |
7449 NameWithSuffix += '_'; | |
7450 for (; Class; Class = Class->getSuperClass()) { | |
7451 for (ObjCIvarDecl *Ivar = Class->all_declared_ivar_begin(); Ivar; | |
7452 Ivar = Ivar->getNextIvar()) { | |
7453 Results.AddResult(Result(Ivar, Results.getBasePriority(Ivar), nullptr), | |
7454 CurContext, nullptr, false); | |
7455 | |
7456 // Determine whether we've seen an ivar with a name similar to the | |
7457 // property. | |
7458 if ((PropertyName == Ivar->getIdentifier() || | |
7459 NameWithPrefix == Ivar->getName() || | |
7460 NameWithSuffix == Ivar->getName())) { | |
7461 SawSimilarlyNamedIvar = true; | |
7462 | |
7463 // Reduce the priority of this result by one, to give it a slight | |
7464 // advantage over other results whose names don't match so closely. | |
7465 if (Results.size() && | |
7466 Results.data()[Results.size() - 1].Kind == | |
7467 CodeCompletionResult::RK_Declaration && | |
7468 Results.data()[Results.size() - 1].Declaration == Ivar) | |
7469 Results.data()[Results.size() - 1].Priority--; | |
7470 } | |
7471 } | |
7472 } | |
7473 | |
7474 if (!SawSimilarlyNamedIvar) { | |
7475 // Create ivar result _propName, that the user can use to synthesize | |
7476 // an ivar of the appropriate type. | |
7477 unsigned Priority = CCP_MemberDeclaration + 1; | |
7478 typedef CodeCompletionResult Result; | |
7479 CodeCompletionAllocator &Allocator = Results.getAllocator(); | |
7480 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo(), | |
7481 Priority, CXAvailability_Available); | |
7482 | |
7483 PrintingPolicy Policy = getCompletionPrintingPolicy(*this); | |
7484 Builder.AddResultTypeChunk( | |
7485 GetCompletionTypeString(PropertyType, Context, Policy, Allocator)); | |
7486 Builder.AddTypedTextChunk(Allocator.CopyString(NameWithPrefix)); | |
7487 Results.AddResult( | |
7488 Result(Builder.TakeString(), Priority, CXCursor_ObjCIvarDecl)); | |
7489 } | |
7490 | |
7491 Results.ExitScope(); | |
7492 | |
7493 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
7494 Results.data(), Results.size()); | |
7495 } | |
7496 | |
7497 // Mapping from selectors to the methods that implement that selector, along | |
7498 // with the "in original class" flag. | |
7499 typedef llvm::DenseMap<Selector, | |
7500 llvm::PointerIntPair<ObjCMethodDecl *, 1, bool>> | |
7501 KnownMethodsMap; | |
7502 | |
7503 /// Find all of the methods that reside in the given container | |
7504 /// (and its superclasses, protocols, etc.) that meet the given | |
7505 /// criteria. Insert those methods into the map of known methods, | |
7506 /// indexed by selector so they can be easily found. | |
7507 static void FindImplementableMethods(ASTContext &Context, | |
7508 ObjCContainerDecl *Container, | |
7509 Optional<bool> WantInstanceMethods, | |
7510 QualType ReturnType, | |
7511 KnownMethodsMap &KnownMethods, | |
7512 bool InOriginalClass = true) { | |
7513 if (ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(Container)) { | |
7514 // Make sure we have a definition; that's what we'll walk. | |
7515 if (!IFace->hasDefinition()) | |
7516 return; | |
7517 | |
7518 IFace = IFace->getDefinition(); | |
7519 Container = IFace; | |
7520 | |
7521 const ObjCList<ObjCProtocolDecl> &Protocols = | |
7522 IFace->getReferencedProtocols(); | |
7523 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), | |
7524 E = Protocols.end(); | |
7525 I != E; ++I) | |
7526 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, | |
7527 KnownMethods, InOriginalClass); | |
7528 | |
7529 // Add methods from any class extensions and categories. | |
7530 for (auto *Cat : IFace->visible_categories()) { | |
7531 FindImplementableMethods(Context, Cat, WantInstanceMethods, ReturnType, | |
7532 KnownMethods, false); | |
7533 } | |
7534 | |
7535 // Visit the superclass. | |
7536 if (IFace->getSuperClass()) | |
7537 FindImplementableMethods(Context, IFace->getSuperClass(), | |
7538 WantInstanceMethods, ReturnType, KnownMethods, | |
7539 false); | |
7540 } | |
7541 | |
7542 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { | |
7543 // Recurse into protocols. | |
7544 const ObjCList<ObjCProtocolDecl> &Protocols = | |
7545 Category->getReferencedProtocols(); | |
7546 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), | |
7547 E = Protocols.end(); | |
7548 I != E; ++I) | |
7549 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, | |
7550 KnownMethods, InOriginalClass); | |
7551 | |
7552 // If this category is the original class, jump to the interface. | |
7553 if (InOriginalClass && Category->getClassInterface()) | |
7554 FindImplementableMethods(Context, Category->getClassInterface(), | |
7555 WantInstanceMethods, ReturnType, KnownMethods, | |
7556 false); | |
7557 } | |
7558 | |
7559 if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { | |
7560 // Make sure we have a definition; that's what we'll walk. | |
7561 if (!Protocol->hasDefinition()) | |
7562 return; | |
7563 Protocol = Protocol->getDefinition(); | |
7564 Container = Protocol; | |
7565 | |
7566 // Recurse into protocols. | |
7567 const ObjCList<ObjCProtocolDecl> &Protocols = | |
7568 Protocol->getReferencedProtocols(); | |
7569 for (ObjCList<ObjCProtocolDecl>::iterator I = Protocols.begin(), | |
7570 E = Protocols.end(); | |
7571 I != E; ++I) | |
7572 FindImplementableMethods(Context, *I, WantInstanceMethods, ReturnType, | |
7573 KnownMethods, false); | |
7574 } | |
7575 | |
7576 // Add methods in this container. This operation occurs last because | |
7577 // we want the methods from this container to override any methods | |
7578 // we've previously seen with the same selector. | |
7579 for (auto *M : Container->methods()) { | |
7580 if (!WantInstanceMethods || M->isInstanceMethod() == *WantInstanceMethods) { | |
7581 if (!ReturnType.isNull() && | |
7582 !Context.hasSameUnqualifiedType(ReturnType, M->getReturnType())) | |
7583 continue; | |
7584 | |
7585 KnownMethods[M->getSelector()] = | |
7586 KnownMethodsMap::mapped_type(M, InOriginalClass); | |
7587 } | |
7588 } | |
7589 } | |
7590 | |
7591 /// Add the parenthesized return or parameter type chunk to a code | |
7592 /// completion string. | |
7593 static void AddObjCPassingTypeChunk(QualType Type, unsigned ObjCDeclQuals, | |
7594 ASTContext &Context, | |
7595 const PrintingPolicy &Policy, | |
7596 CodeCompletionBuilder &Builder) { | |
7597 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7598 std::string Quals = formatObjCParamQualifiers(ObjCDeclQuals, Type); | |
7599 if (!Quals.empty()) | |
7600 Builder.AddTextChunk(Builder.getAllocator().CopyString(Quals)); | |
7601 Builder.AddTextChunk( | |
7602 GetCompletionTypeString(Type, Context, Policy, Builder.getAllocator())); | |
7603 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7604 } | |
7605 | |
7606 /// Determine whether the given class is or inherits from a class by | |
7607 /// the given name. | |
7608 static bool InheritsFromClassNamed(ObjCInterfaceDecl *Class, StringRef Name) { | |
7609 if (!Class) | |
7610 return false; | |
7611 | |
7612 if (Class->getIdentifier() && Class->getIdentifier()->getName() == Name) | |
7613 return true; | |
7614 | |
7615 return InheritsFromClassNamed(Class->getSuperClass(), Name); | |
7616 } | |
7617 | |
7618 /// Add code completions for Objective-C Key-Value Coding (KVC) and | |
7619 /// Key-Value Observing (KVO). | |
7620 static void AddObjCKeyValueCompletions(ObjCPropertyDecl *Property, | |
7621 bool IsInstanceMethod, | |
7622 QualType ReturnType, ASTContext &Context, | |
7623 VisitedSelectorSet &KnownSelectors, | |
7624 ResultBuilder &Results) { | |
7625 IdentifierInfo *PropName = Property->getIdentifier(); | |
7626 if (!PropName || PropName->getLength() == 0) | |
7627 return; | |
7628 | |
7629 PrintingPolicy Policy = getCompletionPrintingPolicy(Results.getSema()); | |
7630 | |
7631 // Builder that will create each code completion. | |
7632 typedef CodeCompletionResult Result; | |
7633 CodeCompletionAllocator &Allocator = Results.getAllocator(); | |
7634 CodeCompletionBuilder Builder(Allocator, Results.getCodeCompletionTUInfo()); | |
7635 | |
7636 // The selector table. | |
7637 SelectorTable &Selectors = Context.Selectors; | |
7638 | |
7639 // The property name, copied into the code completion allocation region | |
7640 // on demand. | |
7641 struct KeyHolder { | |
7642 CodeCompletionAllocator &Allocator; | |
7643 StringRef Key; | |
7644 const char *CopiedKey; | |
7645 | |
7646 KeyHolder(CodeCompletionAllocator &Allocator, StringRef Key) | |
7647 : Allocator(Allocator), Key(Key), CopiedKey(nullptr) {} | |
7648 | |
7649 operator const char *() { | |
7650 if (CopiedKey) | |
7651 return CopiedKey; | |
7652 | |
7653 return CopiedKey = Allocator.CopyString(Key); | |
7654 } | |
7655 } Key(Allocator, PropName->getName()); | |
7656 | |
7657 // The uppercased name of the property name. | |
7658 std::string UpperKey = std::string(PropName->getName()); | |
7659 if (!UpperKey.empty()) | |
7660 UpperKey[0] = toUppercase(UpperKey[0]); | |
7661 | |
7662 bool ReturnTypeMatchesProperty = | |
7663 ReturnType.isNull() || | |
7664 Context.hasSameUnqualifiedType(ReturnType.getNonReferenceType(), | |
7665 Property->getType()); | |
7666 bool ReturnTypeMatchesVoid = ReturnType.isNull() || ReturnType->isVoidType(); | |
7667 | |
7668 // Add the normal accessor -(type)key. | |
7669 if (IsInstanceMethod && | |
7670 KnownSelectors.insert(Selectors.getNullarySelector(PropName)).second && | |
7671 ReturnTypeMatchesProperty && !Property->getGetterMethodDecl()) { | |
7672 if (ReturnType.isNull()) | |
7673 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy, | |
7674 Builder); | |
7675 | |
7676 Builder.AddTypedTextChunk(Key); | |
7677 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, | |
7678 CXCursor_ObjCInstanceMethodDecl)); | |
7679 } | |
7680 | |
7681 // If we have an integral or boolean property (or the user has provided | |
7682 // an integral or boolean return type), add the accessor -(type)isKey. | |
7683 if (IsInstanceMethod && | |
7684 ((!ReturnType.isNull() && | |
7685 (ReturnType->isIntegerType() || ReturnType->isBooleanType())) || | |
7686 (ReturnType.isNull() && (Property->getType()->isIntegerType() || | |
7687 Property->getType()->isBooleanType())))) { | |
7688 std::string SelectorName = (Twine("is") + UpperKey).str(); | |
7689 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
7690 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) | |
7691 .second) { | |
7692 if (ReturnType.isNull()) { | |
7693 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7694 Builder.AddTextChunk("BOOL"); | |
7695 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7696 } | |
7697 | |
7698 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName())); | |
7699 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, | |
7700 CXCursor_ObjCInstanceMethodDecl)); | |
7701 } | |
7702 } | |
7703 | |
7704 // Add the normal mutator. | |
7705 if (IsInstanceMethod && ReturnTypeMatchesVoid && | |
7706 !Property->getSetterMethodDecl()) { | |
7707 std::string SelectorName = (Twine("set") + UpperKey).str(); | |
7708 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
7709 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
7710 if (ReturnType.isNull()) { | |
7711 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7712 Builder.AddTextChunk("void"); | |
7713 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7714 } | |
7715 | |
7716 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName())); | |
7717 Builder.AddTypedTextChunk(":"); | |
7718 AddObjCPassingTypeChunk(Property->getType(), /*Quals=*/0, Context, Policy, | |
7719 Builder); | |
7720 Builder.AddTextChunk(Key); | |
7721 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, | |
7722 CXCursor_ObjCInstanceMethodDecl)); | |
7723 } | |
7724 } | |
7725 | |
7726 // Indexed and unordered accessors | |
7727 unsigned IndexedGetterPriority = CCP_CodePattern; | |
7728 unsigned IndexedSetterPriority = CCP_CodePattern; | |
7729 unsigned UnorderedGetterPriority = CCP_CodePattern; | |
7730 unsigned UnorderedSetterPriority = CCP_CodePattern; | |
7731 if (const auto *ObjCPointer = | |
7732 Property->getType()->getAs<ObjCObjectPointerType>()) { | |
7733 if (ObjCInterfaceDecl *IFace = ObjCPointer->getInterfaceDecl()) { | |
7734 // If this interface type is not provably derived from a known | |
7735 // collection, penalize the corresponding completions. | |
7736 if (!InheritsFromClassNamed(IFace, "NSMutableArray")) { | |
7737 IndexedSetterPriority += CCD_ProbablyNotObjCCollection; | |
7738 if (!InheritsFromClassNamed(IFace, "NSArray")) | |
7739 IndexedGetterPriority += CCD_ProbablyNotObjCCollection; | |
7740 } | |
7741 | |
7742 if (!InheritsFromClassNamed(IFace, "NSMutableSet")) { | |
7743 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; | |
7744 if (!InheritsFromClassNamed(IFace, "NSSet")) | |
7745 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; | |
7746 } | |
7747 } | |
7748 } else { | |
7749 IndexedGetterPriority += CCD_ProbablyNotObjCCollection; | |
7750 IndexedSetterPriority += CCD_ProbablyNotObjCCollection; | |
7751 UnorderedGetterPriority += CCD_ProbablyNotObjCCollection; | |
7752 UnorderedSetterPriority += CCD_ProbablyNotObjCCollection; | |
7753 } | |
7754 | |
7755 // Add -(NSUInteger)countOf<key> | |
7756 if (IsInstanceMethod && | |
7757 (ReturnType.isNull() || ReturnType->isIntegerType())) { | |
7758 std::string SelectorName = (Twine("countOf") + UpperKey).str(); | |
7759 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
7760 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) | |
7761 .second) { | |
7762 if (ReturnType.isNull()) { | |
7763 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7764 Builder.AddTextChunk("NSUInteger"); | |
7765 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7766 } | |
7767 | |
7768 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorId->getName())); | |
7769 Results.AddResult( | |
7770 Result(Builder.TakeString(), | |
7771 std::min(IndexedGetterPriority, UnorderedGetterPriority), | |
7772 CXCursor_ObjCInstanceMethodDecl)); | |
7773 } | |
7774 } | |
7775 | |
7776 // Indexed getters | |
7777 // Add -(id)objectInKeyAtIndex:(NSUInteger)index | |
7778 if (IsInstanceMethod && | |
7779 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { | |
7780 std::string SelectorName = (Twine("objectIn") + UpperKey + "AtIndex").str(); | |
7781 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
7782 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
7783 if (ReturnType.isNull()) { | |
7784 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7785 Builder.AddTextChunk("id"); | |
7786 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7787 } | |
7788 | |
7789 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
7790 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7791 Builder.AddTextChunk("NSUInteger"); | |
7792 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7793 Builder.AddTextChunk("index"); | |
7794 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, | |
7795 CXCursor_ObjCInstanceMethodDecl)); | |
7796 } | |
7797 } | |
7798 | |
7799 // Add -(NSArray *)keyAtIndexes:(NSIndexSet *)indexes | |
7800 if (IsInstanceMethod && | |
7801 (ReturnType.isNull() || | |
7802 (ReturnType->isObjCObjectPointerType() && | |
7803 ReturnType->castAs<ObjCObjectPointerType>()->getInterfaceDecl() && | |
7804 ReturnType->castAs<ObjCObjectPointerType>() | |
7805 ->getInterfaceDecl() | |
7806 ->getName() == "NSArray"))) { | |
7807 std::string SelectorName = (Twine(Property->getName()) + "AtIndexes").str(); | |
7808 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
7809 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
7810 if (ReturnType.isNull()) { | |
7811 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7812 Builder.AddTextChunk("NSArray *"); | |
7813 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7814 } | |
7815 | |
7816 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
7817 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7818 Builder.AddTextChunk("NSIndexSet *"); | |
7819 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7820 Builder.AddTextChunk("indexes"); | |
7821 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, | |
7822 CXCursor_ObjCInstanceMethodDecl)); | |
7823 } | |
7824 } | |
7825 | |
7826 // Add -(void)getKey:(type **)buffer range:(NSRange)inRange | |
7827 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
7828 std::string SelectorName = (Twine("get") + UpperKey).str(); | |
7829 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName), | |
7830 &Context.Idents.get("range")}; | |
7831 | |
7832 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { | |
7833 if (ReturnType.isNull()) { | |
7834 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7835 Builder.AddTextChunk("void"); | |
7836 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7837 } | |
7838 | |
7839 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
7840 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7841 Builder.AddPlaceholderChunk("object-type"); | |
7842 Builder.AddTextChunk(" **"); | |
7843 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7844 Builder.AddTextChunk("buffer"); | |
7845 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
7846 Builder.AddTypedTextChunk("range:"); | |
7847 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7848 Builder.AddTextChunk("NSRange"); | |
7849 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7850 Builder.AddTextChunk("inRange"); | |
7851 Results.AddResult(Result(Builder.TakeString(), IndexedGetterPriority, | |
7852 CXCursor_ObjCInstanceMethodDecl)); | |
7853 } | |
7854 } | |
7855 | |
7856 // Mutable indexed accessors | |
7857 | |
7858 // - (void)insertObject:(type *)object inKeyAtIndex:(NSUInteger)index | |
7859 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
7860 std::string SelectorName = (Twine("in") + UpperKey + "AtIndex").str(); | |
7861 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get("insertObject"), | |
7862 &Context.Idents.get(SelectorName)}; | |
7863 | |
7864 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { | |
7865 if (ReturnType.isNull()) { | |
7866 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7867 Builder.AddTextChunk("void"); | |
7868 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7869 } | |
7870 | |
7871 Builder.AddTypedTextChunk("insertObject:"); | |
7872 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7873 Builder.AddPlaceholderChunk("object-type"); | |
7874 Builder.AddTextChunk(" *"); | |
7875 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7876 Builder.AddTextChunk("object"); | |
7877 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
7878 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
7879 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7880 Builder.AddPlaceholderChunk("NSUInteger"); | |
7881 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7882 Builder.AddTextChunk("index"); | |
7883 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, | |
7884 CXCursor_ObjCInstanceMethodDecl)); | |
7885 } | |
7886 } | |
7887 | |
7888 // - (void)insertKey:(NSArray *)array atIndexes:(NSIndexSet *)indexes | |
7889 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
7890 std::string SelectorName = (Twine("insert") + UpperKey).str(); | |
7891 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName), | |
7892 &Context.Idents.get("atIndexes")}; | |
7893 | |
7894 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { | |
7895 if (ReturnType.isNull()) { | |
7896 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7897 Builder.AddTextChunk("void"); | |
7898 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7899 } | |
7900 | |
7901 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
7902 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7903 Builder.AddTextChunk("NSArray *"); | |
7904 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7905 Builder.AddTextChunk("array"); | |
7906 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
7907 Builder.AddTypedTextChunk("atIndexes:"); | |
7908 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7909 Builder.AddPlaceholderChunk("NSIndexSet *"); | |
7910 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7911 Builder.AddTextChunk("indexes"); | |
7912 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, | |
7913 CXCursor_ObjCInstanceMethodDecl)); | |
7914 } | |
7915 } | |
7916 | |
7917 // -(void)removeObjectFromKeyAtIndex:(NSUInteger)index | |
7918 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
7919 std::string SelectorName = | |
7920 (Twine("removeObjectFrom") + UpperKey + "AtIndex").str(); | |
7921 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
7922 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
7923 if (ReturnType.isNull()) { | |
7924 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7925 Builder.AddTextChunk("void"); | |
7926 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7927 } | |
7928 | |
7929 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
7930 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7931 Builder.AddTextChunk("NSUInteger"); | |
7932 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7933 Builder.AddTextChunk("index"); | |
7934 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, | |
7935 CXCursor_ObjCInstanceMethodDecl)); | |
7936 } | |
7937 } | |
7938 | |
7939 // -(void)removeKeyAtIndexes:(NSIndexSet *)indexes | |
7940 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
7941 std::string SelectorName = (Twine("remove") + UpperKey + "AtIndexes").str(); | |
7942 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
7943 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
7944 if (ReturnType.isNull()) { | |
7945 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7946 Builder.AddTextChunk("void"); | |
7947 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7948 } | |
7949 | |
7950 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
7951 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7952 Builder.AddTextChunk("NSIndexSet *"); | |
7953 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7954 Builder.AddTextChunk("indexes"); | |
7955 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, | |
7956 CXCursor_ObjCInstanceMethodDecl)); | |
7957 } | |
7958 } | |
7959 | |
7960 // - (void)replaceObjectInKeyAtIndex:(NSUInteger)index withObject:(id)object | |
7961 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
7962 std::string SelectorName = | |
7963 (Twine("replaceObjectIn") + UpperKey + "AtIndex").str(); | |
7964 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName), | |
7965 &Context.Idents.get("withObject")}; | |
7966 | |
7967 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { | |
7968 if (ReturnType.isNull()) { | |
7969 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7970 Builder.AddTextChunk("void"); | |
7971 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7972 } | |
7973 | |
7974 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
7975 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7976 Builder.AddPlaceholderChunk("NSUInteger"); | |
7977 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7978 Builder.AddTextChunk("index"); | |
7979 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
7980 Builder.AddTypedTextChunk("withObject:"); | |
7981 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
7982 Builder.AddTextChunk("id"); | |
7983 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
7984 Builder.AddTextChunk("object"); | |
7985 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, | |
7986 CXCursor_ObjCInstanceMethodDecl)); | |
7987 } | |
7988 } | |
7989 | |
7990 // - (void)replaceKeyAtIndexes:(NSIndexSet *)indexes withKey:(NSArray *)array | |
7991 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
7992 std::string SelectorName1 = | |
7993 (Twine("replace") + UpperKey + "AtIndexes").str(); | |
7994 std::string SelectorName2 = (Twine("with") + UpperKey).str(); | |
7995 IdentifierInfo *SelectorIds[2] = {&Context.Idents.get(SelectorName1), | |
7996 &Context.Idents.get(SelectorName2)}; | |
7997 | |
7998 if (KnownSelectors.insert(Selectors.getSelector(2, SelectorIds)).second) { | |
7999 if (ReturnType.isNull()) { | |
8000 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8001 Builder.AddTextChunk("void"); | |
8002 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8003 } | |
8004 | |
8005 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName1 + ":")); | |
8006 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8007 Builder.AddPlaceholderChunk("NSIndexSet *"); | |
8008 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8009 Builder.AddTextChunk("indexes"); | |
8010 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8011 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName2 + ":")); | |
8012 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8013 Builder.AddTextChunk("NSArray *"); | |
8014 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8015 Builder.AddTextChunk("array"); | |
8016 Results.AddResult(Result(Builder.TakeString(), IndexedSetterPriority, | |
8017 CXCursor_ObjCInstanceMethodDecl)); | |
8018 } | |
8019 } | |
8020 | |
8021 // Unordered getters | |
8022 // - (NSEnumerator *)enumeratorOfKey | |
8023 if (IsInstanceMethod && | |
8024 (ReturnType.isNull() || | |
8025 (ReturnType->isObjCObjectPointerType() && | |
8026 ReturnType->getAs<ObjCObjectPointerType>()->getInterfaceDecl() && | |
8027 ReturnType->getAs<ObjCObjectPointerType>() | |
8028 ->getInterfaceDecl() | |
8029 ->getName() == "NSEnumerator"))) { | |
8030 std::string SelectorName = (Twine("enumeratorOf") + UpperKey).str(); | |
8031 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
8032 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) | |
8033 .second) { | |
8034 if (ReturnType.isNull()) { | |
8035 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8036 Builder.AddTextChunk("NSEnumerator *"); | |
8037 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8038 } | |
8039 | |
8040 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); | |
8041 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, | |
8042 CXCursor_ObjCInstanceMethodDecl)); | |
8043 } | |
8044 } | |
8045 | |
8046 // - (type *)memberOfKey:(type *)object | |
8047 if (IsInstanceMethod && | |
8048 (ReturnType.isNull() || ReturnType->isObjCObjectPointerType())) { | |
8049 std::string SelectorName = (Twine("memberOf") + UpperKey).str(); | |
8050 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
8051 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
8052 if (ReturnType.isNull()) { | |
8053 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8054 Builder.AddPlaceholderChunk("object-type"); | |
8055 Builder.AddTextChunk(" *"); | |
8056 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8057 } | |
8058 | |
8059 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
8060 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8061 if (ReturnType.isNull()) { | |
8062 Builder.AddPlaceholderChunk("object-type"); | |
8063 Builder.AddTextChunk(" *"); | |
8064 } else { | |
8065 Builder.AddTextChunk(GetCompletionTypeString( | |
8066 ReturnType, Context, Policy, Builder.getAllocator())); | |
8067 } | |
8068 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8069 Builder.AddTextChunk("object"); | |
8070 Results.AddResult(Result(Builder.TakeString(), UnorderedGetterPriority, | |
8071 CXCursor_ObjCInstanceMethodDecl)); | |
8072 } | |
8073 } | |
8074 | |
8075 // Mutable unordered accessors | |
8076 // - (void)addKeyObject:(type *)object | |
8077 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
8078 std::string SelectorName = | |
8079 (Twine("add") + UpperKey + Twine("Object")).str(); | |
8080 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
8081 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
8082 if (ReturnType.isNull()) { | |
8083 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8084 Builder.AddTextChunk("void"); | |
8085 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8086 } | |
8087 | |
8088 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
8089 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8090 Builder.AddPlaceholderChunk("object-type"); | |
8091 Builder.AddTextChunk(" *"); | |
8092 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8093 Builder.AddTextChunk("object"); | |
8094 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, | |
8095 CXCursor_ObjCInstanceMethodDecl)); | |
8096 } | |
8097 } | |
8098 | |
8099 // - (void)addKey:(NSSet *)objects | |
8100 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
8101 std::string SelectorName = (Twine("add") + UpperKey).str(); | |
8102 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
8103 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
8104 if (ReturnType.isNull()) { | |
8105 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8106 Builder.AddTextChunk("void"); | |
8107 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8108 } | |
8109 | |
8110 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
8111 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8112 Builder.AddTextChunk("NSSet *"); | |
8113 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8114 Builder.AddTextChunk("objects"); | |
8115 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, | |
8116 CXCursor_ObjCInstanceMethodDecl)); | |
8117 } | |
8118 } | |
8119 | |
8120 // - (void)removeKeyObject:(type *)object | |
8121 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
8122 std::string SelectorName = | |
8123 (Twine("remove") + UpperKey + Twine("Object")).str(); | |
8124 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
8125 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
8126 if (ReturnType.isNull()) { | |
8127 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8128 Builder.AddTextChunk("void"); | |
8129 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8130 } | |
8131 | |
8132 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
8133 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8134 Builder.AddPlaceholderChunk("object-type"); | |
8135 Builder.AddTextChunk(" *"); | |
8136 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8137 Builder.AddTextChunk("object"); | |
8138 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, | |
8139 CXCursor_ObjCInstanceMethodDecl)); | |
8140 } | |
8141 } | |
8142 | |
8143 // - (void)removeKey:(NSSet *)objects | |
8144 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
8145 std::string SelectorName = (Twine("remove") + UpperKey).str(); | |
8146 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
8147 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
8148 if (ReturnType.isNull()) { | |
8149 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8150 Builder.AddTextChunk("void"); | |
8151 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8152 } | |
8153 | |
8154 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
8155 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8156 Builder.AddTextChunk("NSSet *"); | |
8157 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8158 Builder.AddTextChunk("objects"); | |
8159 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, | |
8160 CXCursor_ObjCInstanceMethodDecl)); | |
8161 } | |
8162 } | |
8163 | |
8164 // - (void)intersectKey:(NSSet *)objects | |
8165 if (IsInstanceMethod && ReturnTypeMatchesVoid) { | |
8166 std::string SelectorName = (Twine("intersect") + UpperKey).str(); | |
8167 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
8168 if (KnownSelectors.insert(Selectors.getUnarySelector(SelectorId)).second) { | |
8169 if (ReturnType.isNull()) { | |
8170 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8171 Builder.AddTextChunk("void"); | |
8172 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8173 } | |
8174 | |
8175 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName + ":")); | |
8176 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8177 Builder.AddTextChunk("NSSet *"); | |
8178 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8179 Builder.AddTextChunk("objects"); | |
8180 Results.AddResult(Result(Builder.TakeString(), UnorderedSetterPriority, | |
8181 CXCursor_ObjCInstanceMethodDecl)); | |
8182 } | |
8183 } | |
8184 | |
8185 // Key-Value Observing | |
8186 // + (NSSet *)keyPathsForValuesAffectingKey | |
8187 if (!IsInstanceMethod && | |
8188 (ReturnType.isNull() || | |
8189 (ReturnType->isObjCObjectPointerType() && | |
8190 ReturnType->castAs<ObjCObjectPointerType>()->getInterfaceDecl() && | |
8191 ReturnType->castAs<ObjCObjectPointerType>() | |
8192 ->getInterfaceDecl() | |
8193 ->getName() == "NSSet"))) { | |
8194 std::string SelectorName = | |
8195 (Twine("keyPathsForValuesAffecting") + UpperKey).str(); | |
8196 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
8197 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) | |
8198 .second) { | |
8199 if (ReturnType.isNull()) { | |
8200 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8201 Builder.AddTextChunk("NSSet<NSString *> *"); | |
8202 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8203 } | |
8204 | |
8205 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); | |
8206 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, | |
8207 CXCursor_ObjCClassMethodDecl)); | |
8208 } | |
8209 } | |
8210 | |
8211 // + (BOOL)automaticallyNotifiesObserversForKey | |
8212 if (!IsInstanceMethod && | |
8213 (ReturnType.isNull() || ReturnType->isIntegerType() || | |
8214 ReturnType->isBooleanType())) { | |
8215 std::string SelectorName = | |
8216 (Twine("automaticallyNotifiesObserversOf") + UpperKey).str(); | |
8217 IdentifierInfo *SelectorId = &Context.Idents.get(SelectorName); | |
8218 if (KnownSelectors.insert(Selectors.getNullarySelector(SelectorId)) | |
8219 .second) { | |
8220 if (ReturnType.isNull()) { | |
8221 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8222 Builder.AddTextChunk("BOOL"); | |
8223 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8224 } | |
8225 | |
8226 Builder.AddTypedTextChunk(Allocator.CopyString(SelectorName)); | |
8227 Results.AddResult(Result(Builder.TakeString(), CCP_CodePattern, | |
8228 CXCursor_ObjCClassMethodDecl)); | |
8229 } | |
8230 } | |
8231 } | |
8232 | |
8233 void Sema::CodeCompleteObjCMethodDecl(Scope *S, Optional<bool> IsInstanceMethod, | |
8234 ParsedType ReturnTy) { | |
8235 // Determine the return type of the method we're declaring, if | |
8236 // provided. | |
8237 QualType ReturnType = GetTypeFromParser(ReturnTy); | |
8238 Decl *IDecl = nullptr; | |
8239 if (CurContext->isObjCContainer()) { | |
8240 ObjCContainerDecl *OCD = dyn_cast<ObjCContainerDecl>(CurContext); | |
8241 IDecl = OCD; | |
8242 } | |
8243 // Determine where we should start searching for methods. | |
8244 ObjCContainerDecl *SearchDecl = nullptr; | |
8245 bool IsInImplementation = false; | |
8246 if (Decl *D = IDecl) { | |
8247 if (ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) { | |
8248 SearchDecl = Impl->getClassInterface(); | |
8249 IsInImplementation = true; | |
8250 } else if (ObjCCategoryImplDecl *CatImpl = | |
8251 dyn_cast<ObjCCategoryImplDecl>(D)) { | |
8252 SearchDecl = CatImpl->getCategoryDecl(); | |
8253 IsInImplementation = true; | |
8254 } else | |
8255 SearchDecl = dyn_cast<ObjCContainerDecl>(D); | |
8256 } | |
8257 | |
8258 if (!SearchDecl && S) { | |
8259 if (DeclContext *DC = S->getEntity()) | |
8260 SearchDecl = dyn_cast<ObjCContainerDecl>(DC); | |
8261 } | |
8262 | |
8263 if (!SearchDecl) { | |
8264 HandleCodeCompleteResults(this, CodeCompleter, | |
8265 CodeCompletionContext::CCC_Other, nullptr, 0); | |
8266 return; | |
8267 } | |
8268 | |
8269 // Find all of the methods that we could declare/implement here. | |
8270 KnownMethodsMap KnownMethods; | |
8271 FindImplementableMethods(Context, SearchDecl, IsInstanceMethod, ReturnType, | |
8272 KnownMethods); | |
8273 | |
8274 // Add declarations or definitions for each of the known methods. | |
8275 typedef CodeCompletionResult Result; | |
8276 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
8277 CodeCompleter->getCodeCompletionTUInfo(), | |
8278 CodeCompletionContext::CCC_Other); | |
8279 Results.EnterNewScope(); | |
8280 PrintingPolicy Policy = getCompletionPrintingPolicy(*this); | |
8281 for (KnownMethodsMap::iterator M = KnownMethods.begin(), | |
8282 MEnd = KnownMethods.end(); | |
8283 M != MEnd; ++M) { | |
8284 ObjCMethodDecl *Method = M->second.getPointer(); | |
8285 CodeCompletionBuilder Builder(Results.getAllocator(), | |
8286 Results.getCodeCompletionTUInfo()); | |
8287 | |
8288 // Add the '-'/'+' prefix if it wasn't provided yet. | |
8289 if (!IsInstanceMethod) { | |
8290 Builder.AddTextChunk(Method->isInstanceMethod() ? "-" : "+"); | |
8291 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8292 } | |
8293 | |
8294 // If the result type was not already provided, add it to the | |
8295 // pattern as (type). | |
8296 if (ReturnType.isNull()) { | |
8297 QualType ResTy = Method->getSendResultType().stripObjCKindOfType(Context); | |
8298 AttributedType::stripOuterNullability(ResTy); | |
8299 AddObjCPassingTypeChunk(ResTy, Method->getObjCDeclQualifier(), Context, | |
8300 Policy, Builder); | |
8301 } | |
8302 | |
8303 Selector Sel = Method->getSelector(); | |
8304 | |
8305 // Add the first part of the selector to the pattern. | |
8306 Builder.AddTypedTextChunk( | |
8307 Builder.getAllocator().CopyString(Sel.getNameForSlot(0))); | |
8308 | |
8309 // Add parameters to the pattern. | |
8310 unsigned I = 0; | |
8311 for (ObjCMethodDecl::param_iterator P = Method->param_begin(), | |
8312 PEnd = Method->param_end(); | |
8313 P != PEnd; (void)++P, ++I) { | |
8314 // Add the part of the selector name. | |
8315 if (I == 0) | |
8316 Builder.AddTypedTextChunk(":"); | |
8317 else if (I < Sel.getNumArgs()) { | |
8318 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8319 Builder.AddTypedTextChunk( | |
8320 Builder.getAllocator().CopyString(Sel.getNameForSlot(I) + ":")); | |
8321 } else | |
8322 break; | |
8323 | |
8324 // Add the parameter type. | |
8325 QualType ParamType; | |
8326 if ((*P)->getObjCDeclQualifier() & Decl::OBJC_TQ_CSNullability) | |
8327 ParamType = (*P)->getType(); | |
8328 else | |
8329 ParamType = (*P)->getOriginalType(); | |
8330 ParamType = ParamType.substObjCTypeArgs( | |
8331 Context, {}, ObjCSubstitutionContext::Parameter); | |
8332 AttributedType::stripOuterNullability(ParamType); | |
8333 AddObjCPassingTypeChunk(ParamType, (*P)->getObjCDeclQualifier(), Context, | |
8334 Policy, Builder); | |
8335 | |
8336 if (IdentifierInfo *Id = (*P)->getIdentifier()) | |
8337 Builder.AddTextChunk(Builder.getAllocator().CopyString(Id->getName())); | |
8338 } | |
8339 | |
8340 if (Method->isVariadic()) { | |
8341 if (Method->param_size() > 0) | |
8342 Builder.AddChunk(CodeCompletionString::CK_Comma); | |
8343 Builder.AddTextChunk("..."); | |
8344 } | |
8345 | |
8346 if (IsInImplementation && Results.includeCodePatterns()) { | |
8347 // We will be defining the method here, so add a compound statement. | |
8348 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8349 Builder.AddChunk(CodeCompletionString::CK_LeftBrace); | |
8350 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
8351 if (!Method->getReturnType()->isVoidType()) { | |
8352 // If the result type is not void, add a return clause. | |
8353 Builder.AddTextChunk("return"); | |
8354 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8355 Builder.AddPlaceholderChunk("expression"); | |
8356 Builder.AddChunk(CodeCompletionString::CK_SemiColon); | |
8357 } else | |
8358 Builder.AddPlaceholderChunk("statements"); | |
8359 | |
8360 Builder.AddChunk(CodeCompletionString::CK_VerticalSpace); | |
8361 Builder.AddChunk(CodeCompletionString::CK_RightBrace); | |
8362 } | |
8363 | |
8364 unsigned Priority = CCP_CodePattern; | |
8365 auto R = Result(Builder.TakeString(), Method, Priority); | |
8366 if (!M->second.getInt()) | |
8367 setInBaseClass(R); | |
8368 Results.AddResult(std::move(R)); | |
8369 } | |
8370 | |
8371 // Add Key-Value-Coding and Key-Value-Observing accessor methods for all of | |
8372 // the properties in this class and its categories. | |
8373 if (Context.getLangOpts().ObjC) { | |
8374 SmallVector<ObjCContainerDecl *, 4> Containers; | |
8375 Containers.push_back(SearchDecl); | |
8376 | |
8377 VisitedSelectorSet KnownSelectors; | |
8378 for (KnownMethodsMap::iterator M = KnownMethods.begin(), | |
8379 MEnd = KnownMethods.end(); | |
8380 M != MEnd; ++M) | |
8381 KnownSelectors.insert(M->first); | |
8382 | |
8383 ObjCInterfaceDecl *IFace = dyn_cast<ObjCInterfaceDecl>(SearchDecl); | |
8384 if (!IFace) | |
8385 if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(SearchDecl)) | |
8386 IFace = Category->getClassInterface(); | |
8387 | |
8388 if (IFace) | |
8389 for (auto *Cat : IFace->visible_categories()) | |
8390 Containers.push_back(Cat); | |
8391 | |
8392 if (IsInstanceMethod) { | |
8393 for (unsigned I = 0, N = Containers.size(); I != N; ++I) | |
8394 for (auto *P : Containers[I]->instance_properties()) | |
8395 AddObjCKeyValueCompletions(P, *IsInstanceMethod, ReturnType, Context, | |
8396 KnownSelectors, Results); | |
8397 } | |
8398 } | |
8399 | |
8400 Results.ExitScope(); | |
8401 | |
8402 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
8403 Results.data(), Results.size()); | |
8404 } | |
8405 | |
8406 void Sema::CodeCompleteObjCMethodDeclSelector( | |
8407 Scope *S, bool IsInstanceMethod, bool AtParameterName, ParsedType ReturnTy, | |
8408 ArrayRef<IdentifierInfo *> SelIdents) { | |
8409 // If we have an external source, load the entire class method | |
8410 // pool from the AST file. | |
8411 if (ExternalSource) { | |
8412 for (uint32_t I = 0, N = ExternalSource->GetNumExternalSelectors(); I != N; | |
8413 ++I) { | |
8414 Selector Sel = ExternalSource->GetExternalSelector(I); | |
8415 if (Sel.isNull() || MethodPool.count(Sel)) | |
8416 continue; | |
8417 | |
8418 ReadMethodPool(Sel); | |
8419 } | |
8420 } | |
8421 | |
8422 // Build the set of methods we can see. | |
8423 typedef CodeCompletionResult Result; | |
8424 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
8425 CodeCompleter->getCodeCompletionTUInfo(), | |
8426 CodeCompletionContext::CCC_Other); | |
8427 | |
8428 if (ReturnTy) | |
8429 Results.setPreferredType(GetTypeFromParser(ReturnTy).getNonReferenceType()); | |
8430 | |
8431 Results.EnterNewScope(); | |
8432 for (GlobalMethodPool::iterator M = MethodPool.begin(), | |
8433 MEnd = MethodPool.end(); | |
8434 M != MEnd; ++M) { | |
8435 for (ObjCMethodList *MethList = IsInstanceMethod ? &M->second.first | |
8436 : &M->second.second; | |
8437 MethList && MethList->getMethod(); MethList = MethList->getNext()) { | |
8438 if (!isAcceptableObjCMethod(MethList->getMethod(), MK_Any, SelIdents)) | |
8439 continue; | |
8440 | |
8441 if (AtParameterName) { | |
8442 // Suggest parameter names we've seen before. | |
8443 unsigned NumSelIdents = SelIdents.size(); | |
8444 if (NumSelIdents && | |
8445 NumSelIdents <= MethList->getMethod()->param_size()) { | |
8446 ParmVarDecl *Param = | |
8447 MethList->getMethod()->parameters()[NumSelIdents - 1]; | |
8448 if (Param->getIdentifier()) { | |
8449 CodeCompletionBuilder Builder(Results.getAllocator(), | |
8450 Results.getCodeCompletionTUInfo()); | |
8451 Builder.AddTypedTextChunk(Builder.getAllocator().CopyString( | |
8452 Param->getIdentifier()->getName())); | |
8453 Results.AddResult(Builder.TakeString()); | |
8454 } | |
8455 } | |
8456 | |
8457 continue; | |
8458 } | |
8459 | |
8460 Result R(MethList->getMethod(), | |
8461 Results.getBasePriority(MethList->getMethod()), nullptr); | |
8462 R.StartParameter = SelIdents.size(); | |
8463 R.AllParametersAreInformative = false; | |
8464 R.DeclaringEntity = true; | |
8465 Results.MaybeAddResult(R, CurContext); | |
8466 } | |
8467 } | |
8468 | |
8469 Results.ExitScope(); | |
8470 | |
8471 if (!AtParameterName && !SelIdents.empty() && | |
8472 SelIdents.front()->getName().startswith("init")) { | |
8473 for (const auto &M : PP.macros()) { | |
8474 if (M.first->getName() != "NS_DESIGNATED_INITIALIZER") | |
8475 continue; | |
8476 Results.EnterNewScope(); | |
8477 CodeCompletionBuilder Builder(Results.getAllocator(), | |
8478 Results.getCodeCompletionTUInfo()); | |
8479 Builder.AddTypedTextChunk( | |
8480 Builder.getAllocator().CopyString(M.first->getName())); | |
8481 Results.AddResult(CodeCompletionResult(Builder.TakeString(), CCP_Macro, | |
8482 CXCursor_MacroDefinition)); | |
8483 Results.ExitScope(); | |
8484 } | |
8485 } | |
8486 | |
8487 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
8488 Results.data(), Results.size()); | |
8489 } | |
8490 | |
8491 void Sema::CodeCompletePreprocessorDirective(bool InConditional) { | |
8492 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
8493 CodeCompleter->getCodeCompletionTUInfo(), | |
8494 CodeCompletionContext::CCC_PreprocessorDirective); | |
8495 Results.EnterNewScope(); | |
8496 | |
8497 // #if <condition> | |
8498 CodeCompletionBuilder Builder(Results.getAllocator(), | |
8499 Results.getCodeCompletionTUInfo()); | |
8500 Builder.AddTypedTextChunk("if"); | |
8501 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8502 Builder.AddPlaceholderChunk("condition"); | |
8503 Results.AddResult(Builder.TakeString()); | |
8504 | |
8505 // #ifdef <macro> | |
8506 Builder.AddTypedTextChunk("ifdef"); | |
8507 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8508 Builder.AddPlaceholderChunk("macro"); | |
8509 Results.AddResult(Builder.TakeString()); | |
8510 | |
8511 // #ifndef <macro> | |
8512 Builder.AddTypedTextChunk("ifndef"); | |
8513 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8514 Builder.AddPlaceholderChunk("macro"); | |
8515 Results.AddResult(Builder.TakeString()); | |
8516 | |
8517 if (InConditional) { | |
8518 // #elif <condition> | |
8519 Builder.AddTypedTextChunk("elif"); | |
8520 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8521 Builder.AddPlaceholderChunk("condition"); | |
8522 Results.AddResult(Builder.TakeString()); | |
8523 | |
8524 // #else | |
8525 Builder.AddTypedTextChunk("else"); | |
8526 Results.AddResult(Builder.TakeString()); | |
8527 | |
8528 // #endif | |
8529 Builder.AddTypedTextChunk("endif"); | |
8530 Results.AddResult(Builder.TakeString()); | |
8531 } | |
8532 | |
8533 // #include "header" | |
8534 Builder.AddTypedTextChunk("include"); | |
8535 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8536 Builder.AddTextChunk("\""); | |
8537 Builder.AddPlaceholderChunk("header"); | |
8538 Builder.AddTextChunk("\""); | |
8539 Results.AddResult(Builder.TakeString()); | |
8540 | |
8541 // #include <header> | |
8542 Builder.AddTypedTextChunk("include"); | |
8543 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8544 Builder.AddTextChunk("<"); | |
8545 Builder.AddPlaceholderChunk("header"); | |
8546 Builder.AddTextChunk(">"); | |
8547 Results.AddResult(Builder.TakeString()); | |
8548 | |
8549 // #define <macro> | |
8550 Builder.AddTypedTextChunk("define"); | |
8551 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8552 Builder.AddPlaceholderChunk("macro"); | |
8553 Results.AddResult(Builder.TakeString()); | |
8554 | |
8555 // #define <macro>(<args>) | |
8556 Builder.AddTypedTextChunk("define"); | |
8557 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8558 Builder.AddPlaceholderChunk("macro"); | |
8559 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8560 Builder.AddPlaceholderChunk("args"); | |
8561 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8562 Results.AddResult(Builder.TakeString()); | |
8563 | |
8564 // #undef <macro> | |
8565 Builder.AddTypedTextChunk("undef"); | |
8566 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8567 Builder.AddPlaceholderChunk("macro"); | |
8568 Results.AddResult(Builder.TakeString()); | |
8569 | |
8570 // #line <number> | |
8571 Builder.AddTypedTextChunk("line"); | |
8572 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8573 Builder.AddPlaceholderChunk("number"); | |
8574 Results.AddResult(Builder.TakeString()); | |
8575 | |
8576 // #line <number> "filename" | |
8577 Builder.AddTypedTextChunk("line"); | |
8578 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8579 Builder.AddPlaceholderChunk("number"); | |
8580 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8581 Builder.AddTextChunk("\""); | |
8582 Builder.AddPlaceholderChunk("filename"); | |
8583 Builder.AddTextChunk("\""); | |
8584 Results.AddResult(Builder.TakeString()); | |
8585 | |
8586 // #error <message> | |
8587 Builder.AddTypedTextChunk("error"); | |
8588 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8589 Builder.AddPlaceholderChunk("message"); | |
8590 Results.AddResult(Builder.TakeString()); | |
8591 | |
8592 // #pragma <arguments> | |
8593 Builder.AddTypedTextChunk("pragma"); | |
8594 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8595 Builder.AddPlaceholderChunk("arguments"); | |
8596 Results.AddResult(Builder.TakeString()); | |
8597 | |
8598 if (getLangOpts().ObjC) { | |
8599 // #import "header" | |
8600 Builder.AddTypedTextChunk("import"); | |
8601 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8602 Builder.AddTextChunk("\""); | |
8603 Builder.AddPlaceholderChunk("header"); | |
8604 Builder.AddTextChunk("\""); | |
8605 Results.AddResult(Builder.TakeString()); | |
8606 | |
8607 // #import <header> | |
8608 Builder.AddTypedTextChunk("import"); | |
8609 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8610 Builder.AddTextChunk("<"); | |
8611 Builder.AddPlaceholderChunk("header"); | |
8612 Builder.AddTextChunk(">"); | |
8613 Results.AddResult(Builder.TakeString()); | |
8614 } | |
8615 | |
8616 // #include_next "header" | |
8617 Builder.AddTypedTextChunk("include_next"); | |
8618 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8619 Builder.AddTextChunk("\""); | |
8620 Builder.AddPlaceholderChunk("header"); | |
8621 Builder.AddTextChunk("\""); | |
8622 Results.AddResult(Builder.TakeString()); | |
8623 | |
8624 // #include_next <header> | |
8625 Builder.AddTypedTextChunk("include_next"); | |
8626 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8627 Builder.AddTextChunk("<"); | |
8628 Builder.AddPlaceholderChunk("header"); | |
8629 Builder.AddTextChunk(">"); | |
8630 Results.AddResult(Builder.TakeString()); | |
8631 | |
8632 // #warning <message> | |
8633 Builder.AddTypedTextChunk("warning"); | |
8634 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8635 Builder.AddPlaceholderChunk("message"); | |
8636 Results.AddResult(Builder.TakeString()); | |
8637 | |
8638 // Note: #ident and #sccs are such crazy anachronisms that we don't provide | |
8639 // completions for them. And __include_macros is a Clang-internal extension | |
8640 // that we don't want to encourage anyone to use. | |
8641 | |
8642 // FIXME: we don't support #assert or #unassert, so don't suggest them. | |
8643 Results.ExitScope(); | |
8644 | |
8645 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
8646 Results.data(), Results.size()); | |
8647 } | |
8648 | |
8649 void Sema::CodeCompleteInPreprocessorConditionalExclusion(Scope *S) { | |
8650 CodeCompleteOrdinaryName(S, S->getFnParent() ? Sema::PCC_RecoveryInFunction | |
8651 : Sema::PCC_Namespace); | |
8652 } | |
8653 | |
8654 void Sema::CodeCompletePreprocessorMacroName(bool IsDefinition) { | |
8655 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
8656 CodeCompleter->getCodeCompletionTUInfo(), | |
8657 IsDefinition ? CodeCompletionContext::CCC_MacroName | |
8658 : CodeCompletionContext::CCC_MacroNameUse); | |
8659 if (!IsDefinition && (!CodeCompleter || CodeCompleter->includeMacros())) { | |
8660 // Add just the names of macros, not their arguments. | |
8661 CodeCompletionBuilder Builder(Results.getAllocator(), | |
8662 Results.getCodeCompletionTUInfo()); | |
8663 Results.EnterNewScope(); | |
8664 for (Preprocessor::macro_iterator M = PP.macro_begin(), | |
8665 MEnd = PP.macro_end(); | |
8666 M != MEnd; ++M) { | |
8667 Builder.AddTypedTextChunk( | |
8668 Builder.getAllocator().CopyString(M->first->getName())); | |
8669 Results.AddResult(CodeCompletionResult( | |
8670 Builder.TakeString(), CCP_CodePattern, CXCursor_MacroDefinition)); | |
8671 } | |
8672 Results.ExitScope(); | |
8673 } else if (IsDefinition) { | |
8674 // FIXME: Can we detect when the user just wrote an include guard above? | |
8675 } | |
8676 | |
8677 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
8678 Results.data(), Results.size()); | |
8679 } | |
8680 | |
8681 void Sema::CodeCompletePreprocessorExpression() { | |
8682 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
8683 CodeCompleter->getCodeCompletionTUInfo(), | |
8684 CodeCompletionContext::CCC_PreprocessorExpression); | |
8685 | |
8686 if (!CodeCompleter || CodeCompleter->includeMacros()) | |
8687 AddMacroResults(PP, Results, | |
8688 !CodeCompleter || CodeCompleter->loadExternal(), true); | |
8689 | |
8690 // defined (<macro>) | |
8691 Results.EnterNewScope(); | |
8692 CodeCompletionBuilder Builder(Results.getAllocator(), | |
8693 Results.getCodeCompletionTUInfo()); | |
8694 Builder.AddTypedTextChunk("defined"); | |
8695 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace); | |
8696 Builder.AddChunk(CodeCompletionString::CK_LeftParen); | |
8697 Builder.AddPlaceholderChunk("macro"); | |
8698 Builder.AddChunk(CodeCompletionString::CK_RightParen); | |
8699 Results.AddResult(Builder.TakeString()); | |
8700 Results.ExitScope(); | |
8701 | |
8702 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
8703 Results.data(), Results.size()); | |
8704 } | |
8705 | |
8706 void Sema::CodeCompletePreprocessorMacroArgument(Scope *S, | |
8707 IdentifierInfo *Macro, | |
8708 MacroInfo *MacroInfo, | |
8709 unsigned Argument) { | |
8710 // FIXME: In the future, we could provide "overload" results, much like we | |
8711 // do for function calls. | |
8712 | |
8713 // Now just ignore this. There will be another code-completion callback | |
8714 // for the expanded tokens. | |
8715 } | |
8716 | |
8717 // This handles completion inside an #include filename, e.g. #include <foo/ba | |
8718 // We look for the directory "foo" under each directory on the include path, | |
8719 // list its files, and reassemble the appropriate #include. | |
8720 void Sema::CodeCompleteIncludedFile(llvm::StringRef Dir, bool Angled) { | |
8721 // RelDir should use /, but unescaped \ is possible on windows! | |
8722 // Our completions will normalize to / for simplicity, this case is rare. | |
8723 std::string RelDir = llvm::sys::path::convert_to_slash(Dir); | |
8724 // We need the native slashes for the actual file system interactions. | |
8725 SmallString<128> NativeRelDir = StringRef(RelDir); | |
8726 llvm::sys::path::native(NativeRelDir); | |
8727 llvm::vfs::FileSystem &FS = | |
8728 getSourceManager().getFileManager().getVirtualFileSystem(); | |
8729 | |
8730 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
8731 CodeCompleter->getCodeCompletionTUInfo(), | |
8732 CodeCompletionContext::CCC_IncludedFile); | |
8733 llvm::DenseSet<StringRef> SeenResults; // To deduplicate results. | |
8734 | |
8735 // Helper: adds one file or directory completion result. | |
8736 auto AddCompletion = [&](StringRef Filename, bool IsDirectory) { | |
8737 SmallString<64> TypedChunk = Filename; | |
8738 // Directory completion is up to the slash, e.g. <sys/ | |
8739 TypedChunk.push_back(IsDirectory ? '/' : Angled ? '>' : '"'); | |
8740 auto R = SeenResults.insert(TypedChunk); | |
8741 if (R.second) { // New completion | |
8742 const char *InternedTyped = Results.getAllocator().CopyString(TypedChunk); | |
8743 *R.first = InternedTyped; // Avoid dangling StringRef. | |
8744 CodeCompletionBuilder Builder(CodeCompleter->getAllocator(), | |
8745 CodeCompleter->getCodeCompletionTUInfo()); | |
8746 Builder.AddTypedTextChunk(InternedTyped); | |
8747 // The result is a "Pattern", which is pretty opaque. | |
8748 // We may want to include the real filename to allow smart ranking. | |
8749 Results.AddResult(CodeCompletionResult(Builder.TakeString())); | |
8750 } | |
8751 }; | |
8752 | |
8753 // Helper: scans IncludeDir for nice files, and adds results for each. | |
8754 auto AddFilesFromIncludeDir = [&](StringRef IncludeDir, | |
8755 bool IsSystem, | |
8756 DirectoryLookup::LookupType_t LookupType) { | |
8757 llvm::SmallString<128> Dir = IncludeDir; | |
8758 if (!NativeRelDir.empty()) { | |
8759 if (LookupType == DirectoryLookup::LT_Framework) { | |
8760 // For a framework dir, #include <Foo/Bar/> actually maps to | |
8761 // a path of Foo.framework/Headers/Bar/. | |
8762 auto Begin = llvm::sys::path::begin(NativeRelDir); | |
8763 auto End = llvm::sys::path::end(NativeRelDir); | |
8764 | |
8765 llvm::sys::path::append(Dir, *Begin + ".framework", "Headers"); | |
8766 llvm::sys::path::append(Dir, ++Begin, End); | |
8767 } else { | |
8768 llvm::sys::path::append(Dir, NativeRelDir); | |
8769 } | |
8770 } | |
8771 | |
8772 std::error_code EC; | |
8773 unsigned Count = 0; | |
8774 for (auto It = FS.dir_begin(Dir, EC); | |
8775 !EC && It != llvm::vfs::directory_iterator(); It.increment(EC)) { | |
8776 if (++Count == 2500) // If we happen to hit a huge directory, | |
8777 break; // bail out early so we're not too slow. | |
8778 StringRef Filename = llvm::sys::path::filename(It->path()); | |
8779 switch (It->type()) { | |
8780 case llvm::sys::fs::file_type::directory_file: | |
8781 // All entries in a framework directory must have a ".framework" suffix, | |
8782 // but the suffix does not appear in the source code's include/import. | |
8783 if (LookupType == DirectoryLookup::LT_Framework && | |
8784 NativeRelDir.empty() && !Filename.consume_back(".framework")) | |
8785 break; | |
8786 | |
8787 AddCompletion(Filename, /*IsDirectory=*/true); | |
8788 break; | |
8789 case llvm::sys::fs::file_type::regular_file: | |
8790 // Only files that really look like headers. (Except in system dirs). | |
8791 if (!IsSystem) { | |
8792 // Header extensions from Types.def, which we can't depend on here. | |
8793 if (!(Filename.endswith_lower(".h") || | |
8794 Filename.endswith_lower(".hh") || | |
8795 Filename.endswith_lower(".hpp") || | |
8796 Filename.endswith_lower(".inc"))) | |
8797 break; | |
8798 } | |
8799 AddCompletion(Filename, /*IsDirectory=*/false); | |
8800 break; | |
8801 default: | |
8802 break; | |
8803 } | |
8804 } | |
8805 }; | |
8806 | |
8807 // Helper: adds results relative to IncludeDir, if possible. | |
8808 auto AddFilesFromDirLookup = [&](const DirectoryLookup &IncludeDir, | |
8809 bool IsSystem) { | |
8810 switch (IncludeDir.getLookupType()) { | |
8811 case DirectoryLookup::LT_HeaderMap: | |
8812 // header maps are not (currently) enumerable. | |
8813 break; | |
8814 case DirectoryLookup::LT_NormalDir: | |
8815 AddFilesFromIncludeDir(IncludeDir.getDir()->getName(), IsSystem, | |
8816 DirectoryLookup::LT_NormalDir); | |
8817 break; | |
8818 case DirectoryLookup::LT_Framework: | |
8819 AddFilesFromIncludeDir(IncludeDir.getFrameworkDir()->getName(), IsSystem, | |
8820 DirectoryLookup::LT_Framework); | |
8821 break; | |
8822 } | |
8823 }; | |
8824 | |
8825 // Finally with all our helpers, we can scan the include path. | |
8826 // Do this in standard order so deduplication keeps the right file. | |
8827 // (In case we decide to add more details to the results later). | |
8828 const auto &S = PP.getHeaderSearchInfo(); | |
8829 using llvm::make_range; | |
8830 if (!Angled) { | |
8831 // The current directory is on the include path for "quoted" includes. | |
8832 auto *CurFile = PP.getCurrentFileLexer()->getFileEntry(); | |
8833 if (CurFile && CurFile->getDir()) | |
8834 AddFilesFromIncludeDir(CurFile->getDir()->getName(), false, | |
8835 DirectoryLookup::LT_NormalDir); | |
8836 for (const auto &D : make_range(S.quoted_dir_begin(), S.quoted_dir_end())) | |
8837 AddFilesFromDirLookup(D, false); | |
8838 } | |
8839 for (const auto &D : make_range(S.angled_dir_begin(), S.angled_dir_end())) | |
8840 AddFilesFromDirLookup(D, false); | |
8841 for (const auto &D : make_range(S.system_dir_begin(), S.system_dir_end())) | |
8842 AddFilesFromDirLookup(D, true); | |
8843 | |
8844 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
8845 Results.data(), Results.size()); | |
8846 } | |
8847 | |
8848 void Sema::CodeCompleteNaturalLanguage() { | |
8849 HandleCodeCompleteResults(this, CodeCompleter, | |
8850 CodeCompletionContext::CCC_NaturalLanguage, nullptr, | |
8851 0); | |
8852 } | |
8853 | |
8854 void Sema::CodeCompleteAvailabilityPlatformName() { | |
8855 ResultBuilder Results(*this, CodeCompleter->getAllocator(), | |
8856 CodeCompleter->getCodeCompletionTUInfo(), | |
8857 CodeCompletionContext::CCC_Other); | |
8858 Results.EnterNewScope(); | |
8859 static const char *Platforms[] = {"macOS", "iOS", "watchOS", "tvOS"}; | |
8860 for (const char *Platform : llvm::makeArrayRef(Platforms)) { | |
8861 Results.AddResult(CodeCompletionResult(Platform)); | |
8862 Results.AddResult(CodeCompletionResult(Results.getAllocator().CopyString( | |
8863 Twine(Platform) + "ApplicationExtension"))); | |
8864 } | |
8865 Results.ExitScope(); | |
8866 HandleCodeCompleteResults(this, CodeCompleter, Results.getCompletionContext(), | |
8867 Results.data(), Results.size()); | |
8868 } | |
8869 | |
8870 void Sema::GatherGlobalCodeCompletions( | |
8871 CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, | |
8872 SmallVectorImpl<CodeCompletionResult> &Results) { | |
8873 ResultBuilder Builder(*this, Allocator, CCTUInfo, | |
8874 CodeCompletionContext::CCC_Recovery); | |
8875 if (!CodeCompleter || CodeCompleter->includeGlobals()) { | |
8876 CodeCompletionDeclConsumer Consumer(Builder, | |
8877 Context.getTranslationUnitDecl()); | |
8878 LookupVisibleDecls(Context.getTranslationUnitDecl(), LookupAnyName, | |
8879 Consumer, | |
8880 !CodeCompleter || CodeCompleter->loadExternal()); | |
8881 } | |
8882 | |
8883 if (!CodeCompleter || CodeCompleter->includeMacros()) | |
8884 AddMacroResults(PP, Builder, | |
8885 !CodeCompleter || CodeCompleter->loadExternal(), true); | |
8886 | |
8887 Results.clear(); | |
8888 Results.insert(Results.end(), Builder.data(), | |
8889 Builder.data() + Builder.size()); | |
8890 } |