20
20
#include " swift/AST/Initializer.h"
21
21
#include " swift/AST/LazyResolver.h"
22
22
#include " swift/AST/Module.h"
23
+ #include " swift/AST/ParameterList.h"
23
24
#include " swift/AST/Pattern.h"
24
25
#include " swift/AST/Stmt.h"
25
26
#include " swift/AST/Type.h"
@@ -289,7 +290,9 @@ static void collectPossibleCalleesByQualifiedLookup(
289
290
Type declaredMemberType = VD->getInterfaceType ();
290
291
if (VD->getDeclContext ()->isTypeContext ()) {
291
292
if (isa<FuncDecl>(VD)) {
292
- if (!isOnMetaType)
293
+ if (!isOnMetaType && VD->isStatic ())
294
+ continue ;
295
+ if (isOnMetaType == VD->isStatic ())
293
296
declaredMemberType =
294
297
declaredMemberType->castTo <AnyFunctionType>()->getResult ();
295
298
} else if (isa<ConstructorDecl>(VD)) {
@@ -407,6 +410,31 @@ static bool collectPossibleCalleesForSubscript(
407
410
return !candidates.empty ();
408
411
}
409
412
413
+ // / For the given \p unresolvedMemberExpr, collect possible callee types and
414
+ // / declarations.
415
+ static bool collectPossibleCalleesForUnresolvedMember (
416
+ DeclContext &DC, UnresolvedMemberExpr *unresolvedMemberExpr,
417
+ SmallVectorImpl<FunctionTypeAndDecl> &candidates) {
418
+ auto currModule = DC.getParentModule ();
419
+ auto baseName = unresolvedMemberExpr->getName ().getBaseName ();
420
+
421
+ // Get the context of the expression itself.
422
+ ExprContextInfo contextInfo (&DC, unresolvedMemberExpr);
423
+ for (auto expectedTy : contextInfo.getPossibleTypes ()) {
424
+ if (!expectedTy->mayHaveMembers ())
425
+ continue ;
426
+ SmallVector<FunctionTypeAndDecl, 2 > members;
427
+ collectPossibleCalleesByQualifiedLookup (DC, MetatypeType::get (expectedTy),
428
+ baseName, members);
429
+ for (auto member : members) {
430
+ if (isReferenceableByImplicitMemberExpr (currModule, &DC, expectedTy,
431
+ member.second ))
432
+ candidates.push_back (member);
433
+ }
434
+ }
435
+ return !candidates.empty ();
436
+ }
437
+
410
438
// / Get index of \p CCExpr in \p Args. \p Args is usually a \c TupleExpr
411
439
// / or \c ParenExpr.
412
440
// / \returns \c true if success, \c false if \p CCExpr is not a part of \p Args.
@@ -470,6 +498,11 @@ class ExprContextAnalyzer {
470
498
if (!collectPossibleCalleesForSubscript (*DC, subscriptExpr, Candidates))
471
499
return false ;
472
500
Arg = subscriptExpr->getIndex ();
501
+ } else if (auto *unresolvedMemberExpr = dyn_cast<UnresolvedMemberExpr>(E)) {
502
+ if (!collectPossibleCalleesForUnresolvedMember (*DC, unresolvedMemberExpr,
503
+ Candidates))
504
+ return false ;
505
+ Arg = unresolvedMemberExpr->getArgument ();
473
506
} else {
474
507
llvm_unreachable (" unexpected expression kind" );
475
508
}
@@ -484,7 +517,8 @@ class ExprContextAnalyzer {
484
517
// Collect possible types (or labels) at the position.
485
518
{
486
519
bool MayNeedName = !HasName && !E->isImplicit () &&
487
- (isa<CallExpr>(E) | isa<SubscriptExpr>(E));
520
+ (isa<CallExpr>(E) | isa<SubscriptExpr>(E) ||
521
+ isa<UnresolvedMemberExpr>(E));
488
522
SmallPtrSet<TypeBase *, 4 > seenTypes;
489
523
SmallPtrSet<Identifier, 4 > seenNames;
490
524
for (auto &typeAndDecl : Candidates) {
@@ -493,18 +527,30 @@ class ExprContextAnalyzer {
493
527
memberDC = typeAndDecl.second ->getInnermostDeclContext ();
494
528
495
529
auto Params = typeAndDecl.first ->getParams ();
496
- if (Position >= Params.size ())
497
- continue ;
498
- const auto &Param = Params[Position];
499
- if (Param.hasLabel () && MayNeedName) {
500
- if (seenNames.insert (Param.getLabel ()).second )
501
- recordPossibleName (Param.getLabel ().str ());
502
- } else {
503
- Type ty = Param.getOldType ();
504
- if (memberDC && ty->hasTypeParameter ())
505
- ty = memberDC->mapTypeIntoContext (ty);
506
- if (seenTypes.insert (ty.getPointer ()).second )
507
- recordPossibleType (ty);
530
+ ParameterList *paramList = nullptr ;
531
+ if (auto VD = typeAndDecl.second ) {
532
+ if (auto FD = dyn_cast<AbstractFunctionDecl>(VD))
533
+ paramList = FD->getParameters ();
534
+ else if (auto SD = dyn_cast<SubscriptDecl>(VD))
535
+ paramList = SD->getIndices ();
536
+ if (paramList && paramList->size () != Params.size ())
537
+ paramList = nullptr ;
538
+ }
539
+ for (auto Pos = Position; Pos < Params.size (); ++Pos) {
540
+ const auto &Param = Params[Pos];
541
+ if (Param.hasLabel () && MayNeedName) {
542
+ if (seenNames.insert (Param.getLabel ()).second )
543
+ recordPossibleName (Param.getLabel ().str ());
544
+ if (paramList && paramList->get (Position)->isDefaultArgument ())
545
+ continue ;
546
+ } else {
547
+ Type ty = Param.getOldType ();
548
+ if (memberDC && ty->hasTypeParameter ())
549
+ ty = memberDC->mapTypeIntoContext (ty);
550
+ if (seenTypes.insert (ty.getPointer ()).second )
551
+ recordPossibleType (ty);
552
+ }
553
+ break ;
508
554
}
509
555
}
510
556
}
@@ -515,6 +561,7 @@ class ExprContextAnalyzer {
515
561
switch (Parent->getKind ()) {
516
562
case ExprKind::Call:
517
563
case ExprKind::Subscript:
564
+ case ExprKind::UnresolvedMember:
518
565
case ExprKind::Binary:
519
566
case ExprKind::PrefixUnary: {
520
567
analyzeApplyExpr (Parent);
@@ -706,11 +753,14 @@ class ExprContextAnalyzer {
706
753
case ExprKind::Assign:
707
754
case ExprKind::Array:
708
755
return true ;
756
+ case ExprKind::UnresolvedMember:
757
+ return true ;
709
758
case ExprKind::Tuple: {
710
759
auto ParentE = Parent.getAsExpr ();
711
760
return !ParentE ||
712
761
(!isa<CallExpr>(ParentE) && !isa<SubscriptExpr>(ParentE) &&
713
- !isa<BinaryExpr>(ParentE));
762
+ !isa<BinaryExpr>(ParentE) &&
763
+ !isa<UnresolvedMemberExpr>(ParentE));
714
764
}
715
765
case ExprKind::Closure:
716
766
return isSingleExpressionBodyForCodeCompletion (
@@ -779,3 +829,75 @@ ExprContextInfo::ExprContextInfo(DeclContext *DC, Expr *TargetExpr) {
779
829
PossibleCallees, singleExpressionBody);
780
830
Analyzer.Analyze ();
781
831
}
832
+
833
+ // ===----------------------------------------------------------------------===//
834
+ // isReferenceableByImplicitMemberExpr(ModuleD, DeclContext, Type, ValueDecl)
835
+ // ===----------------------------------------------------------------------===//
836
+
837
+ bool swift::ide::isReferenceableByImplicitMemberExpr (
838
+ ModuleDecl *CurrModule, DeclContext *DC, Type T, ValueDecl *VD) {
839
+
840
+ if (VD->isOperator ())
841
+ return false ;
842
+
843
+ if (!VD->hasInterfaceType ())
844
+ return false ;
845
+
846
+ if (T->getOptionalObjectType () &&
847
+ VD->getModuleContext ()->isStdlibModule ()) {
848
+ // In optional context, ignore '.init(<some>)', 'init(nilLiteral:)',
849
+ if (isa<ConstructorDecl>(VD))
850
+ return false ;
851
+ // TODO: Ignore '.some(<Wrapped>)' and '.none' too *in expression
852
+ // context*. They are useful in pattern context though.
853
+ }
854
+
855
+ // Enum element decls can always be referenced by implicit member
856
+ // expression.
857
+ if (isa<EnumElementDecl>(VD))
858
+ return true ;
859
+
860
+ // Only non-failable constructors are implicitly referenceable.
861
+ if (auto CD = dyn_cast<ConstructorDecl>(VD)) {
862
+ switch (CD->getFailability ()) {
863
+ case OTK_None:
864
+ case OTK_ImplicitlyUnwrappedOptional:
865
+ return true ;
866
+ case OTK_Optional:
867
+ return false ;
868
+ }
869
+ }
870
+
871
+ // Otherwise, check the result type matches the contextual type.
872
+ auto declTy = T->getTypeOfMember (CurrModule, VD);
873
+ if (declTy->is <ErrorType>())
874
+ return false ;
875
+
876
+ // Member types can also be implicitly referenceable as long as it's
877
+ // convertible to the contextual type.
878
+ if (auto CD = dyn_cast<TypeDecl>(VD)) {
879
+ declTy = declTy->getMetatypeInstanceType ();
880
+
881
+ // Emit construction for the same type via typealias doesn't make sense
882
+ // because we are emitting all `.init()`s.
883
+ if (declTy->isEqual (T))
884
+ return false ;
885
+ return swift::isConvertibleTo (declTy, T, *DC);
886
+ }
887
+
888
+ // Only static member can be referenced.
889
+ if (!VD->isStatic ())
890
+ return false ;
891
+
892
+ if (isa<FuncDecl>(VD)) {
893
+ // Strip '(Self.Type) ->' and parameters.
894
+ declTy = declTy->castTo <AnyFunctionType>()->getResult ();
895
+ declTy = declTy->castTo <AnyFunctionType>()->getResult ();
896
+ } else if (auto FT = declTy->getAs <AnyFunctionType>()) {
897
+ // The compiler accepts 'static var factory: () -> T' for implicit
898
+ // member expression.
899
+ // FIXME: This emits just 'factory'. We should emit 'factory()' instead.
900
+ declTy = FT->getResult ();
901
+ }
902
+ return declTy->isEqual (T) || swift::isConvertibleTo (declTy, T, *DC);
903
+ }
0 commit comments