Slide 1

Slide 1 text

0OUIF fl Z4VHHFTUJPOTPG 3FXSJUJOH.FUIPE%FQSFDBUJPOT  .BTBUP0ICB !PICBSZF  3VCZ,BJHJ SVCZLBJHJSVCZLBJHJ$

Slide 2

Slide 2 text

 4NBSU#BOL *OD &OHJOFFSJOH.BOBHFS4PGUXBSF&OHJOFFS .BTBUP0ICB !PICBSZF !PICBSZF

Slide 3

Slide 3 text

%PZPVSFNFNCFSIPXNBOZEFQSFDBUJPOXBSOJOHTZPVWFTFFO

Slide 4

Slide 4 text

5IJTNFBOTFWFSZPOFIFSF

Slide 5

Slide 5 text

4QFDJ fi DBMMZ QFPQMFJOUFSFTUFEJONFUIPEEFQSFDBUJPO

Slide 6

Slide 6 text

%&.0 IUUQTZPVUVCF5$BPINJ.*

Slide 7

Slide 7 text

%&.0 IUUQTZPVUVCFHU@,+6

Slide 8

Slide 8 text

 *OUSPEVDUJPO  %FQSFDBUJPO1SPCMFN0WFSWJFX  -FBSOJOHGSPN0UIFS-BOHVBHFT  %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT  'VUVSF1PTTJCJMJUJFT 0VUMJOF

Slide 9

Slide 9 text

%FQSFDBUJPO1SPCMFN0WFSWJFX

Slide 10

Slide 10 text

 5IF%FQSFDBUJPO1SPCMFN0WFSWJFX w "TPGUXBSFEFWFMPQNFOUQSBDUJDFUPQIBTFPVUPMEGFBUVSFT w *UTFSWFTBTBUSBOTJUJPOQFSJPECFUXFFOTVQQPSUJOHMFHBDZDPEFBOE SFNPWJOHJU w ,FZQVSQPTFT w 4JHOBMJOHQMBOOFESFNPWBMPGBGFBUVSF w &ODPVSBHJOHNJHSBUJPOUPOFXFSBMUFSOBUJWFT w "MMPXJOHHSBEVBMDPEFCBTFVQEBUFT 8IBUJTEFQSFDBUJPO

Slide 11

Slide 11 text

 5IF%FQSFDBUJPO1SPCMFN0WFSWJFX 5SBEJUJPOBMNFUIPEEFQSFDBUJPOUJNFMJOF W W W -JCSBSZ6TFS *NQMFNFOU old_method "EEnew_method %FQSFDBUFold_method 3FNPWF old_method 6TF old_method 4FFXBSOJOHTXIJMF VTJOHold_method $PEFCSFBLTVOMFTT VTJOHnew_method -JWFXJUI new_method W -JCSBSZ"VUIPS 5SBOTJUJPOQFSJPE 1BJOPGNBOVBMDPEFVQEBUFT -JCSBSZBVUIPSTJODMVEFJUTMBOHVBHFEFWFMPQFST

Slide 12

Slide 12 text

 5IF%FQSFDBUJPO1SPCMFN0WFSWJFX 1BJOPGNBOVBMDPEFVQEBUFT 5JNFDPOTVNJOH ⏱ -BSHFDPEFCBTFTNBZIBWFIVOESFETPGEFQSFDBUFENFUIPEDBMMTUPVQEBUF &SSPSQSPOF πŸ’₯ .BOVBMTFBSDIBOESFQMBDFDBOJOUSPEVDFOFXCVHTBOEJODPOTJTUFODJFT %JTUSBDUJOH 😢🌫 5BLFTGPDVTBXBZGSPNDPSFEFWFMPQNFOUBOEOFXGFBUVSFT

Slide 13

Slide 13 text

 5IF%FQSFDBUJPO1SPCMFN0WFSWJFX %PDVNFOUBUJPO 3VOUJNFXBSOJOH 4UBUJD%ZOBNJDBOBMZTJT %FQSFDBUJPOIBOEMJOHJO3VCZFDPTZTUFN 1 2 3

Slide 14

