@@ -250,6 +250,19 @@ static ValueDecl* getReferencedDecl(Expr *E) {
250
250
}
251
251
}
252
252
253
+ struct ConversionFunctionInfo {
254
+ Expr *ExpressionToWrap;
255
+ SmallString<256 > Buffer;
256
+ unsigned FuncNameStart;
257
+ unsigned FuncNameEnd;
258
+ ConversionFunctionInfo (Expr *ExpressionToWrap):
259
+ ExpressionToWrap (ExpressionToWrap) {}
260
+ StringRef getFuncDef () const { return Buffer.str (); }
261
+ StringRef getFuncName () const {
262
+ return Buffer.substr (FuncNameStart, FuncNameEnd - FuncNameStart);
263
+ }
264
+ };
265
+
253
266
struct APIDiffMigratorPass : public ASTMigratorPass , public SourceEntityWalker {
254
267
255
268
APIDiffItemStore DiffStore;
@@ -328,20 +341,53 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
328
341
return false ;
329
342
}
330
343
331
- std::set<std::string> InsertedFunctions ;
344
+ std::vector<ConversionFunctionInfo> HelperFuncInfo ;
332
345
SourceLoc FileEndLoc;
346
+
333
347
APIDiffMigratorPass (EditorAdapter &Editor, SourceFile *SF,
334
348
const MigratorOptions &Opts):
335
349
ASTMigratorPass (Editor, SF, Opts), DiffStore(Diags),
336
- FileEndLoc (SM.getRangeForBuffer(BufferID).getEnd()) {
337
- SmallVector<Decl*, 16 > TopDecls;
338
- SF->getTopLevelDecls (TopDecls);
339
- for (auto *D: TopDecls) {
340
- if (auto *FD = dyn_cast<FuncDecl>(D)) {
341
- InsertedFunctions.insert (FD->getBaseName ().getIdentifier ().str ());
342
- }
350
+ FileEndLoc (SM.getRangeForBuffer(BufferID).getEnd()) {}
351
+
352
+ ~APIDiffMigratorPass () {
353
+ Editor.disableCache ();
354
+ SWIFT_DEFER { Editor.enableCache (); };
355
+
356
+ // Collect inserted functions to avoid re-insertion.
357
+ std::set<std::string> InsertedFunctions;
358
+ SmallVector<Decl*, 16 > TopDecls;
359
+ SF->getTopLevelDecls (TopDecls);
360
+ for (auto *D: TopDecls) {
361
+ if (auto *FD = dyn_cast<FuncDecl>(D)) {
362
+ InsertedFunctions.insert (FD->getBaseName ().getIdentifier ().str ());
343
363
}
344
364
}
365
+ for (auto &Cur: HelperFuncInfo) {
366
+ // Avoid wrapping nil expression.
367
+ if (isNilExpr (Cur.ExpressionToWrap ))
368
+ continue ;
369
+
370
+ // Avoid wrapping a single expression with multiple conversion functions.
371
+ auto count = std::count_if (HelperFuncInfo.begin (), HelperFuncInfo.end (),
372
+ [&] (ConversionFunctionInfo &Info) {
373
+ return Info.ExpressionToWrap ->getSourceRange () ==
374
+ Cur.ExpressionToWrap ->getSourceRange ();
375
+ });
376
+ if (count > 1 )
377
+ continue ;
378
+ assert (count == 1 );
379
+ auto FuncName = Cur.getFuncName ();
380
+
381
+ // Avoid inserting the helper function if it's already present.
382
+ if (!InsertedFunctions.count (FuncName)) {
383
+ Editor.insert (FileEndLoc, Cur.getFuncDef ());
384
+ InsertedFunctions.insert (FuncName);
385
+ }
386
+ Editor.insertBefore (Cur.ExpressionToWrap ->getStartLoc (),
387
+ (Twine (FuncName) + " (" ).str ());
388
+ Editor.insertAfterToken (Cur.ExpressionToWrap ->getEndLoc (), " )" );
389
+ }
390
+ }
345
391
346
392
void run () {
347
393
if (Opts.APIDigesterDataStorePaths .empty ())
@@ -737,12 +783,9 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
737
783
}
738
784
if (!Kind.hasValue ())
739
785
return false ;
740
- if (Kind && !isNilExpr (WrapperTarget)) {
741
- SmallString<256 > Buffer;
742
- auto Func = insertHelperFunction (*Kind, LeftComment, RightComment, Buffer,
743
- FromString);
744
- Editor.insert (WrapperTarget->getStartLoc (), (Twine (Func) + " (" ).str ());
745
- Editor.insertAfterToken (WrapperTarget->getEndLoc (), " )" );
786
+ if (Kind) {
787
+ insertHelperFunction (*Kind, LeftComment, RightComment, FromString,
788
+ WrapperTarget);
746
789
}
747
790
if (!Rename.empty ()) {
748
791
replaceExpr (Reference, Rename);
@@ -751,8 +794,6 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
751
794
}
752
795
753
796
bool handleAssignDestMigration (Expr *E) {
754
- Editor.disableCache ();
755
- SWIFT_DEFER { Editor.enableCache (); };
756
797
auto *ASE = dyn_cast<AssignExpr>(E);
757
798
if (!ASE || !ASE->getDest () || !ASE->getSrc ())
758
799
return false ;
@@ -771,14 +812,16 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
771
812
return wrapAttributeReference (E, E, false );
772
813
}
773
814
774
- StringRef insertHelperFunction (NodeAnnotation Anno, StringRef RawType,
775
- StringRef NewType,
776
- SmallString<256 > &Buffer, bool FromString) {
777
- llvm::raw_svector_ostream OS (Buffer);
815
+ void insertHelperFunction (NodeAnnotation Anno, StringRef RawType,
816
+ StringRef NewType, bool FromString,
817
+ Expr *Wrappee) {
818
+ HelperFuncInfo.emplace_back (Wrappee);
819
+ ConversionFunctionInfo &Info = HelperFuncInfo.back ();
820
+ llvm::raw_svector_ostream OS (Info.Buffer );
778
821
OS << " \n " ;
779
822
OS << " // Helper function inserted by Swift 4.2 migrator.\n " ;
780
823
OS << " fileprivate func " ;
781
- unsigned FuncNameStart = Buffer.size ();
824
+ Info. FuncNameStart = Info. Buffer .size ();
782
825
OS << (FromString ? " convertTo" : " convertFrom" );
783
826
SmallVector<std::string, 8 > Segs;
784
827
StringRef guard = " \t guard let input = input else { return nil }\n " ;
@@ -835,24 +878,17 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
835
878
for (auto P: Parts)
836
879
OS << P;
837
880
OS << Segs[1 ];
838
- auto FuncName = Buffer.str ().substr (FuncNameStart);
839
- if (!InsertedFunctions.count (FuncName)) {
840
- if (FromString) {
841
- OS << " (_ input: " << Segs[2 ] << " ) -> " << Segs[3 ] << " {\n " ;
842
- OS << Segs[4 ] << " \n }\n " ;
843
- } else {
844
- OS << " (_ input: " << Segs[3 ] << " ) -> " << Segs[2 ] << " {\n " ;
845
- OS << Segs[5 ] << " \n }\n " ;
846
- }
847
- Editor.insert (FileEndLoc, OS.str ());
848
- InsertedFunctions.insert (FuncName);
881
+ Info.FuncNameEnd = Info.Buffer .size ();
882
+ if (FromString) {
883
+ OS << " (_ input: " << Segs[2 ] << " ) -> " << Segs[3 ] << " {\n " ;
884
+ OS << Segs[4 ] << " \n }\n " ;
885
+ } else {
886
+ OS << " (_ input: " << Segs[3 ] << " ) -> " << Segs[2 ] << " {\n " ;
887
+ OS << Segs[5 ] << " \n }\n " ;
849
888
}
850
- return FuncName;
851
889
}
852
890
853
891
void handleStringRepresentableArg (ValueDecl *FD, Expr *Arg, Expr *Call) {
854
- Editor.disableCache ();
855
- SWIFT_DEFER { Editor.enableCache (); };
856
892
NodeAnnotation Kind;
857
893
StringRef RawType;
858
894
StringRef NewAttributeType;
@@ -880,19 +916,14 @@ struct APIDiffMigratorPass : public ASTMigratorPass, public SourceEntityWalker {
880
916
if (AllArgs.size () <= ArgIdx)
881
917
return ;
882
918
WrapTarget = AllArgs[ArgIdx].ArgExp ;
883
- // Avoid wrapping nil literal.
884
- if (isNilExpr (WrapTarget))
885
- return ;
886
919
}
887
920
assert (WrapTarget);
888
- SmallString<256 > Buffer;
889
- auto FuncName = insertHelperFunction (Kind, RawType, NewAttributeType, Buffer,
890
- FromString);
891
- Editor.insert (WrapTarget->getStartLoc (), (Twine (FuncName) + " (" ).str ());
892
- Editor.insertAfterToken (WrapTarget->getEndLoc (), " )" );
921
+ insertHelperFunction (Kind, RawType, NewAttributeType, FromString, WrapTarget);
893
922
}
894
923
895
924
bool walkToExprPre (Expr *E) override {
925
+ if (E->getSourceRange ().isInvalid ())
926
+ return false ;
896
927
if (handleQualifiedReplacement (E))
897
928
return false ;
898
929
if (handleAssignDestMigration (E))
0 commit comments