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