Slide 14 text

 5IF%FQSFDBUJPO1SPCMFN0WFSWJFX %PDVNFOUBUJPOCBTFEBQQSPBDI 1 w 3&"%.&OPUJDFT w $)"/(&-0(FOUSJFT w :"3%!EFQSFDBUFEUBHT

Slide 15

Slide 15 text

 5IF%FQSFDBUJPO1SPCMFN0WFSWJFX 3VOUJNFXBSOJOH 2 w Warning Kernel#warnXJUI DBMMFSJOGPSNBUJPO w Gem :: Deprecate w ActiveSupport : : Deprecation

Slide 16

Slide 16 text

 5IF%FQSFDBUJPO1SPCMFN0WFSWJFX 4UBUJD%ZOBNJDBOBMZTJT 3 w 3VCP$PQ w "VUPDPSSFDUTEFQSFDBUJPOT w %FQSFDBUJPO5PPMLJU w 3FDPSETEFQSFDBUJPOXBSOJOHT BUSVOUJNF IUUQTEPDTSVCPDPQPSHSVCPDPQDPQT@MJOUIUNMMJOUEFQSFDBUFEDMBTTNFUIPET IUUQTHJUIVCDPN4IPQJGZEFQSFDBUJPO@UPPMLJU

Slide 17

Slide 17 text

 5IF%FQSFDBUJPO1SPCMFN0WFSWJFX 8IBUXPVMEBOJEFBMEFQSFDBUJPOTZTUFNEP IUUQTBCPVUHJUMBCDPNCMPHIPXXFBVUPNBUJDBMMZ fi YFEIVOESFETPGSVCZEFQSFDBUJPOXBSOJOHT 5IFRVFTUJPO8IZBUSVOUJNF XJMMCFBOTXFSFEMBUFS %FUFDUJOHEFQSFDBUJPOTBUSVOUJNF  fi YJOHUIFN BVUPNBUJDBMMZXPVMECSJOHCFUUFSEFWFMPQFSFYQFSJFODF

Slide 18

Slide 18 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT

Slide 19

Slide 19 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT %J ff FSFOUQSPHSBNNJOHMBOHVBHFTIBOEMFEFQSFDBUJPOJOVOJRVFXBZT w warningsNPEVMF w EPDVNFOUBUJPO w TUBUJDBOBMZTJTUPPMT 1ZUIPO w @deprecatedUBH w DPNQJMFUJNFXBSOJOHT w DPEFNPET +4BTXFMM 5ZQF4DSJQU w @DeprecatedBOOPUBUJPO w +BWBEPD w *%&JOUFHSBUJPO +BWB w [Obsolete]BUUSJCVUF w 3PTMZOBOBMZ[FST w "VUP fi YFTJO*%& $ w  #[ deprecated]BUUSJCVUF w cargo fix GPSBVUPNBUFE VQEBUFT 3VTU #[ deprecated(since = "1.0.0", note = "U pub fn old_function() { println!("This function is deprecat } @Deprecated public void oldMeth System.out.prin } [Obsolete("Use NewMethod instead")] public Task OldMethod(string s) { } import warnings def old_method(): warnings.warn( "Use new_method", DeprecationWarning, stacklevel=2 ) return "oops"

Slide 20

Slide 20 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT &WPMVUJPOPGEFQSFDBUJPOIBOEMJOH 1 2 3 4 5 %PDVNFOUBUJPOPOMZ $PNNFOUT DIBOHFMPHTBOEHVJEFT 3VOUJNFXBSOJOHT 8BSOXIFODPEFSVOT 4UBUJDBOBMZTJT 'JOEJTTVFTXJUIUPPMT JODMVEJOHUZQFDIFDL *%&JOUFHSBUJPO 7JTVBMDVFTBOETVHHFTUFE fi YFT "VUPNBUFE fi Y "VUPNBUJDBMMZUSBOTGPSNTDPEF ? 'VUVSF 0OUIF fl Z DPEFSFXSJUJOH 5IFQPTJUJPOTPGFBDIMPHPBSFGPSJMMVTUSBUJPOQVSQPTFTPOMZBOENBZOPUBDDVSBUFMZSF fl FDUUIFBDUVBMTJUVBUJPO

Slide 21

Slide 21 text

0OFNPSFOPUBCMFMBOHVBHF

Slide 22

Slide 22 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT IUUQTQIBSPPSH IUUQTJOSJBIBMTDJFODFIBMEPDVNFOU

Slide 23

Slide 23 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT 1IBSPT%FQSFXSJUFS "VUPNBUJDBMMZSFXSJUFTDBMMFSTPGEFQSFDBUFENFUIPETBUSVOUJNF  CBTFEPOUSBOTGPSNBUJPOSVMFTEF fi OFECZMJCSBSZBVUIPST Logger >> log: aMessage [ "The deprecation definition" self deprecated: 'use #log:level: instead' transformWith: '`@rec log: `@argument' - > '`@rec log: `@argument level: #info'. "The body of the method" ^ self log: aMessage level: #info ]

Slide 24

Slide 24 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT 1IBSPT%FQSFXSJUFS %&.0 IUUQTZPVUVCFYR(5QY)N.

Slide 25

Slide 25 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT )PX1IBSPT%FQSFXSJUFSXPSLT "OOPUBUJPO 1 5IFEFQSFDBUFENFUIPEJTNBSLFEXJUI EFQSFDBUJPOBOEJUTSVOUJNF USBOTGPSNBUJPO &YFDVUJPO 2 %VSJOHQSPHSBNFYFDVUJPO UIF FYFDVUJPOPGUIFEFQSFDBUFENFUIPE SBJTFTBOFYDFQUJPO &YDFQUJPOIBOEMJOH 3 *UDBQUVSFTUIFFYDFQUJPO $BMMFSSFXSJUJOH 4 *UJEFOUJ fi FTDBMMTJUFTJOUIFDBMMJOH NFUIPEBOEJUSFXSJUFTUIFNFUIPEXJUI USBOTGPSNBUJPOSVMFT &YFDVUJPODPOUJOVFT 5 5IFIBMUFENFUIPEFYFDVUJPOJTSFTVNFE 5IFCPEZPGUIFEFQSFDBUFENFUIPEJT SFXSJUUFOJONPTUDBTFT 5IF fi HVSFXBTDSFBUFECBTFEPOSFGFSFODFTGSPNUIFQBQFSIUUQTJOSJBIBMTDJFODFIBMEPDVNFOU -JCSBSZ6TFS -JCSBSZ"VUIPS

Slide 26

Slide 26 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT 8IZBUSVOUJNF OPUTUBUJDBOBMZTJT 5IPTFFYBNQMFTBSFEFTDSJCFEJOUIFQBQFS $IBSBDUFSJTUJDTPG EZOBNJDUZQFEMBOHVBHF 4UBUJDBOBMZTJTUPPMTDBVTFFYDFTTJWFPSJOTV ff i DJFOU SFXSJUJOHDBOEJEBUFT &YJTUFODFPG )PNPOZNPVT.FUIPET *GCPUIMPHHJOHNBUIMJCSBSJFTIBWFMPHNFUIPE TUBUJD BOBMZTJTDPVMEOUEFUFSNJOFJGBQBSUJDVMBSMPHDBMM .FUIPE0WFSSJEJOH 5IFFYBNQMFPGJT/JMJO1IBSP XIJDIJTTFOUUJNFT BOEJNQMFNFOUFEJODMBTTFT

Slide 27

Slide 27 text

8IBUJGXFDPVMECSJOH 1IBSPTBQQSPBDIUP3VCZ

Slide 28

Slide 28 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT class Legacy def old_method(arg) # do old thing end def new_method(arg) # do new thing end end w .BJOUBJOTLegacyDMBTT w "EETnew_method w %FQSFDBUFTold_method -JCSBSZ"VUIPS -FUTTBZBMJCSBSZBVUIPS

Slide 29

Slide 29 text

 -FBSOJOHGSPN0UIFS-BOHVBHFT -JCSBSZ"VUIPS $VSSFOUBQQSPBDIFT Gem :: Deprecate class Legacy # @deprecated Use {#new_method} def old_method(arg) warn "Use #new_method instead" # do old thing end def new_method(arg) # do new thing end end class Legacy def old_method(arg) # do old thing end def new_method(arg) # do new thing end extend Gem : : Deprecate deprewrite :old_method, :new_method, 2025, 4 end :"3% warn

Slide 30

Slide 30 text

class Legacy def old_method(arg) # do old thing end def new_method(arg) # do new thing end extend Deprewriter deprewrite :old_method, to: "new_method( {{ arguments } } )" end  -FBSOJOHGSPN0UIFS-BOHVBHFT w %FDMBSFUBSHFUUPSFXSJUF w %FDMBSFUSBOTGPSNBUJPOSVMF -JCSBSZ"VUIPS 6TF%FQSFXSJUFS πŸ’‘

Slide 31

Slide 31 text

--- ./script.rb +++ ./script.rb @@ -37,6 +37,6 @@ legecy = Legacy.new -legecy.old_method(arg) +legecy.new_method(arg)  -FBSOJOHGSPN0UIFS-BOHVBHFT legacy = Legacy.new legacy.old_method(arg) -JCSBSZ6TFS 3VOVTFSDPEF UIFOHFU fi YFTPSTVHHFTUJPOT MPHHJOH EJ ff  fi MFT BQQMZJNNFEJBUFMZ %FQSFXSJUFSJEFOUJ fi FTDPEFUPCFSFXSJUUFOBUSVOUJNFBOESFXSJUFT PSPVUQVUTTVHHFTUJPOTUPSFXSJUF

Slide 32

Slide 32 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT

Slide 33

Slide 33 text

%FTJHO%FQSFXSJUFSJO3VCZ /PUF'SPNUIJTQPJOUGPSXBSE *XJMMSFGFSUPUIFJNQMFNFOUBUJPO PG3VCZCZUIFTQFBLFSBT%FQSFXSJUFS

Slide 34

Slide 34 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT 5PSFDBQ1IBSPT%FQSFXSJUFSXPSL fl PX "OOPUBUJPO 1 &YFDVUJPO 2 &YDFQUJPOIBOEMJOH 3 -JCSBSZ"VUIPS -JCSBSZ6TFS $BMMFSSFXSJUJOH &YFDVUJPODPOUJOVFT 5 4

Slide 35

Slide 35 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT )PXUPJNQMFNFOUB%FQSFXSJUFSJO3VCZ "OOPUBUJPO 1 &YFDVUJPO 2 &YDFQUJPOIBOEMJOH 3 -JCSBSZ6TFS $BMMFSSFXSJUJOH &YFDVUJPODPOUJOVFT 5 4 "VUIPSTOFFEUPBEE JUUPEFQFOEFODZ 3VCZQSPWJEFTNFUIPEJOUFSDFQUJPO XBZXJUIPVUFYDFQUJPO /FFEUP fi OEDBMMFSMPDBUJPOXJUISPX OVNCFSIPSJ[POUBMQPTJUJPO -JCSBSZ"VUIPS

Slide 36

Slide 36 text

"OOPUBUF USBOTGPSNBUJPOSVMFT 2  %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT %FQSFXSJUFSTDPNQMFUFXPSL fl PXJO3VCZ -JCSBSZ"VUIPS -JCSBSZ6TFS "EE%FQSFXSJUFSUP EFQFOEFODZ 1     DBOCFEPOFCZMJCSBSZVTFST*UTJEFBMUPEF fi OFCZBVUIPST πŸ€”)PXUPXSJUFUSBOTGPSNBUJPOSVMFT πŸ€”*TSFXSJUJOHDPEFBUSVOUJNFTBGF πŸ€”8JMMUIF3VCZFDPTZTUFNBEPQUJU πŸ€”)PXUPUSBOTGPSNDPEF &YFDVUFVTFSDPEF FOBCMJOH%FQSFXSJUFS 3 %FQSFDBUFENFUIPEDBMM USJHHFSTJOUFSDFQUJPO 4 'JOEFYBDUDBMMFS MPDBUJPO 4 5SBOTGPSNDBMMFSDPEF CBTFEPOSVMFT 5 $IBOHFTBSFSFQPSUFE BQQMJFE 6 0SJHJOBMNFUIPE FYFDVUJPODPOUJOVFT 7

Slide 37

Slide 37 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $IBMMFOHFTPG%FQSFXSJUFS 1 2 3 4 )PXUPXSJUFUSBOTGPSNBUJPOSVMFT  )PXUPUSBOTGPSNDPEF  *TSFXSJUJOHDPEFBUSVOUJNFTBGF  8JMMUIF3VCZFDPTZTUFNBEPQUJU *NQMFNFOUBUJPO$PODFSOT &DPTZTUFNXJEF$PODFSOT

Slide 38

Slide 38 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $IBMMFOHFTPG%FQSFXSJUFS 1 2 3 4 )PXUPXSJUFUSBOTGPSNBUJPOSVMFT  )PXUPUSBOTGPSNDPEF  *TSFXSJUJOHDPEFBUSVOUJNFTBGF  8JMMUIF3VCZFDPTZTUFNBEPQUJU πŸ€” *NQMFNFOUBUJPO$PODFSOT &DPTZTUFNXJEF$PODFSOT

