@@ -176,161 +176,8 @@ struct TupleSplatMigratorPass : public ASTMigratorPass,
176
176
return true ;
177
177
};
178
178
179
- // Handles such kind of cases:
180
- // \code
181
- // func test(_: ((Int, Int)) -> ()) {}
182
- // test({ (x,y) in })
183
- // \endcode
184
- // This compiles fine in Swift 3 but Swift 4 complains with
185
- // error: cannot convert value of type '(_, _) -> ()' to expected
186
- // argument type '((Int, Int)) -> ()'
187
- //
188
- // It will fix the code to "test({ let (x,y) = $0; })".
189
- //
190
- auto handleTupleMapToClosureArgs = [&](const CallExpr *E) -> bool {
191
- auto fnTy = E->getFn ()->getType ()->getAs <FunctionType>();
192
- if (!fnTy)
193
- return false ;
194
- auto fnTy2 = fnTy->getInput ()->getAs <FunctionType>();
195
- if (!fnTy2) {
196
- // This may have been a tuple type of one element.
197
- if (auto tuple = fnTy->getInput ()->getAs <TupleType>()) {
198
- if (tuple->getNumElements () == 1 ) {
199
- fnTy2 = tuple->getElement (0 ).getType ()->getAs <FunctionType>();
200
- }
201
- }
202
- }
203
- if (!fnTy2) {
204
- return false ;
205
- }
206
- auto parenT = dyn_cast<ParenType>(fnTy2->getInput ().getPointer ());
207
- if (!parenT)
208
- return false ;
209
- auto tupleInFn = parenT->getAs <TupleType>();
210
- if (!tupleInFn)
211
- return false ;
212
- if (!E->getArg ())
213
- return false ;
214
- auto argE = E->getArg ()->getSemanticsProvidingExpr ();
215
- while (auto *ICE = dyn_cast<ImplicitConversionExpr>(argE))
216
- argE = ICE->getSubExpr ();
217
- argE = argE->getSemanticsProvidingExpr ();
218
- auto closureE = dyn_cast<ClosureExpr>(argE);
219
- if (!closureE) {
220
- if (auto *FCE = dyn_cast<FunctionConversionExpr>(argE)) {
221
- closureE = dyn_cast<ClosureExpr>(FCE->getSubExpr ());
222
- }
223
- }
224
- if (!closureE)
225
- return false ;
226
- if (closureE->getInLoc ().isInvalid ())
227
- return false ;
228
- auto paramList = closureE->getParameters ();
229
- if (!paramList ||
230
- paramList->getLParenLoc ().isInvalid () || paramList->getRParenLoc ().isInvalid ())
231
- return false ;
232
- if (paramList->size () != tupleInFn->getNumElements ())
233
- return false ;
234
- if (paramList->size () == 0 )
235
- return false ;
236
-
237
- auto hasParamListWithNoTypes = [&]() {
238
- if (closureE->hasExplicitResultType ())
239
- return false ;
240
- for (auto *param : *paramList) {
241
- auto tyLoc = param->getTypeLoc ();
242
- if (!tyLoc.isNull ())
243
- return false ;
244
- }
245
- return true ;
246
- };
247
-
248
- if (hasParamListWithNoTypes ()) {
249
- // Simpler form depending on type inference.
250
- // Change "(x, y) in " to "let (x, y) = $0;".
251
-
252
- Editor.insert (paramList->getLParenLoc (), " let " );
253
- for (auto *param : *paramList) {
254
- // If the argument list is like "(_ x, _ y)", remove the underscores.
255
- if (param->getArgumentNameLoc ().isValid ()) {
256
- Editor.remove (CharSourceRange (SM, param->getArgumentNameLoc (),
257
- param->getNameLoc ()));
258
- }
259
- // If the argument list has type annotations, remove them.
260
- auto tyLoc = param->getTypeLoc ();
261
- if (!tyLoc.isNull () && !tyLoc.getSourceRange ().isInvalid ()) {
262
- auto nameRange = CharSourceRange (param->getNameLoc (),
263
- param->getNameStr ().size ());
264
- auto tyRange = Lexer::getCharSourceRangeFromSourceRange (SM,
265
- tyLoc.getSourceRange ());
266
- Editor.remove (CharSourceRange (SM, nameRange.getEnd (),
267
- tyRange.getEnd ()));
268
- }
269
- }
270
-
271
- // If the original closure was a single expression without the need
272
- // for a `return` statement, it needs one now, because we've added a new
273
- // assignment statement just above.
274
- if (closureE->hasSingleExpressionBody ()) {
275
- Editor.replaceToken (closureE->getInLoc (), " = $0; return" );
276
- } else {
277
- Editor.replaceToken (closureE->getInLoc (), " = $0;" );
278
- }
279
-
280
- return true ;
281
- }
282
-
283
- // Includes types in the closure signature. The following will do a
284
- // more complicated edit than the above:
285
- // (x: Int, y: Int) -> Int in
286
- // to
287
- // (__val:(Int, Int)) -> Int in let (x,y) = __val;
288
-
289
- std::string paramListText;
290
- {
291
- llvm::raw_string_ostream OS (paramListText);
292
- OS << " (__val:(" ;
293
- for (size_t i = 0 , e = paramList->size (); i != e; ++i) {
294
- if (i != 0 )
295
- OS << " , " ;
296
- auto param = paramList->get (i);
297
- auto tyLoc = param->getTypeLoc ();
298
- if (!tyLoc.isNull () && !tyLoc.getSourceRange ().isInvalid ()) {
299
- OS << SM.extractText (
300
- Lexer::getCharSourceRangeFromSourceRange (SM,
301
- tyLoc.getSourceRange ()));
302
- } else {
303
- param->getType ().print (OS);
304
- }
305
- }
306
- OS << " ))" ;
307
- }
308
- std::string varBindText;
309
- {
310
- llvm::raw_string_ostream OS (varBindText);
311
- OS << " let (" ;
312
- for (size_t i = 0 , e = paramList->size (); i != e; ++i) {
313
- if (i != 0 )
314
- OS << " ," ;
315
- auto param = paramList->get (i);
316
- OS << param->getNameStr ();
317
- }
318
- OS << " ) = __val;" ;
319
-
320
- if (closureE->hasSingleExpressionBody ()) {
321
- OS << " return" ;
322
- }
323
- }
324
-
325
- Editor.replace (paramList->getSourceRange (), paramListText);
326
- Editor.insertAfterToken (closureE->getInLoc (), varBindText);
327
- return true ;
328
- };
329
-
330
179
if (handleCallsToEmptyTuple (E))
331
180
return ;
332
- if (handleTupleMapToClosureArgs (E))
333
- return ;
334
181
}
335
182
336
183
bool walkToExprPre (Expr *E) override {
0 commit comments