10
10
//
11
11
// ===----------------------------------------------------------------------===//
12
12
13
- #include " swift/Basic/Assertions.h"
14
13
#include " swift/IDE/ArgumentCompletion.h"
14
+ #include " swift/AST/Types.h"
15
+ #include " swift/Basic/Assertions.h"
15
16
#include " swift/IDE/CodeCompletion.h"
16
17
#include " swift/IDE/CompletionLookup.h"
17
18
#include " swift/IDE/SelectedOverloadInfo.h"
19
+ #include " swift/IDE/SignatureHelp.h"
18
20
#include " swift/Sema/ConstraintSystem.h"
19
21
#include " swift/Sema/IDETypeChecking.h"
20
22
@@ -60,9 +62,9 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams(
60
62
// a multitple trailing closure label but the parameter is not a function
61
63
// type. Since we only allow labeled trailing closures after the first
62
64
// 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.
66
68
if (Required) {
67
69
break ;
68
70
} else {
@@ -95,14 +97,62 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams(
95
97
static bool hasParentCallLikeExpr (Expr *E, ConstraintSystem &CS) {
96
98
E = CS.getParentExpr (E);
97
99
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)) {
99
102
return true ;
100
103
}
101
104
E = CS.getParentExpr (E);
102
105
}
103
106
return false ;
104
107
}
105
108
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
+
106
156
void ArgumentTypeCheckCompletionCallback::sawSolutionImpl (const Solution &S) {
107
157
Type ExpectedTy = getTypeForCompletion (S, CompletionExpr);
108
158
@@ -230,11 +280,24 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
230
280
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes;
231
281
getSolutionSpecificVarTypes (S, SolutionSpecificVarTypes);
232
282
283
+ ValueDecl *FuncD = nullptr ;
233
284
AnyFunctionType *FuncTy = nullptr ;
285
+ bool IsSecondApply = false ;
234
286
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 ;
236
295
}
237
296
297
+ bool IsImplicitlyCurried =
298
+ Info.ValueRef && Info.ValueRef .getDecl ()->isInstanceMember () &&
299
+ !doesMemberRefApplyCurriedSelf (Info.BaseTy , Info.ValueRef .getDecl ());
300
+
238
301
// Determine which parameters are optional. We need to do this in
239
302
// `sawSolutionImpl` because it accesses the substitution map in
240
303
// `Info.ValueRef`. This substitution map might contain type variables that
@@ -246,9 +309,7 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
246
309
for (auto Idx : range (0 , ParamsToPass.size ())) {
247
310
bool Optional = false ;
248
311
if (Info.ValueRef ) {
249
- if (Info.ValueRef .getDecl ()->isInstanceMember () &&
250
- !doesMemberRefApplyCurriedSelf (Info.BaseTy ,
251
- Info.ValueRef .getDecl ())) {
312
+ if (IsImplicitlyCurried) {
252
313
// We are completing in an unapplied instance function, eg.
253
314
// struct TestStatic {
254
315
// func method() -> Void {}
@@ -286,10 +347,11 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
286
347
}
287
348
288
349
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});
293
355
}
294
356
295
357
void ArgumentTypeCheckCompletionCallback::computeShadowedDecls (
@@ -432,3 +494,19 @@ void ArgumentTypeCheckCompletionCallback::collectResults(
432
494
*Lookup.getExpectedTypeContext (),
433
495
Lookup.canCurrDeclContextHandleAsync ());
434
496
}
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