Slide 39

Slide 39 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT # @param method_name [Symbol] The name of the method to deprecate # @param from [String, nil] Pattern to match for transformation # @param to [String] Pattern to transform to def deprewrite: (Symbol method_name, to: String, ?from: String?) -> void Deprewriter.deprewriteTJHOBUVSF deprewrite :old_method, from: ".call_node[name=old_method]", to: "new_method( {{ arguments } } )" &YBNQMF fromJTBOPQUJPOBMBSHVNFOUUPTUSJDUMZ fi MUFSBDBMMOPEF )PXUPXSJUFUSBOTGPSNBUJPOSVMFT 1

Slide 40

Slide 40 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT 4ZOWFSU IUUQTTZOWFSUOFU IUUQTSVCZLBJHJPSHQSFTFOUBUJPO43JDIBSE)VBOH )PXUPXSJUFUSBOTGPSNBUJPOSVMFT 1

Slide 41

Slide 41 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT w "45CBTFE3VCZDPEFUSBOTGPSNBUJPOUPPM w 1SPWJEFTQBSTFSPQUJPOT JODMVEJOH1SJTN w &YUSBDUTJUTJOUFSOBMJNQMFNFOUBUJPOJOUPTFQBSBUFHFNT w IUUQTHJUIVCDPNTZOWFSUIROPEFRVFSZSVCZ w IUUQTHJUIVCDPNTZOWFSUIROPEFNVUBUJPOSVCZ 4ZOWFSU *EFDJEFEUPBEPQU4ZOWFSUTZOUBYBTUSBOTGPSNBUJPOSVMF from, to )PXUPXSJUFUSBOTGPSNBUJPOSVMFT 1

