@@ -404,7 +404,27 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
404
404
InsertedFunctions.insert (FD->getBaseName ().getIdentifier ().str ());
405
405
}
406
406
}
407
+
408
+ // Handle helper functions without wrappees first.
409
+ for (auto &Cur: HelperFuncInfo) {
410
+ if (Cur.ExpressionToWrap )
411
+ continue ;
412
+ auto FuncName = Cur.getFuncName ();
413
+ // Avoid inserting the helper function if it's already present.
414
+ if (!InsertedFunctions.count (FuncName)) {
415
+ Editor.insert (FileEndLoc, Cur.getFuncDef ());
416
+ InsertedFunctions.insert (FuncName);
417
+ }
418
+ }
419
+
420
+ // Remove all helper functions that're without expressions to wrap.
421
+ HelperFuncInfo.erase (std::remove_if (HelperFuncInfo.begin (),
422
+ HelperFuncInfo.end (), [](const ConversionFunctionInfo& Info) {
423
+ return !Info.ExpressionToWrap ;
424
+ }), HelperFuncInfo.end ());
425
+
407
426
for (auto &Cur: HelperFuncInfo) {
427
+ assert (Cur.ExpressionToWrap );
408
428
// Avoid wrapping nil expression.
409
429
if (isNilExpr (Cur.ExpressionToWrap ))
410
430
continue ;
@@ -885,9 +905,11 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
885
905
return wrapAttributeReference (E, E, false );
886
906
}
887
907
888
- void insertHelperFunction (NodeAnnotation Anno, StringRef RawType,
889
- StringRef NewType, bool FromString,
890
- Expr *Wrappee) {
908
+ ConversionFunctionInfo &insertHelperFunction (NodeAnnotation Anno,
909
+ StringRef RawType,
910
+ StringRef NewType,
911
+ bool FromString,
912
+ Expr *Wrappee) {
891
913
HelperFuncInfo.emplace_back (Wrappee);
892
914
ConversionFunctionInfo &Info = HelperFuncInfo.back ();
893
915
llvm::raw_svector_ostream OS (Info.Buffer );
@@ -959,6 +981,7 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
959
981
OS << " (_ input: " << Segs[3 ] << " ) -> " << Segs[2 ] << " {\n " ;
960
982
OS << Segs[5 ] << " \n }\n " ;
961
983
}
984
+ return Info;
962
985
}
963
986
964
987
void handleStringRepresentableArg (ValueDecl *FD, Expr *Arg, Expr *Call) {
@@ -1106,6 +1129,18 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
1106
1129
return true ;
1107
1130
}
1108
1131
1132
+ static void collectParamters (AbstractFunctionDecl *AFD,
1133
+ SmallVectorImpl<ParamDecl*> &Results) {
1134
+ for (auto PL : AFD->getParameterLists ()) {
1135
+ for (auto *PD: *PL) {
1136
+ // Self parameter should not be updated.
1137
+ if (PD->isSelfParameter ())
1138
+ continue ;
1139
+ Results.push_back (PD);
1140
+ }
1141
+ }
1142
+ }
1143
+
1109
1144
void handleFuncDeclRename (AbstractFunctionDecl *AFD,
1110
1145
CharSourceRange NameRange) {
1111
1146
bool IgnoreBase = false ;
@@ -1114,29 +1149,26 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
1114
1149
if (!IgnoreBase)
1115
1150
Editor.replace (NameRange, View.base ());
1116
1151
unsigned Index = 0 ;
1117
- for (auto PL : AFD->getParameterLists ()) {
1118
- for (auto *PD : *PL) {
1119
- if (Index == View.argSize ())
1120
- break ;
1121
- // Self parameter should not be updated.
1122
- if (PD->isSelfParameter ())
1123
- continue ;
1124
- StringRef NewArg = View.args ()[Index++];
1125
- auto ArgLoc = PD->getArgumentNameLoc ();
1126
-
1127
- // Represent empty label with underscore.
1128
- if (NewArg.empty ())
1129
- NewArg = " _" ;
1130
-
1131
- // If the argument name is not specified, add the argument name before
1132
- // the parameter name.
1133
- if (ArgLoc.isInvalid ())
1134
- Editor.insertBefore (PD->getNameLoc (),
1135
- (llvm::Twine (NewArg) + " " ).str ());
1136
- else {
1137
- // Otherwise, replace the argument name directly.
1138
- Editor.replaceToken (ArgLoc, NewArg);
1139
- }
1152
+ SmallVector<ParamDecl*, 4 > Params;
1153
+ collectParamters (AFD, Params);
1154
+ for (auto *PD: Params) {
1155
+ if (Index == View.argSize ())
1156
+ break ;
1157
+ StringRef NewArg = View.args ()[Index++];
1158
+ auto ArgLoc = PD->getArgumentNameLoc ();
1159
+
1160
+ // Represent empty label with underscore.
1161
+ if (NewArg.empty ())
1162
+ NewArg = " _" ;
1163
+
1164
+ // If the argument name is not specified, add the argument name before
1165
+ // the parameter name.
1166
+ if (ArgLoc.isInvalid ())
1167
+ Editor.insertBefore (PD->getNameLoc (),
1168
+ (llvm::Twine (NewArg) + " " ).str ());
1169
+ else {
1170
+ // Otherwise, replace the argument name directly.
1171
+ Editor.replaceToken (ArgLoc, NewArg);
1140
1172
}
1141
1173
}
1142
1174
}
@@ -1224,6 +1256,49 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
1224
1256
}
1225
1257
}
1226
1258
1259
+ // When users override a SDK function whose parameter types have been changed,
1260
+ // we should introduce a local variable in the body of the function definition
1261
+ // to shadow the changed parameter. Also, a proper conversion function should
1262
+ // be defined to bridge the parameter to the local variable.
1263
+ void handleLocalParameterBridge (AbstractFunctionDecl *AFD,
1264
+ CommonDiffItem *DiffItem) {
1265
+ assert (AFD);
1266
+ assert (DiffItem->isStringRepresentableChange ());
1267
+
1268
+ // We only handle top-level parameter type change.
1269
+ if (DiffItem->getChildIndices ().size () != 1 )
1270
+ return ;
1271
+ auto Idx = DiffItem->getChildIndices ().front ();
1272
+
1273
+ // We don't handle return type change.
1274
+ if (Idx == 0 )
1275
+ return ;
1276
+ Idx --;
1277
+ SmallVector<ParamDecl*, 4 > Params;
1278
+ collectParamters (AFD, Params);
1279
+ if (Params.size () <= Idx)
1280
+ return ;
1281
+
1282
+ // Get the internal name of the changed paramter.
1283
+ auto VariableName = Params[Idx]->getParameterName ().str ();
1284
+
1285
+ // Insert the helper function to convert the type back to raw types.
1286
+ auto &Info = insertHelperFunction (DiffItem->DiffKind , DiffItem->LeftComment ,
1287
+ DiffItem->RightComment , /* From String*/ false ,
1288
+ /* No expression to wrap*/ nullptr );
1289
+
1290
+ if (auto *BD = AFD->getBody ()) {
1291
+ auto BL = BD->getLBraceLoc ();
1292
+ if (BL.isValid ()) {
1293
+ // Insert the local variable declaration after the opening brace.
1294
+ Editor.insertAfterToken (BL,
1295
+ (llvm::Twine (" \n // Local variable inserted by Swift 4.2 migrator." ) +
1296
+ " \n let " + VariableName + " = " + Info.getFuncName () + " (" +
1297
+ VariableName + " )\n " ).str ());
1298
+ }
1299
+ }
1300
+ }
1301
+
1227
1302
bool walkToDeclPre (Decl *D, CharSourceRange Range) override {
1228
1303
if (D->isImplicit ())
1229
1304
return true ;
@@ -1235,6 +1310,8 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
1235
1310
handleOverridingTypeChange (AFD, DiffItem);
1236
1311
else if (DiffItem->isToPropertyChange ())
1237
1312
handleOverridingPropertyChange (AFD, DiffItem);
1313
+ else if (DiffItem->isStringRepresentableChange ())
1314
+ handleLocalParameterBridge (AFD, DiffItem);
1238
1315
}
1239
1316
}
1240
1317
}
0 commit comments