1010//
1111// ===----------------------------------------------------------------------===//
1212
13- #include " swift/Basic/Assertions.h"
1413#include " swift/IDE/ArgumentCompletion.h"
14+ #include " swift/AST/Types.h"
15+ #include " swift/Basic/Assertions.h"
1516#include " swift/IDE/CodeCompletion.h"
1617#include " swift/IDE/CompletionLookup.h"
1718#include " swift/IDE/SelectedOverloadInfo.h"
19+ #include " swift/IDE/SignatureHelp.h"
1820#include " swift/Sema/ConstraintSystem.h"
1921#include " swift/Sema/IDETypeChecking.h"
2022
@@ -60,9 +62,9 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams(
6062 // a multitple trailing closure label but the parameter is not a function
6163 // type. Since we only allow labeled trailing closures after the first
6264 // trailing closure, we cannot pass an argument for this parameter.
63- // If the parameter is required, stop here since we cannot pass an argument
64- // for the parameter. If it's optional, keep looking for more trailing
65- // closures that can be passed.
65+ // If the parameter is required, stop here since we cannot pass an
66+ // argument for the parameter. If it's optional, keep looking for more
67+ // trailing closures that can be passed.
6668 if (Required) {
6769 break ;
6870 } else {
@@ -95,14 +97,62 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams(
9597static bool hasParentCallLikeExpr (Expr *E, ConstraintSystem &CS) {
9698 E = CS.getParentExpr (E);
9799 while (E) {
98- if (E->getArgs () || isa<ParenExpr>(E) || isa<TupleExpr>(E) || isa<CollectionExpr>(E)) {
100+ if (E->getArgs () || isa<ParenExpr>(E) || isa<TupleExpr>(E) ||
101+ isa<CollectionExpr>(E)) {
99102 return true ;
100103 }
101104 E = CS.getParentExpr (E);
102105 }
103106 return false ;
104107}
105108
109+ // / The callee can be a double-applied function in the second apply (e.g.
110+ // / `f()(|)`). In that case, the normal callee locator will not be able to find
111+ // / a selected overload since an overload has been selected for the first apply
112+ // / but not the second. We try to find the function's declaration and type
113+ // / if it turns out to be a double apply.
114+ static std::optional<std::pair<ValueDecl *, AnyFunctionType *>>
115+ tryResolveDoubleAppliedFunction (CallExpr *OuterCall, const Solution &S) {
116+ if (!OuterCall)
117+ return std::nullopt ;
118+
119+ auto *InnerCall = dyn_cast<CallExpr>(OuterCall->getSemanticFn ());
120+ if (!InnerCall)
121+ return std::nullopt ;
122+
123+ auto &CS = S.getConstraintSystem ();
124+ auto *InnerCallLocator = CS.getConstraintLocator (InnerCall);
125+ auto Overload = S.getCalleeOverloadChoiceIfAvailable (InnerCallLocator);
126+ if (!Overload)
127+ return std::nullopt ;
128+
129+ if (!Overload->choice .isDecl ())
130+ return std::nullopt ;
131+
132+ auto FuncRefInfo = Overload->choice .getFunctionRefInfo ();
133+ if (!FuncRefInfo.isDoubleApply ())
134+ return std::nullopt ;
135+
136+ auto CalleeTy = Overload->adjustedOpenedType ->getAs <AnyFunctionType>();
137+ auto ResultTy = S.simplifyTypeForCodeCompletion (CalleeTy->getResult ());
138+
139+ auto *FuncTy = ResultTy->getAs <AnyFunctionType>();
140+ if (!FuncTy)
141+ return std::nullopt ;
142+
143+ auto *VD = Overload->choice .getDecl ();
144+ auto BaseTy = Overload->choice .getBaseType ();
145+ bool IsOuterCallImplicitlyCurried =
146+ VD->isInstanceMember () && !doesMemberRefApplyCurriedSelf (BaseTy, VD);
147+
148+ // The function declaration is only relevant if the function is an implicitly
149+ // curried instance method.
150+ if (IsOuterCallImplicitlyCurried)
151+ return std::make_pair (Overload->choice .getDecl (), FuncTy);
152+
153+ return std::make_pair (nullptr , FuncTy);
154+ }
155+
106156void ArgumentTypeCheckCompletionCallback::sawSolutionImpl (const Solution &S) {
107157 Type ExpectedTy = getTypeForCompletion (S, CompletionExpr);
108158
@@ -230,11 +280,24 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
230280 llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes;
231281 getSolutionSpecificVarTypes (S, SolutionSpecificVarTypes);
232282
283+ ValueDecl *FuncD = nullptr ;
233284 AnyFunctionType *FuncTy = nullptr ;
285+ bool IsSecondApply = false ;
234286 if (Info.ValueTy ) {
235- FuncTy = Info.ValueTy ->lookThroughAllOptionalTypes ()->getAs <AnyFunctionType>();
287+ FuncD = Info.getValue ();
288+ FuncTy =
289+ Info.ValueTy ->lookThroughAllOptionalTypes ()->getAs <AnyFunctionType>();
290+ } else if (auto Result = tryResolveDoubleAppliedFunction (
291+ dyn_cast<CallExpr>(ParentCall), S)) {
292+ FuncD = Result->first ;
293+ FuncTy = Result->second ;
294+ IsSecondApply = true ;
236295 }
237296
297+ bool IsImplicitlyCurried =
298+ Info.ValueRef && Info.ValueRef .getDecl ()->isInstanceMember () &&
299+ !doesMemberRefApplyCurriedSelf (Info.BaseTy , Info.ValueRef .getDecl ());
300+
238301 // Determine which parameters are optional. We need to do this in
239302 // `sawSolutionImpl` because it accesses the substitution map in
240303 // `Info.ValueRef`. This substitution map might contain type variables that
@@ -246,9 +309,7 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
246309 for (auto Idx : range (0 , ParamsToPass.size ())) {
247310 bool Optional = false ;
248311 if (Info.ValueRef ) {
249- if (Info.ValueRef .getDecl ()->isInstanceMember () &&
250- !doesMemberRefApplyCurriedSelf (Info.BaseTy ,
251- Info.ValueRef .getDecl ())) {
312+ if (IsImplicitlyCurried) {
252313 // We are completing in an unapplied instance function, eg.
253314 // struct TestStatic {
254315 // func method() -> Void {}
@@ -286,10 +347,11 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
286347 }
287348
288349 Results.push_back (
289- {ExpectedTy, ExpectedCallType, isa<SubscriptExpr>(ParentCall),
290- Info.getValue (), FuncTy, ArgIdx, ParamIdx, std::move (ClaimedParams),
291- IsNoninitialVariadic, IncludeSignature, Info.BaseTy , HasLabel, FirstTrailingClosureIndex,
292- IsAsync, DeclParamIsOptional, SolutionSpecificVarTypes});
350+ {ExpectedTy, ExpectedCallType, isa<SubscriptExpr>(ParentCall), FuncD,
351+ FuncTy, ArgIdx, ParamIdx, std::move (ClaimedParams), IsNoninitialVariadic,
352+ IncludeSignature, Info.BaseTy , HasLabel, FirstTrailingClosureIndex,
353+ IsAsync, IsImplicitlyCurried, IsSecondApply, DeclParamIsOptional,
354+ SolutionSpecificVarTypes});
293355}
294356
295357void ArgumentTypeCheckCompletionCallback::computeShadowedDecls (
@@ -432,3 +494,19 @@ void ArgumentTypeCheckCompletionCallback::collectResults(
432494 *Lookup.getExpectedTypeContext (),
433495 Lookup.canCurrDeclContextHandleAsync ());
434496}
497+
498+ void ArgumentTypeCheckCompletionCallback::getSignatures (
499+ SourceLoc Loc, DeclContext *DC, SmallVectorImpl<Signature> &Signatures) {
500+ SmallPtrSet<ValueDecl *, 4 > ShadowedDecls;
501+ computeShadowedDecls (ShadowedDecls);
502+
503+ for (auto &Result : Results) {
504+ // Only show signature if the function isn't overridden.
505+ if (!Result.FuncTy || ShadowedDecls.contains (Result.FuncD ))
506+ continue ;
507+
508+ Signatures.push_back ({Result.IsSubscript , Result.IsImplicitlyCurried ,
509+ Result.IsSecondApply , Result.FuncD , Result.FuncTy ,
510+ Result.ExpectedType , Result.ParamIdx });
511+ }
512+ }
0 commit comments