Slide 42

Slide 42 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT NodeMutation :: PrismAdapterFYBNQMF adapter = NodeMutation :: PrismAdapter.new replacement = "new_method( {{ arguments.arguments.0 }} :, {{ arguments.arguments.1 }} :)" original_code = "old_method(arg1, arg2)" call_node = Prism.parse(original_code).value.statements.body.first new_code = adapter.rewritten_source(call_node, replacement) # => "new_method(arg1:, arg2:)" )PXUPXSJUFUSBOTGPSNBUJPOSVMFT 1

Slide 43

Slide 43 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT NodeMutation :: PrismAdapterFYBNQMF adapter = NodeMutation :: PrismAdapter.new replacement = "new_method( {{ arguments.arguments.0 }} :, {{ arguments.arguments.1 }} :)" original_code = "old_method(arg1, arg2)" call_node = Prism.parse(original_code).value.statements.body.first new_code = adapter.rewritten_source(call_node, replacement) # => "new_method(arg1:, arg2:)" $PEFUSBOTGPSNBUJPOJTQPTTJCMFJGXFQBTTBO"45OPEF )PXUPXSJUFUSBOTGPSNBUJPOSVMFT 1

Slide 44

Slide 44 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $IBMMFOHFTPG%FQSFXSJUFS 1 2 3 4 )PXUPXSJUFUSBOTGPSNBUJPOSVMFT  )PXUPUSBOTGPSNDPEF  *TSFXSJUJOHDPEFBUSVOUJNFTBGF  8JMMUIF3VCZFDPTZTUFNBEPQUJU βœ… πŸ€” *NQMFNFOUBUJPO$PODFSOT &DPTZTUFNXJEF$PODFSOT

