@@ -78,6 +78,98 @@ bool ArgumentTypeCheckCompletionCallback::addPossibleParams(
78
78
return ShowGlobalCompletions;
79
79
}
80
80
81
+ // / Information that \c getSelectedOverloadInfo gathered about a
82
+ // / \c SelectedOverload.
83
+ struct SelectedOverloadInfo {
84
+ // / The function that is being called.
85
+ ValueDecl *FuncD = nullptr ;
86
+ // / The type of the called function itself (not its result type)
87
+ Type FuncTy;
88
+ // / The type on which the function is being called. \c null if the function is
89
+ // / a free function.
90
+ Type CallBaseTy;
91
+ };
92
+
93
+ // / Extract additional information about the overload that is being called by
94
+ // / \p CalleeLocator.
95
+ SelectedOverloadInfo getSelectedOverloadInfo (const Solution &S,
96
+ ConstraintLocator *CalleeLocator) {
97
+ auto &CS = S.getConstraintSystem ();
98
+
99
+ SelectedOverloadInfo Result;
100
+
101
+ auto SelectedOverload = S.getOverloadChoiceIfAvailable (CalleeLocator);
102
+ if (!SelectedOverload) {
103
+ return Result;
104
+ }
105
+
106
+ switch (SelectedOverload->choice .getKind ()) {
107
+ case OverloadChoiceKind::KeyPathApplication:
108
+ case OverloadChoiceKind::Decl:
109
+ case OverloadChoiceKind::DeclViaDynamic:
110
+ case OverloadChoiceKind::DeclViaBridge:
111
+ case OverloadChoiceKind::DeclViaUnwrappedOptional: {
112
+ Result.CallBaseTy = SelectedOverload->choice .getBaseType ();
113
+ if (Result.CallBaseTy ) {
114
+ Result.CallBaseTy = S.simplifyType (Result.CallBaseTy )->getRValueType ();
115
+ }
116
+
117
+ Result.FuncD = SelectedOverload->choice .getDeclOrNull ();
118
+ Result.FuncTy =
119
+ S.simplifyTypeForCodeCompletion (SelectedOverload->openedType );
120
+
121
+ // For completion as the arg in a call to the implicit [keypath: _]
122
+ // subscript the solver can't know what kind of keypath is expected without
123
+ // an actual argument (e.g. a KeyPath vs WritableKeyPath) so it ends up as a
124
+ // hole. Just assume KeyPath so we show the expected keypath's root type to
125
+ // users rather than '_'.
126
+ if (SelectedOverload->choice .getKind () ==
127
+ OverloadChoiceKind::KeyPathApplication) {
128
+ auto Params = Result.FuncTy ->getAs <AnyFunctionType>()->getParams ();
129
+ if (Params.size () == 1 &&
130
+ Params[0 ].getPlainType ()->is <UnresolvedType>()) {
131
+ auto *KPDecl = CS.getASTContext ().getKeyPathDecl ();
132
+ Type KPTy =
133
+ KPDecl->mapTypeIntoContext (KPDecl->getDeclaredInterfaceType ());
134
+ Type KPValueTy = KPTy->castTo <BoundGenericType>()->getGenericArgs ()[1 ];
135
+ KPTy = BoundGenericType::get (KPDecl, Type (),
136
+ {Result.CallBaseTy , KPValueTy});
137
+ Result.FuncTy =
138
+ FunctionType::get ({Params[0 ].withType (KPTy)}, KPValueTy);
139
+ }
140
+ }
141
+ break ;
142
+ }
143
+ case OverloadChoiceKind::KeyPathDynamicMemberLookup: {
144
+ auto *fnType = SelectedOverload->openedType ->castTo <FunctionType>();
145
+ assert (fnType->getParams ().size () == 1 &&
146
+ " subscript always has one argument" );
147
+ // Parameter type is KeyPath<T, U> where `T` is a root type
148
+ // and U is a leaf type (aka member type).
149
+ auto keyPathTy =
150
+ fnType->getParams ()[0 ].getPlainType ()->castTo <BoundGenericType>();
151
+
152
+ auto *keyPathDecl = keyPathTy->getAnyNominal ();
153
+ assert (isKnownKeyPathType (keyPathTy) &&
154
+ " parameter is supposed to be a keypath" );
155
+
156
+ auto KeyPathDynamicLocator = CS.getConstraintLocator (
157
+ CalleeLocator, LocatorPathElt::KeyPathDynamicMember (keyPathDecl));
158
+ Result = getSelectedOverloadInfo (S, KeyPathDynamicLocator);
159
+ break ;
160
+ }
161
+ case OverloadChoiceKind::DynamicMemberLookup:
162
+ case OverloadChoiceKind::TupleIndex:
163
+ // If it's DynamicMemberLookup, we don't know which function is being
164
+ // called, so we can't extract any information from it.
165
+ // TupleIndex isn't a function call and is not relevant for argument
166
+ // completion because it doesn't take arguments.
167
+ break ;
168
+ }
169
+
170
+ return Result;
171
+ }
172
+
81
173
void ArgumentTypeCheckCompletionCallback::sawSolutionImpl (const Solution &S) {
82
174
Type ExpectedTy = getTypeForCompletion (S, CompletionExpr);
83
175
@@ -104,41 +196,8 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
104
196
105
197
auto *CallLocator = CS.getConstraintLocator (ParentCall);
106
198
auto *CalleeLocator = S.getCalleeLocator (CallLocator);
107
- ValueDecl *FuncD = nullptr ;
108
- Type FuncTy;
109
- Type CallBaseTy;
110
- // If we are calling a closure in-place there is no overload choice, but we
111
- // still have all the other required information (like the argument's
112
- // expected type) to provide useful code completion results.
113
- if (auto SelectedOverload = S.getOverloadChoiceIfAvailable (CalleeLocator)) {
114
-
115
- CallBaseTy = SelectedOverload->choice .getBaseType ();
116
- if (CallBaseTy) {
117
- CallBaseTy = S.simplifyType (CallBaseTy)->getRValueType ();
118
- }
119
-
120
- FuncD = SelectedOverload->choice .getDeclOrNull ();
121
- FuncTy = S.simplifyTypeForCodeCompletion (SelectedOverload->openedType );
122
199
123
- // For completion as the arg in a call to the implicit [keypath: _]
124
- // subscript the solver can't know what kind of keypath is expected without
125
- // an actual argument (e.g. a KeyPath vs WritableKeyPath) so it ends up as a
126
- // hole. Just assume KeyPath so we show the expected keypath's root type to
127
- // users rather than '_'.
128
- if (SelectedOverload->choice .getKind () ==
129
- OverloadChoiceKind::KeyPathApplication) {
130
- auto Params = FuncTy->getAs <AnyFunctionType>()->getParams ();
131
- if (Params.size () == 1 &&
132
- Params[0 ].getPlainType ()->is <UnresolvedType>()) {
133
- auto *KPDecl = CS.getASTContext ().getKeyPathDecl ();
134
- Type KPTy =
135
- KPDecl->mapTypeIntoContext (KPDecl->getDeclaredInterfaceType ());
136
- Type KPValueTy = KPTy->castTo <BoundGenericType>()->getGenericArgs ()[1 ];
137
- KPTy = BoundGenericType::get (KPDecl, Type (), {CallBaseTy, KPValueTy});
138
- FuncTy = FunctionType::get ({Params[0 ].withType (KPTy)}, KPValueTy);
139
- }
140
- }
141
- }
200
+ auto Info = getSelectedOverloadInfo (S, CalleeLocator);
142
201
143
202
// Find the parameter the completion was bound to (if any), as well as which
144
203
// parameters are already bound (so we don't suggest them even when the args
@@ -174,9 +233,6 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
174
233
ClaimedParams.insert (i);
175
234
}
176
235
}
177
- } else {
178
- // FIXME: We currently don't look through @dynamicMemberLookup applications
179
- // for subscripts (rdar://90363138)
180
236
}
181
237
182
238
bool HasLabel = false ;
@@ -190,8 +246,9 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
190
246
191
247
// If this is a duplicate of any other result, ignore this solution.
192
248
if (llvm::any_of (Results, [&](const Result &R) {
193
- return R.FuncD == FuncD && nullableTypesEqual (R.FuncTy , FuncTy) &&
194
- nullableTypesEqual (R.BaseType , CallBaseTy) &&
249
+ return R.FuncD == Info.FuncD &&
250
+ nullableTypesEqual (R.FuncTy , Info.FuncTy ) &&
251
+ nullableTypesEqual (R.BaseType , Info.CallBaseTy ) &&
195
252
R.ParamIdx == ParamIdx &&
196
253
R.IsNoninitialVariadic == IsNoninitialVariadic;
197
254
})) {
@@ -201,9 +258,9 @@ void ArgumentTypeCheckCompletionCallback::sawSolutionImpl(const Solution &S) {
201
258
llvm::SmallDenseMap<const VarDecl *, Type> SolutionSpecificVarTypes;
202
259
getSolutionSpecificVarTypes (S, SolutionSpecificVarTypes);
203
260
204
- Results.push_back ({ExpectedTy, isa<SubscriptExpr>(ParentCall), FuncD, FuncTy ,
205
- ArgIdx, ParamIdx, std::move (ClaimedParams),
206
- IsNoninitialVariadic, CallBaseTy, HasLabel, IsAsync,
261
+ Results.push_back ({ExpectedTy, isa<SubscriptExpr>(ParentCall), Info. FuncD ,
262
+ Info. FuncTy , ArgIdx, ParamIdx, std::move (ClaimedParams),
263
+ IsNoninitialVariadic, Info. CallBaseTy , HasLabel, IsAsync,
207
264
SolutionSpecificVarTypes});
208
265
}
209
266
0 commit comments