Slide 45

Slide 45 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT class Legacy def old_method(arg) # do old thing end def new_method(arg) # do new thing end extend Deprewriter deprewrite :old_method, to: "new_method( {{ arguments }} )" end 8IBUIBQQFOTPOVTJOHdeprewrite )PXUPUSBOTGPSNDPEF 2

Slide 46

Slide 46 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT def deprewrite(method_name, to:, from: nil) class_eval do old = "_deprecated_ #{ method_name}" alias_method old, method_name define_method method_name do |*args, &block| # Transformation logic here send old, *args, &block end end end .FUIPEDBMMJOUFSDFQUJPO w 4BNFUFDIOJRVFBT Gem :: Deprecate. deprecate w 1SFTFSWFPSJHJOBM NFUIPECFIBWJPSUP SFTVNFMBUFS IUUQTEPDTSVCZMBOHPSHFONBTUFS(FN%FQSFDBUFIUNM )PXUPUSBOTGPSNDPEF 2

Slide 47

Slide 47 text

def deprewrite(method_name, to:, from: nil) class_eval do old = "_deprecated_ #{ method_name}" alias_method old, method_name define_method method_name do |*args, &block| filepath, line = Gem.location_of_caller source = File.read(filepath) # Transformation logic here send old, *args, &block end end end  %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT (FU fi MFQBUIBOESFBEUIF fi MFUPEFUFDUBDBMMTJUF )PXUPUSBOTGPSNDPEF 2

Slide 48

Slide 48 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT (FUPrism :: CallNodeXJUIDBMMFSsourceUPCFUSBOTGPSNFE IUUQTEPDTSVCZMBOHPSHFONBTUFS1SJTN7JTJUPSIUNM class CallSiteFinder < Prism :: Visitor def initialize(method_name, line, from: nil) # Set instance variables end # @param source [String] source code to search def find(source) parsed_result = Prism.parse(source) parsed_result.value.statements.accept(self) @node # @return [Prism :: CallNode] end def visit_call_node(node) # Find call node here end end )PXUPUSBOTGPSNDPEF 2

Slide 49

Slide 49 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT Prism :: CallNode IUUQTEPDTSVCZMBOHPSHFONBTUFS1SJTN$BMM/PEFIUNM legacy = Legacy.new result = legacy.old_method(1, 2) do |a| # block arg end do_something(with: result) DBMMOPEFPG #old_method )PXUPUSBOTGPSNDPEF 2

Slide 50

Slide 50 text

class CallSiteFinder < Prism :: Visitor def initialize(method_name, line, from: nil) @node_query = from ? NodeQuery.new(from, adapter: :prism) : nil end def visit_call_node(node) if @node_query matched = @node_query.query_nodes(node) @node = matched.first if matched.any? else @node = node end end end  %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT IUUQTHJUIVCDPNTZOWFSUIROPEFRVFSZSVCZ 6UJMJ[FOPEFRVFSZSVCZUPTUSJDUMZ fi OEDBMMOPEF deprewrite :old_method, from: ".call_node[name=old_method]", to: "new_method( {{ arguments }} )" %FUFDUJOHNFUIPEDBMMTJUFT )PXUPUSBOTGPSNDPEF 2

Slide 51

Slide 51 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $PEFUSBOTGPSNBUJPO class Transformer def initialize(source, node, transform_with) # Set instance variables end def transform # @return [String] return @source if @node.nil? before_node = @source[0 . .. @node.location.start_offset] new_code = transform_call_node after_node = @source[@node.location.end_offset .. ] before_node + new_code + after_node end end )PXUPUSBOTGPSNDPEF 2

Slide 52

Slide 52 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $PEFUSBOTGPSNBUJPO class Transformer def initialize(source, node, transform_ # Set instance variables end def transform return @source if @node.nil? before_node = @source[0 .. . @node.locat new_code = transform_call_node after_node = @source[@node.location.e .. before_node + new_code + after_node end end legacy = Legacy.new result = legacy.old_method(1, 2) do |a| # block arg end do_something(with: result) *UUSBOTGPSNTPOMZDBMMOPEF  BOEQSFTFSWFTTVSSPVOEJOHDPEFDPOUFYU )PXUPUSBOTGPSNDPEF 2

Slide 53

Slide 53 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $PEFUSBOTGPSNBUJPO IUUQTHJUIVCDPNTZOWFSUIROPEFNVUBUJPOSVCZ class Transformer def transform_call_node adapter = NodeMutation :: PrismAdapter.new receiver_code = @node.receiver ? " #{ @node.receiver.slice}." : "" call_node = Prism.parse(@node.slice.gsub(receiver_code, "")). value.statements.body.first receiver_code + adapter.rewritten_source(call_node, @transform_with) end end 6UJMJ[FOPEFNVUBUJPOSVCZUPUSBOTGPSNDBMMOPEF deprewrite :old_method, from: ".call_node[name=old_method]", to: "new_method( {{ arguments }} )" 4FUBT@transform_with )PXUPUSBOTGPSNDPEF 2

Slide 54

Slide 54 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $PEFUSBOTGPSNBUJPO legacy = Legacy.new result = legacy.old_method(1, 2) do |a| # block arg end do_something(with: result) legacy = Legacy.new result = legacy.new_method(1, 2) do |a| # block arg end do_something(with: result) 5IJT NFUIPESFOBNJOH JTUIFTJNQMFTUEFQSFDBUJPOQBUUFSO )PXUPUSBOTGPSNDPEF 2

Slide 55

Slide 55 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT .BKPSEFQSFDBUJPOTDFOBSJPT 3FOBNFNFUIPE 5IFNPTUDPNNPOSFGBDUPSJOHPQFSBUJPO βœ… "EEBSHVNFOU T "EEJOHOFXQBSBNFUFSTUPBNFUIPE βœ… 3FNPWFBSHVNFOU T 3FNPWJOHQBSBNFUFSTUIBUBSFOPMPOHFSOFFEFE βœ… $IBOHFBSH T UZQF $POWFSUJOHBSHUZQFTXJUIPVUDIBOHJOHNFUIPEOBNF ❌ $IBOHFSFDFJWFS .PWJOHNFUIPEGSPNPOFPCKFDUUPBOPUIFSPCKFDU ❌ %FMFUFNFUIPE 8JUIPVUBOZSFQMBDFNFOU ❌ *NQMFNFOUBUJPO 4UBUVT )PXUPUSBOTGPSNDPEF 2 'FBUVSFGVODUJPOBMJUZEFQSFDBUJPOBMTPFYJTUT5IJTJTPVUPGTDPQFGPSUIJTQSFTFOUBUJPO

Slide 56

Slide 56 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $IBMMFOHFTPG%FQSFXSJUFS 1 2 3 4 )PXUPXSJUFUSBOTGPSNBUJPOSVMFT  )PXUPUSBOTGPSNDPEF  *TSFXSJUJOHDPEFBUSVOUJNFTBGF  8JMMUIF3VCZFDPTZTUFNBEPQUJU βœ… βœ… πŸ€” *NQMFNFOUBUJPO$PODFSOT &DPTZTUFNXJEF$PODFSOT

Slide 57

Slide 57 text

/P NBZCF

Slide 58

Slide 58 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT w *UIPVHIUPGUXPBQQSPBDIFT w 3FXSJUFUIFDBMMFS fi MFEJSFDUMZBOEMPBEUIF fi MF w 3FEF fi OFUIFDBMMFSNFUIPEXJUIBNPOLFZQBUDI w #VU XIPXBOUTUPSFXSJUFDPEFPOQSPEVDUJPOBUSVOUJNF  w %FQSFXSJUFSJTTVQQPTFEUPCFBDUJWBUFEJOUFTUPSMPDBM FOWJSPONFOU 3FXSJUJOHDPEFBUSVOUJNFNBZCFOPUTBGF *TSFXSJUJOHDPEFBUSVOUJNFTBGF 3

Slide 59

Slide 59 text

--- ./script.rb +++ ./script.rb @@ -37,6 +37,6 @@ legecy = Legacy.new -legecy.old_method +legecy.new_method  %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT 1SPWJEFNPEFTUPIBOEMFSFXSJUUFODPEF -PH.PEF 4IPXXBSOJOHTXJUI TVHHFTUFEDIBOHFT %J ff .PEF (FOFSBUFQBUDI fi MFTUPCF BQQMJFE 3FXSJUF.PEF "VUPNBUJDBMMZVQEBUF TPVSDF fi MFT *TSFXSJUJOHDPEFBUSVOUJNFTBGF 3

Slide 60

Slide 60 text

-PH.PEF %&.0 IUUQTZPVUVCF9SH+[+I

Slide 61

Slide 61 text

%J ff .PEF %&.0 IUUQTZPVUVCFWVDU#961[

Slide 62

Slide 62 text

%J ff .PEF 5IJTJEFBXBTPSJHJOBMMZTVHHFTUFECZNZDPMMFBHVF !PTZPZV5IBOLT

Slide 63

Slide 63 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT &YQFDUFEVTBHF NPEF EFTDSJQUJPO FOWJSPONFOU -PH 4IPXXBSOJOHTXJUITVHHFTUFEDIBOHFT TUBHJOH %J f (FOFSBUFQBUDI fi MFTGPSSFWJFX MPDBM UFTU 3FXSJUF "VUPNBUJDBMMZVQEBUFTPVSDF fi MFT MPDBM UFTU *TSFXSJUJOHDPEFBUSVOUJNFTBGF 3

Slide 64

Slide 64 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT )PXUPHFOFSBUFEJ ff GPSMPHEJ ff NPEFT class Deprewriter :: Diff def to_s original_diff = Diffy :: Diff.new( @source, @rewritten_source, include_diff_info: true, diff: "-u").to_s formatted_timestamp = @timestamp.strftime("%Y-%m-%d %H:%M:%S.%N %z") header = [ " - -- #{ @filepath}\t #{ formatted_timestamp}", " + ++ #{ @filepath}\t #{ formatted_timestamp}" ].join("\n") [header, original_diff.lines[2 .. ].join].join("\n") end end IUUQTHJUIVCDPNTBNHEJ ff Z --- ./script.rb +++ ./script.rb @@ -37,6 +37,6 @@ legecy = Legacy.new -legecy.old_method +legecy.new_method (FOFSBUFEJ ff  *TSFXSJUJOHDPEFBUSVOUJNFTBGF 3

Slide 65

Slide 65 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $IBMMFOHFTPG%FQSFXSJUFS 1 2 3 4 )PXUPXSJUFUSBOTGPSNBUJPOSVMFT  )PXUPUSBOTGPSNDPEF  *TSFXSJUJOHDPEFBUSVOUJNFTBGF  8JMMUIF3VCZFDPTZTUFNBEPQUJU βœ… βœ… βœ… πŸ€” *NQMFNFOUBUJPO$PODFSOT &DPTZTUFNXJEF$PODFSOT

Slide 66

Slide 66 text

"OOPUBUF USBOTGPSNBUJPOSVMFT 2  %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT -JCSBSZ"VUIPS -JCSBSZ6TFS "EE%FQSFXSJUFSUP EFQFOEFODZ 1 &YFDVUFVTFSDPEF FOBCMJOH%FQSFXSJUFS 3 %FQSFDBUFENFUIPEDBMM USJHHFSTJOUFSDFQUJPO 4 'JOEFYBDUDBMMFS MPDBUJPO 4 5SBOTGPSNDBMMFSDPEF CBTFEPOSVMFT 5 $IBOHFTBSFSFQPSUFE BQQMJFE 6 0SJHJOBMNFUIPE FYFDVUJPODPOUJOVFT 7 5PSFDBQ%FQSFXSJUFSTDPNQMFUFXPSL fl PX 8JMMUIF3VCZFDPTZTUFNBEPQUJU 4 5IJTQBSUJTIBSE

Slide 67

Slide 67 text

6TFSDPEF -JCSBSZDPEF  %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT *EFBM fl PX -JCSBSZ6TFST -JCSBSZ"VUIPS %FQSFDBUJPOXJUI USBOTGPSNBUJPOSVMFT "VUPNBUJDBMMZVQEBUFDPEFXJUI USBOTGPSNBUJPOSVMFT 4IJQHFNTJODMVEJOH%FQSFXSJUFS BOEJUTUSBOTGPSNBUJPOSVMFT 6TFSDPEF 6TFSDPEF 6TF 8JMMUIF3VCZFDPTZTUFNBEPQUJU 4

Slide 68

Slide 68 text

-JCSBSZDPEF  %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $PNQSPNJTFE fl PX -JCSBSZ"VUIPS 4IJQHFNTXJUIPVU%FQSFXSJUFS 6TFSDPEF -JCSBSZ6TFST "VUPNBUJDBMMZVQEBUFDPEFXJUI USBOTGPSNBUJPOSVMFT 6TFSDPEF 6TFSDPEF &BDIVTFSJOTUBMM%FQSFXSJUFS BOEXSJUFTUSBOTGPSNBUJPOSVMFT πŸ’¦ πŸ’¦ πŸ’¦ 6TF 8JMMUIF3VCZFDPTZTUFNBEPQUJU 4

Slide 69

Slide 69 text

6TFSDPEFXJUI%FQSFXSJUFS 8SJUFBSVMFXJUIBNPOLFZQBUDI -JCSBSZDPEFXJUIPVU%FQSFXSJUFS /PUIJOHDIBOHFT  %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $PNQSPNJTFE fl PX class Legacy def old_method(arg) # do old thing end def new_method(arg) # do new thing end end require "deprewriter" class Legacy extend Deprewriter deprewrite :old_method, to: "new_method( {{ arguments } } )" end 8JMMUIF3VCZFDPTZTUFNBEPQUJU 4

Slide 70

Slide 70 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT w %FQSFXSJUFSJTKVTUBUIJSEQBSUZHFN OPUBMBOHVBHFCVJMUJO GFBUVSF w *UTOPUSFBMJTUJDUPGPSDFBMMMJCSBSZBVUIPSTUPVTFJU w "UUIJTTUBHF NPTUVTFDBTFTXJMMCFGPSVTFSTUPJOTUBMMUIF EFQSFXSJUFSUIFNTFMWFTBOEXSJUFUIFJSPXOUSBOTGPSNBUJPO SVMFT 8JMMUIF3VCZFDPTZTUFNBEPQUJU 8JMMUIF3VCZFDPTZTUFNBEPQUJU 4

Slide 71

Slide 71 text

 %FQSFXSJUFS3VCZ*NQMFNFOUBUJPO%FUBJMT $IBMMFOHFTPG%FQSFXSJUFS 1 2 3 4 )PXUPXSJUFUSBOTGPSNBUJPOSVMFT  )PXUPUSBOTGPSNDPEF  *TSFXSJUJOHDPEFBUSVOUJNFTBGF  8JMMUIF3VCZFDPTZTUFNBEPQUJU βœ… βœ… βœ… ❌ *NQMFNFOUBUJPO$PODFSOT &DPTZTUFNXJEF$PODFSOT

Slide 72

Slide 72 text

 'VUVSF1PTTJCJMJUJFT

Slide 73

Slide 73 text

 'VUVSF1PTTJCJMJUJFT w $BOUSFXSJUFDPNQMFYNFUIPE DBMMT NFUBQSPHSBNNJOHFUD  w /PUF ffi DJFOU3FXSJUJOHSVOT FWFSZUJNFXIFOBEFQSFDBUFE NFUIPEJTDBMMFE w /PUTUBOEBMPOF EFQFOETPO OPOTUBOEBSE3VCZMJCSBSJFT $VSSFOUMJNJUBUJPOT 5IFQBUIGPSXBSE w )BOEMFNPSFDPNQMFYNFUIPE DBMMT w 0QUJNJ[FCZTLJQQJOH QSPDFTTJOHPOTVCTFRVFOU NFUIPEDBMMTBGUFSUIF fi STUDBMM w #FTUBOEBMPOFCZSFEVDJOH EFQFOEFODJFT ➑

Slide 74

Slide 74 text

 'VUVSF1PTTJCJMJUJFT w 8IBUJG3VCZDPSFIBTBGFBUVSFMJLF %FQSFXSJUFSBOETIJQTJUBTCVJMUJO  w 'BTUFSSFTPMWJOHEFQSFDBUJPOTJNQSPWFT EFWFMPQFSFYQFSJFODFPGCPUIMJCSBSZBVUIPST BOEVTFST &DPTZTUFNXJEFBEPQUJPOQPUFOUJBM 8IFOFBDIMJCSBSZBOE3VCZDPSFDBOFWPMWFGBTUFS  UIFFOUJSF3VCZFDPTZTUFNBEWBODFTGBTUFS

Slide 75

Slide 75 text

On-the- fl y Suggestions of
 Rewriting Method Deprecations Masato Ohba (@ohbarye)

Slide 76

Slide 76 text

"QQFOEJY

Slide 77

Slide 77 text

 "QQFOEJY w %FQSFXSJUFSJO3VCZ w IUUQTHJUIVCDPNPICBSZFEFQSFXSJUFSSVCZ w 1IBSP w IUUQTQIBSPPSH w %FQSFXSJUFS0OUIF fl ZSFXSJUJOHNFUIPEEFQSFDBUJPOT   w IUUQTJOSJBIBMTDJFODFIBMEPDVNFOU w %FQ.JOFS"VUPNBUJD3FDPNNFOEBUJPOPG5SBOTGPSNBUJPO3VMFTGPS.FUIPE %FQSFDBUJPO   w IUUQTSNPE fi MFTMJMMFJOSJBGS5FBN5FYUT1BQFST;BJUB*$43%FQSFXSJUFSQEG

Slide 78

Slide 78 text

 "QQFOEJY w 4ZOWFSU w IUUQTTZOWFSUOFU w IUUQTHJUIVCDPNTZOWFSUIROPEFRVFSZSVCZ w IUUQTHJUIVCDPNTZOWFSUIROPEFNVUBUJPOSVCZ w IUUQTSVCZLBJHJPSHQSFTFOUBUJPO43JDIBSE)VBOH w %J ff Z w IUUQTHJUIVCDPNTBNHEJ ff Z w )PXXFBVUPNBUJDBMMZ fi YFEUIPVTBOETPG3VCZEFQSFDBUJPOXBSOJOHT   w IUUQTBCPVUHJUMBCDPNCMPHIPXXFBVUPNBUJDBMMZ fi YFEIVOESFETPGSVCZEFQSFDBUJPOXBSOJOHT w %FQSFDBUJPO5PPMLJU w IUUQTHJUIVCDPNTIPQJGZEFQSFDBUJPO@UPPMLJU w IUUQTTIPQJGZFOHJOFFSJOHJOUSPEVDJOHUIFEFQSFDBUJPOUPPMLJU w 5IF$PNQMFUF(VJEFGPS%FQSFDBUJPO8BSOJOHTJO3BJMT   w IUUQTXXXGBTUSVCZJPCMPHSBJMTVQHSBEFTEFQSFDBUJPOXBSOJOHTSBJMTHVJEFIUNM