Slide 1

Slide 1 text

3VCP$PQ-41BOE1SJTN ,PJDIJ*50&4. *OD 3VCZ,BJHJ Towards Smarter and Faster .BZ UI /")"$6-563"-"355)&"5&3/")"SU

Slide 2

Slide 2 text

!LPJD w 044QSPHSBNNFS w 3VCP$PQDPSFUFBN w &OHJOFFSJOH.BOBHFSBOE %JTUJOHVJTIFE&OHJOFFSPG&4. *OD w 3VCZ,BJHJTQFBLFSBU -5 5BLFPVU 5BLFPVU BOE

Slide 3

Slide 3 text

.BJOUBJO044&WFSZ%BZ IUUQTHJUIVCDPNLPJD

Slide 4

Slide 4 text

&4. *OD BHJMFFTNDPKQ

Slide 5

Slide 5 text

4 Q FBLFS 4QFBLFSTBOE"UUFOEFFT 4 Q FBLFS -5 , BSBPLF !LPJD !IBSVHVDIJZVNB !KVOL !4)(".&-*/,4 !GVHBLLCO !NIJSBUB !TGKXS !UIBUB !LBTVNJQPO !XBJEPJ

Slide 6

Slide 6 text

1SJTNBOE-SBNB 3VCP$PQ -41BOE1SJTN 'SPN-"-3UP*&-3 "-SBNBT/FYU4UFQ

Slide 7

Slide 7 text

4QPOTPSFECZ&4. *OD BU 🚒 🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊🌊 🌊🌊🌊🌊🌊 🐬 🐳 /JHIU$SVJTFπŸ›³β›±πŸΊ 5POEPDIP /BIB 0LJOBXB 8&45."3*/& 5VF.BZBU%FQBSUVSF 4FFZPVOFYUUJNF Day 0 5IF&WFOUXBT40-%065

Slide 8

Slide 8 text

Support OSS community

Slide 9

Slide 9 text

w !LPJD1BSTFSHFNDPNNJUUFS w !KVOL-SBNBDPNNJUUFS w !4)(".&-*/,4QBSTFZDPOUSJCVUPS w !GVHBLLCO3#4DPOUSJCVUPS w .FNCFST8BOUFE 1BSTFS$MVC IUUQTNBHB[JOFSVCZJTUOFUBSUJDMFT'PMMPX6Q,JSJTIJNB3VCZIUNM ίΰΈˆΥ²ΰ©³Ψ«έšΪ€ΰ·¦

Slide 10

Slide 10 text

πŸ—Ύ +PJOVT w-FUTIBDLUPHFUIFS w:PVDBOXPSL SFNPUFMZGSPN BOZXIFSFJO+BQBO w4FFBHJMFFTNDPKQ

Slide 11

Slide 11 text

UIXPSL "OOJWFSTBSZ Trial Participant 0OMJOF"EWJTPS4FSWJDF Available Now NEXWAYΰΌ·Ν΄Ο„Ο₯ΠΞϧͰ ͝ڠྗ͍͍͓ͨͩͯΓ·͒

Slide 12

Slide 12 text

No content

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

$POUFOUT **3VCP$PQBOE1SJTN *3VCP$PQBOE-41 Towards Smarter and Faster

Slide 15

Slide 15 text

Omen *3VCP$PQBOE-41

Slide 16

Slide 16 text

w *XBTOURVJUFTVSFXIBU-41XBT TP*XBTUIJOLJOHPGUSZJOHUPDSFBUFPOF w 5IF4UBOEBSEHFNTVQQPSUT-41 CZ!XJMM w "U3VCZ,BJHJ UIFSFXBTBEJTDVTTJPO XJUI+VTUJO4FBSMTBCPVUUIFJEFBPGIBWJOH TPNFUIJOHTJNJMBSJO3VCP$PQ .PUJWBUJPO#BDLHSPVOE

Slide 17

Slide 17 text

w 3VCZ TU w 3BJMT UI w 3VCP$PQ OE w -41 UI )JTUPSZ -41JTB3FMBUJWFMZ/FX5FDIOPMPHZ

Slide 18

Slide 18 text

74$PEFXJUI-41 3FBMUJNFEJBHOPTUJDT 1PJOUPVUUIFSBOHFPGUIFQSPCMFN $PNNBOEBCMFGSPNUIF$PNNBOE1BMFUUF

Slide 19

Slide 19 text

-BOHVBHF4FSWFS1SPUPDPM &NBDT 7JN 74$PEF 4UFFQ 3VCZ-41 3VCP$PQ $MJFOU 4FSWFS 1SPUPDPM JSON-RPC 1SPUPDPMTNFUIPETTVDIBTinitialize textDocument/formatting BOE workspace/executeCommandBSFBNPOHUIPTFEF fi OFEJOUIF-41

Slide 20

Slide 20 text

w "EEBEFGBVMU-41GPSCFUUFSFEJUPS*%& TVQQPSUJO3BJMT SBJMTSBJMT w 1SFGFS-41PWFSHJUIPPLTGPS-JOUFS SBJMTSBJMT 3BJMT4VQQPSUT-41

Slide 21

Slide 21 text

w 3VCZ-41 3VCZ-413BJMT Monolithic LSP w 3VCP$PQTCVJMUJO-41 w 4UBOEBSETCVJMUJO-41 w 4UFFQTCVJMUJO-41 w 5ZQF1SPGTCVJMUJO-41 3VCZT-41TBSF$PNQPTBCMF Micro LSP

Slide 22

Slide 22 text

3VCP$PQTCVJMUJO-41 docs.rubocop.org/rubocop/usage/lsp.html w 3VCP$PQTCVJMUJO -41IBTCFFO TVQQPSUFETJODF BOESFRVJSFT B3VCZSVOUJNF *UJTFBTZUPVTF w /05&3VCZ-41 SFRVJSFT3VCZ SVOUJNF

Slide 23

Slide 23 text

SVCPDPQSVCPDPQ 4VQQPSUCVJMUJO-41TFSWFS rubocop --lsp

Slide 24

Slide 24 text

rubocop --lsp

Slide 25

Slide 25 text

+40/31$ [jsonrpc] D[15:18:14.117] Running language server: bundle exec rubocop --lsp [jsonrpc] e[15:18:14.118] --> initialize[1] {"jsonrpc":"2.0","id":1,"method":"initialize","params": {"processId":3303,"clientInfo":{"name":"Eglot","version":"1.17"},"rootPath":"/ Users/koic/src/github.com/rubocop/rubocop/","rootUri":"file:///Users/koic/src/ github.com/rubocop/rubocop","initializationOptions":{},"capabilities": {"workspace":{"applyEdit":true,"executeCommand": {"dynamicRegistration":false},"workspaceEdit": {"documentChanges":true},"didChangeWatchedFiles": {"dynamicRegistration":true},"symbol": {"dynamicRegistration":false},"configuration":true,"workspaceFolders":true},"te xtDocument":{"synchronization": {"dynamicRegistration":false,"willSave":true,"willSaveWaitUntil":true,"didSave" :true},"completion":{"dynamicRegistration":false,"completionItem": {"snippetSupport":false,"deprecatedSupport":true,"resolveSupport": {"properties":["documentation","details","additionalTextEdits"]},"tagSupport": {"valueSet":[1]}},"contextSupport":true},"hover": M-x eglot-events-buffer

Slide 26

Slide 26 text

1MVHJO*OUFSBDUTXJUI-41 w -41DMJFOUJTJNQMFNFOUFEBT BQMVHJOGPSFBDIFEJUPS w -41TFSWFSTUBSUTBQSPDFTT GPSFBDIQSPKFDU w -41TFSWFSQSPDFTTSFRVFTUT BOESFTQPOETUPUIF-41 DMJFOU -414FSWFS Request and Response &HMPU -414FSWFS &NBDT Request and Response 1MVHJO &EJUPS*%&

Slide 27

Slide 27 text

WTDPEFSVCPDPQ IUUQTHJUIVCDPNSVCPDPQWTDPEFSVCPDPQCMPCWTSDFYUFOTJPOUT-- w :PVDBOJOTUBMMUIJT74$PEF FYUFOTJPOGSPNUIF7JTVBM4UVEJP .BSLFUQMBDF w 'PS74$PEFCBTFE*%&TMJLF 74$PEJVNPS&DMJQTF5IFJB UIF FYUFOTJPODBOCFJOTUBMMFEGSPNUIF 0QFO7493FHJTUSZ

Slide 28

Slide 28 text

&YBNQMFTPG-41$MJFOU (require 'eglot) (add-to-list 'eglot-server-programs '(ruby-mode . ("bundle" "exec" "rubocop" "--lsp"))) (add-hook 'ruby-mode-hook (lambda () (add-hook 'before-save-hook 'eglot-format-buffer nil 'local))) { "languageserver": { "rubocop": { "command": "bundle", "args" : ["exec", "rubocop", "--lsp"], "filetypes": ["ruby"], "rootPatterns": [".git", "Gemfile"], "requireRootPattern": true } }, "coc.preferences.formatOnSave": true } &NBDT FHMPU ~/.eamcs.d/init.el 7JNBOE/FPWJN DPDOWJN ~/.config/nvim/coc-settings.json

Slide 29

Slide 29 text

*OTJEF-BOHVBHF4FSWFS rubocop --lsp

Slide 30

Slide 30 text

-41JT5SJHHFSFECZ1MVHJO w -41DMJFOUJTJNQMFNFOUFEBT BQMVHJOGPSFBDIFEJUPS w -41TFSWFSTUBSUTBQSPDFTT GPSFBDIQSPKFDU w -41TFSWFSQSPDFTTSFRVFTUT BOESFTQPOETUPUIF-41 DMJFOU -414FSWFS Request and Response -414FSWFS Request and Response 1MVHJO &EJUPS*%& &HMPU &NBDT

Slide 31

Slide 31 text

%FTJHOPG3VCP$PQT-41 Request (JSON-RPC) 3VCP$PQ 3VOOFS 3VCP$PQ-41 4FSWFS 3VCP$PQ-41 3PVUFT 3VCP$PQ-41 3VOUJNF Daemon 3VCP$PQ$-* $PNNBOE -41 rubocop --lsp TUBSU SVO P ff FOTFT GPSNBU XSJUF DBMM SFRVFTU EFMFHBUF P ff FOTFT OFX@UFYU +40/ Response (JSON-RPC) 1MVHJO &EJUPS*%&

Slide 32

Slide 32 text

3VOrubocop --lspWJB1MVHJO 3VCP$PQ$-* $PNNBOE -41 rubocop --lsp 1MVHJO &EJUPS*%&

Slide 33

Slide 33 text

Daemon rubocop --lsp4UBSUTB%BFNPO 3VCP$PQ$-* $PNNBOE -41 rubocop --lsp 1MVHJO &EJUPS*%& $ ps aux | grep rubocop user 7414 0.0 0.2 57716 4376 ?? Ss 4:48PM 0:02.13 rubocop --lsp path/to/rubocop IUUQTTQFBLFSEFDLDPNLPJDNBLFSVCPDPQTVQFSGBTU TMJEF

Slide 34

Slide 34 text

w 50%0Ξ«Ο₯Ρ਀ʁ 3VCP$PQ$-*$PNNBOE-41 module RuboCop class CLI module Command # Start Language Server Protocol of RuboCop. # @api private class LSP < Base self.command_name = :lsp def run RuboCop::LSP::Server.new(@config_store).start end end end $PEFTOJQQFU 3VOBTBEBFNPO $BMMFECZrubocop --lsp

Slide 35

Slide 35 text

Daemon 4UBSUUIF-414FSWFS 3VCP$PQ-41 4FSWFS rubocop --lsp TUBSU 1MVHJO &EJUPS*%& $ ps aux | grep rubocop user 7414 0.0 0.2 57716 4376 ?? Ss 4:48PM 0:02.13 rubocop --lsp path/to/rubocop 3VCP$PQ$-* $PNNBOE -41

Slide 36

Slide 36 text

-BOHVBHF4FSWFS1SPUPDPM IUUQTSVCZLBJHJPSHQSFTFOUBUJPOTNUTNGNIUNM "-BOHVBHF 4FSWFS1SPUPDPM 4%,GPS3VCZ

Slide 37

Slide 37 text

w 50%0Ξ«Ο₯Ρ਀ʁ 3VCP$PQ-414FSWFS LSP = LanguageServer::Protocol class RuboCop::LSP::Server def initialize(config_store) RuboCop::LSP.enable @reader = ::LSP::Transport::Io::Reader.new($stdin) @writer = ::LSP::Transport::Io::Writer.new($stdout) @runtime = RuboCop::LSP::Runtime.new(config_store) @routes = Routes.new(self) end end $PEFTOJQQFU LSPJTTIPSUGPSLanguageServer::Protocol &OBCMF-41DPOUFYU -41DMJFOUJOUFSBDUTWJBstdinBOEstdout

Slide 38

Slide 38 text

w 50%0Ξ«Ο₯Ρ਀ʁ 3VCP$PQ-414FSWFS class RuboCop::LSP::Server def start @reader.read do |request| if !request.key?(:method) @routes.handle_method_missing(request) elsif (route = @routes.for(request[:method])) route.call(request) else @routes.handle_unsupported_method(request) end rescue StandardError => e # snip end $PEFTOJQQFU 1SPDFTTBSFRVFTUNFUIPE 8BJUGPSstdinJOQVUVTJOH-41*0SFBEFS 5IFrequestWBSJBCMFJTBIBTI DPOWFSUFEGSPN+40/31$

Slide 39

Slide 39 text

Daemon 3FRVFTU +40/31$ $ ps aux | grep rubocop user 7414 0.0 0.2 57716 4376 ?? Ss 4:48PM 0:02.13 rubocop --lsp path/to/rubocop Request (JSON-RPC) 3VCP$PQ$-* $PNNBOE -41 rubocop --lsp TUBSU 3VCP$PQ-41 4FSWFS 1MVHJO &EJUPS*%&

Slide 40

Slide 40 text

Daemon 3PVUJOHCZ.FUIPE $ ps aux | grep rubocop user 7414 0.0 0.2 57716 4376 ?? Ss 4:48PM 0:02.13 rubocop --lsp path/to/rubocop Request (JSON-RPC) DBMM SFRVFTU 3VCP$PQ$-* $PNNBOE -41 rubocop --lsp TUBSU 3VCP$PQ-41 4FSWFS 1MVHJO &EJUPS*%& 3VCP$PQ-41 3PVUFT

Slide 41

Slide 41 text

w 50%0Ξ«Ο₯Ρ਀ʁ 3VCP$PQ-413PVUFT class RuboCop::LSP::Routes handle 'textDocument/didChange' do |request| doc = request[:params][:textDocument] result = diagnostic(doc[:uri], doc[:text]) @server.write(result) end handle 'textDocument/formatting' do |request| uri = request[:params][:textDocument][:uri] @server.write( id: request[:id], result: format_file(uri) ) end end 3FUSJFWFBGPSNBUUFEUFYUGSPN3VCP$PQ $PEFTOJQQFU (FUBSFTVMUPGEJBHOPTUJDGSPN3VCP$PQ

Slide 42

Slide 42 text

Daemon 3VO3VCP$PQ $ ps aux | grep rubocop user 7414 0.0 0.2 57716 4376 ?? Ss 4:48PM 0:02.13 rubocop --lsp path/to/rubocop Request (JSON-RPC) 3VCP$PQ 3VOOFS SVO P ff FOTFT GPSNBU XSJUF DBMM SFRVFTU EFMFHBUF 3VCP$PQ$-* $PNNBOE -41 rubocop --lsp TUBSU 3VCP$PQ-41 4FSWFS 1MVHJO &EJUPS*%& 3VCP$PQ-41 3PVUFT 3VCP$PQ-41 3VOUJNF

Slide 43

Slide 43 text

w 50%0Ξ«Ο₯Ρ਀ʁ 3VCP$PQ-413VOUJNF class RuboCop::LSP::Runtime def offenses(path, text) opts = {stdin: text, force_exclusion: true, formatters: ['json'], format: 'json'} json = redirect_stdout { run_rubocop(opts, path) } results = JSON.parse(json, symbolize_names: true) # snip end def run_rubocop(options, path) runner = RuboCop::Runner.new(options,@config_store) runner.run([path]) end $PEFTOJQQFU 3VOrubocopVTJOH3VOOFS"1* 3VOrubocop --stdin ... --format=json

Slide 44

Slide 44 text

Daemon 3FTQPOTF +40/31$ $ ps aux | grep rubocop user 7414 0.0 0.2 57716 4376 ?? Ss 4:48PM 0:02.13 rubocop --lsp path/to/rubocop Request (JSON-RPC) 3VCP$PQ 3VOOFS SVO P ff FOTFT GPSNBU XSJUF DBMM SFRVFTU EFMFHBUF P ff FOTFT OFX@UFYU +40/ Response (JSON-RPC) 3VCP$PQ-41 3PVUFT 3VCP$PQ$-* $PNNBOE -41 rubocop --lsp TUBSU 3VCP$PQ-41 4FSWFS 1MVHJO &EJUPS*%& 3VCP$PQ-41 3VOUJNF

Slide 45

Slide 45 text

w 50%0Ξ«Ο₯Ρ਀ʁ 3VCP$PQ-413PVUFT class RuboCop::LSP::Routes handle 'textDocument/didChange' do |request| doc = request[:params][:textDocument] result = diagnostic(doc[:uri], doc[:text]) @server.write(result) end handle 'textDocument/formatting' do |request| uri = request[:params][:textDocument][:uri] @server.write( id: request[:id], result: format_file(uri) ) end end $PEFTOJQQFU (FUBSFTVMUPGEJBHOPTUJDGSPN3VCP$PQ 3FUSJFWFBGPSNBUUFEUFYUGSPN3VCP$PQ 8SJUFSFTVMUUPstdoutVTJOH-41*08SJUFS 8SJUFBVUPDPSSFDUFEDPEFUPstdoutVTJOH-41*08SJUFS

Slide 46

Slide 46 text

3F fl FDU-414FSWFS3FTVMUTJO$MJFOU "QQMZJOH%JBHOPTUJDTBOE"VUP$PSSFDUJOH GSPN-414FSWFSUP-41$MJFOU

Slide 47

Slide 47 text

-41"DDFMFSBUFT%FW9 $* &EJUPS*%& $-* &EJUPS*%& $-* &EJUPS*%& $-* A /PSFBMUJNFGFFECBDLEVSJOHDPEJOH switch switch switch switch context switch

Slide 48

Slide 48 text

-41"DDFMFSBUFT%FW9 $* &EJUPS*%& $-* &EJUPS*%& $-* &EJUPS*%& $-* &EJUPS*%&XJUI-41 $-* A B Smarter Faster BSFQSFTFOUTUIFEFWFMPQNFOU fl PXFOWJTJPOFEGPSUIFNBJOUPQJD &OTVSFGBTUGFFECBDLXJUIBEF fi OFEQSPUPDPM[Simple, Easy] /PSFBMUJNFGFFECBDLEVSJOHDPEJOH switch switch switch switch context switch context switch

Slide 49

Slide 49 text

w %FWFMPQXJUINVMUJQMF-41DMJFOUTJOBXBZUIBUJT DIBSBDUFSJTUJDPG-41 w 3VCP$PQTCVJMUJO-41IBTCFFOEPHGPPEJOHXJUI &NBDT &HMPU BOETFFNTUPIBWFBTJHOJ fi DBOU TIBSFDPNQBUJCMFXJUI74$PEF w "TFYQFDUFEGSPNB.JDSPTPGUTQFDJ fi DBUJPO UIFSFJT BCVOEBOUJNQMFNFOUBUJPOJOGPSNBUJPOGPS74$PEF *NQMFNFOUBUJPO5JQT

Slide 50

Slide 50 text

%PHGPPEJOH JT*NQPSUBOU Insights from the User's Perspective

Slide 51

Slide 51 text

&OBCMF:+*5 IUUQTHJUIVCDPNSVCPDPQWTDPEFSVCPDPQCMPCWTSDFYUFOTJPOUT-- &OBCMF:+*5GSPNUIF -41DMJFOUVTJOHUIF RUBY_YJIT_ENABLE FOWJSPONFOUWBSJBCMF 5JQ&OBCMF:+*5 env RUBY_YJIT_ENABLE=1 bundle exec rubocop --lsp

Slide 52

Slide 52 text

w "VUPDPSSFDUXJUIFormat on Save w 6OMJLFSVOOJOHUFTUT BVUPDPSSFDUPO fi MFTBWF TFFNTHFOFSBMMZTBUJTGBDUPSZ w &YFDVUFDPNNBOET*GVTJOH74$PEF SVOGSPN UIF$PNNBOE1BMFUUF 3FDPNNFOE"VUPDPSSFDUJO:PVS&EJUPS

Slide 53

Slide 53 text

w 8IBUJTEF fi OFEJTNFSFMZUIFQSPUPDPM TQFDJ fi DBUJPO w 5IFEFTJHOPGMBOHVBHFTFSWFSJTMFGUUP UIFEJTDSFUJPOPGEFWFMPQFST w %PFT/FXNFBOUIBUUIFSFBSFTUJMM TPNFSPVHIFEHFT πŸ€” -41JTB3FMBUJWFMZ/FX5FDIOPMPHZ

Slide 54

Slide 54 text

w 1BSUJBMMZXSJUUFOWBSJBCMFTBVUPDPSSFDU GSPNvariableUP_variable w &NQUZNFUIPETUVSOJOUPPOFMJOFSFOET w 34QFDTfitJTBVUPDPSSFDUFEUPit QSFWFOUJOHGPDVTPOBTQFDJ fi DTQFD &YDFTTJWF"VUPDPSSFDUJO-41 &EJUPS*%&

Slide 55

Slide 55 text

%J ff FSFODFTJOSFRVJSFNFOUTCFUXFFO DPNNBOEMJOFBOE-41NBZTPNFUJNFT OFFEUPCFIBOEMFEPOBDBTFCZDBTFCBTJT "1SBDUJDBM*TTVF 7BMJE4ZOUBY *OWBMJE4ZOUBY $PEFJT$PNQMFUFE "VUPDPSSFDUFE /P"VUPDPSSFDUFE $PEFJT*ODPNQMFUFE 6OFYQFDUFEMZ"VUPDPSSFDUFE /P"VUPDPSSFDUFE 5IF/FX*TTVF

Slide 56

Slide 56 text

)PXDBOBNBDIJOF EFUFSNJOFJGDPEFJT JODPNQMFUFPSDPNQMFUF

Slide 57

Slide 57 text

SVCPDPQSVCPDPQ 4VQQPSUAutoCorrect: contextualPQUJPOGPS-41 # .rubocop.yml Lint/UnusedMethodArgument: AutoCorrect: contextual

Slide 58

Slide 58 text

4UBUFPG4PVSDF$PEF

Slide 59

Slide 59 text

4UBUFPG4PVSDF$PEF 7BMJE4ZOUBY4ZOUBYJTWBMJE CVUJUTTUJMMCFJOHXSJUUFO *OWBMJE4ZOUBY4ZOUBYJTJOWBMJEBOETUJMMCFJOHXSJUUFO Editor Part

Slide 60

Slide 60 text

4UBUFPG4PVSDF$PEF 7BMJE4ZOUBY4ZOUBYJTWBMJE CVUJUTTUJMMCFJOHXSJUUFO *OWBMJE4ZOUBY4ZOUBYJTJOWBMJEBOETUJMMCFJOHXSJUUFO Editor Part CLI Part

Slide 61

Slide 61 text

4UBUFPG4PVSDF$PEF 7BMJE4ZOUBY4ZOUBYJTWBMJE CVUJUTTUJMMCFJOHXSJUUFO *OWBMJE4ZOUBY4ZOUBYJTJOWBMJEBOETUJMMCFJOHXSJUUFO Editor Part CLI Part *UJTQSPCMFNBUJDJG DPEFJTBVUPDPSSFDUFE XIJMFJUJTCFJOHFEJUFE

Slide 62

Slide 62 text

4UBUFPG4PVSDF$PEF $PNQMFUFETPVSDFDPEF UZQJDBMMZDMFBSPGTZOUBYFSSPST DBOCFUSBEJUJPOBMMZQSPDFTTFE WJBrubocopDPNNBOE 7BMJE4ZOUBY4ZOUBYJTWBMJE CVUJUTTUJMMCFJOHXSJUUFO *OWBMJE4ZOUBY4ZOUBYJTJOWBMJEBOETUJMMCFJOHXSJUUFO Editor Part CLI Part *UJTQSPCMFNBUJDJG DPEFJTBVUPDPSSFDUFE XIJMFJUJTCFJOHFEJUFE

Slide 63

Slide 63 text

w *GJUTWJB-41 JUTBMXBZTTFFOBTTPVSDF DPEFCFJOHFEJUFE w *GJUTWJBDPNNBOE MJOF JUTTFFOBT TPVSDFDPEFXIFSF FEJUJOHJTDPNQMFUFE %FDJEFCBTFEPO)PXUIF5PPMJT6TFE LSP CLI RuboCop::LSP.enabled? is true RuboCop::LSP.enabled? is false

Slide 64

Slide 64 text

w AutoCorrect: always&OBCMFBVUPDPSSFDUJPOBMXBZT w AutoCorrect: disabled%JTBCMFBVUPDPSSFDUJPO w AutoCorrect: contextual &OBCMF BVUPDPSSFDUJPOXIFOMBVODIFEGSPNUIFrubocop DPNNBOE CVUJUJT/05BWBJMBCMFUISPVHI-41 5IF5ISFF7BMVFTPG"VUP$PSSFDU &OBCMF"VUP$PSSFDU %JTBCMF"VUP$PSSFDU $POUFYUVBM 3VCP$PQ USVF GBMTF 3VCP$PQ BMXBZTPSUSVF EJTBCMFEPSGBMTF DPOUFYVBM[NEW]

Slide 65

Slide 65 text

"-41T/FYU4UFQ Prism supports Error Tolerance w "TBO-41EFWFMPQFS POF DPOTJEFSTIBOEMJOH"45GPS JODPNQMFUFDPEF w $VSSFOUMZ VOQBSTBCMFDPEFJT SFHJTUFSFEBOP ff FOTFCZ Lint/SyntaxDPQ

Slide 66

Slide 66 text

The Final Chapter **3VCP$PQBOE1SJTN

Slide 67

Slide 67 text

w *OUFSFTUFEJOXIBU&SSPS5PMFSBODFDPVME BDIJFWF CVUOPUTVQQPSUFECZUIF1BSTFS HFN w RuboCop runs 4 times faster with Prism JOSVCPDPQSVCPDPQ w 'BTUBOEOPCPEZDPNQMBJOT .PUJWBUJPO#BDLHSPVOE

Slide 68

Slide 68 text

The header of lib/prism.rb # The Prism Ruby parser. # # "Parsing Ruby is suddenly manageable!" # - You, hopefully # module Prism 1BSTJOH3VCZJTTVEEFOMZNBOBHFBCMF w $SFBUFECZ,FWJO/FXUPO w )BOEXSJUUFO3FDVSTJWF%FTDFOU3VCZ1BSTFSJO$ w 1SPWJEF&SSPS5PMFSBODF 5SBOTMBUJPOMBZFS BOEPUIFST

Slide 69

Slide 69 text

w :PVDBOVTF1SJTNBTUIFQBSTFSGPSUIF .3*QSPDFTTJOHXJUI--parser=prism 1BSTF7BSJPVT3VCJFTXJUI1SJTN $ ruby --parser=prism example.rb $ RUBYOPT='--parser=prism' ruby example.rb w 3VCZ"1*TBSFQSPWJEFEUPQBSTFTPVSDF DPEFBOEIBOEMFQBSTJOHSFTVMUT Prism.parse('articles.map { it.title }') Prism.parse_file('example.rb')

Slide 70

Slide 70 text

w 5XPNBJODBOEJEBUFTJO6OJWFSTBM1BSTFS -SBNB -3 BOE1SJTN )BOEDSBGU w 8IJDIXJMMCFUIF6OJWFSTBM1BSTFS 0OMZUJNFXJMMUFMMπŸ•° w &JUIFSXBZ JUTFYQFDUFEUPBEPQU UIF1SJTN"1* FH "45 IUUQTNBHB[JOFSVCZJTUOFUBSUJDMFT'PMMPX6Q,JSJTIJNB3VCZIUNM 5IF3VCZ1BSTFS$PNNVOJUZ

Slide 71

Slide 71 text

SVCPDPQSVCPDPQ <'JY>4VQQPSU1SJTNBTB3VCZ1BSTFS # .rubocop.yml AllCops: ParserEngine: parser_prism

Slide 72

Slide 72 text

"455SFFBOEOPEFCFIBWJPSWBSJBUJPOT -FYFSUPLFOT5PLFOPSEFSEJ ff FSFODFT %JBHOPTUJDT%J ff FSFODFTJOFSSPSBOE XBSOJOHIBOEMJOH 5IF5ISFF3FTQPOTJCJMJUJFTPG1BSTFS Incompatibilities may occur between parsers

Slide 73

Slide 73 text

1BSTFSHFNBOE1SJTNT"45T Parser gem Prism 4UBUFNFOUT/PEF 1SPHSBN/PEF $BMM/PEF "SHVNFOUT/PEF 4USJOH/PEF TFOE TUS w 5IFTUSVDUVSF OBNF BUUSJCVUFT BOENFUIPETBSFBMM EJ ff FSFOU w "45VTFSTXJMMGBDF BNBTTJWFBNPVOUPG SFQMBDFNFOUXPSL puts 'hello'

Slide 74

Slide 74 text

w 1SJTNQSPWJEFT5SBOTMBUJPOMBZFS w 5SBOTMBUJPOTFYJTUGPS3JQQFSBOE TFBUUMFSCSVCZ@QBSTFSCFTJEFT1BSTFS HFN w 3VCP$PQDBOTXJUDIXIJMFNBJOUBJOJOH UIF1BSTFSHFN"1* 1SJTN5SBOTMBUJPO1BSTFS

Slide 75

Slide 75 text

<> SVCZZ 5IJTDMBTTJOIFSJUJOHGSPN Racc::ParserDMBTT 1BSTFS#BTF *NQPSUQBSTFZBT3BDDQFS3VCZWFSTJPO 1BSTFS3VCZ (FOFSBUFQBSTFSDPEF CBTFEPOBTZOUBY fi MF BDDPSEJOHUP-"-3 3VCP$PQ"45 1SPDFTTFE4PVSDF 1BSTFS3VCZ 1BSTFS3VCZ $ racc SVCZZ <> <> <> <> <> whitequark/parser

Slide 76

Slide 76 text

1BSTFS#BTF 6TF1SJTNXJUIUIF1BSTFSHFNJOUFSGBDF 1SJTN5SBOTMBUJPO1BSTFS "IBOEXSJUUFO3VCZ QBSTFSJO$FYUFOTJPO "DMBTTUIBUTFSWFTBTBO "EBQUFSCFUXFFOUIF 1BSTFSHFNBOE1SJTN 1SJTN 3VCP$PQ"45 1SPDFTTFE4PVSDF 1SJTN5SBOTMBUJPO 1BSTFS <> <> <>

Slide 77

Slide 77 text

1BSTFS#BTF 1SJTN4VQQPSUT:version0QUJPO Prism.parseBMMPXTTQFDJGZJOHUIF3VCZ BOBMZTJTWFSTJPOUISPVHIUIFversionPQUJPO 1SJTN 3VCP$PQ"45 1SPDFTTFE4PVSDF 1SJTN5SBOTMBUJPO 1BSTFS <> <> <> Prism.parse(source, filepath: filepath, version: '3.3.1')

Slide 78

Slide 78 text

1BSTFS#BTF *UTVQQPSUTNVMUJWFSTJPOT SVCZQSJTN 1SJTN5SBOTMBUJPO1BSTFS 5IFWBMVFCBTFEPO TargetRubyVersionJTQBTTFEUP UIF:versionPQUJPOPG1SJTN 1SJTN 3VCP$PQ"45 1SPDFTTFE4PVSDF 1SJTN5SBOTMBUJPO 1BSTFS 1SJTN5SBOTMBUJPO 1BSTFS 1SJTN5SBOTMBUJPO 1BSTFS <> <> <> *UCSBODIFTJOUFSOBMMZ CBTFEPOUIFWFSTJPO

Slide 79

Slide 79 text

w 3VCP$PQBMMPXTTQFDJGZJOH TargetRubyVersionJOEFQFOEFOUMZPG UIFSVOUJNF w *NQPSUBOUGPSNJOJNVN3VCZWFSTJPO BOBMZTJT FH 3VCZ(FNT 3VCP$PQ3FRVJSFT.VMUJ7FSTJPOT

Slide 80

Slide 80 text

w 4FUParserEngine: parser_prismBOE TargetRubyVersion as 3.3PSIJHIFS :PV$BO6TFUIF&YQFSJNFOUBM'FBUVSF AllCops: ParserEngine: parser_prism TargetRubyVersion: 3.3 w "EEgem 'prism'UPZPVS(FN fi MF gem 'prism'

Slide 81

Slide 81 text

⏱YJTFaster" $ cd path/to/ruby/prism $ bin/prism benchmark lib/prism.rb (snip) Comparison: Prism: 6951.8 i/s Ripper::SexpBuilder: 2058.9 i/s - 3.38x slower Prism::Translation::RubyParser: 1573.8 i/s - 4.42x slower Prism::Translation::Parser: 767.7 i/s - 9.06x slower Prism::Translation::Ripper::SexpBuilder: 696.0 i/s - 9.99x slower RubyParser: 221.1 i/s - 31.44x slower Parser::CurrentRuby: 210.1 i/s - 33.09x slower w 1SJTNJT33xGBTUFSUIBO1BSTFS$VSSFOU3VCZ XIJUFRVBSL w 1SJTNJT9xGBTUFSUIBO5SBOTMBUJPO1BSTFS w 5SBOTMBUJPO1BSTFSJT3.65xGBTUFSUIBO1BSTFS$VSSFOU3VCZ

Slide 82

Slide 82 text

w 3VCP$PQTTFSWFS NPEFCPPUVQUJNF XBTEJTDVTTFEBU 3VCZ,BJHJ 8IBUJTUIF3FBMJUZ IUUQTTQFBLFSEFDLDPNLPJDNBLFSVCPDPQTVQFSGBTU TMJEF w 'BTUFSBOBMZTJTUZQJDBMMZCFOF fi UT FTQFDJBMMZ GPSTZTUFNTMJLF-41UIBUSFQFBUFEMZQBSTF

Slide 83

Slide 83 text

1SPWJEFSmarter" .PSF'FFECBDL $VSSFOU3VCP$PQ EPFTOUIBOEMFXJUI *OWBMJE4ZOUBY "MXBZTIBOEMFECZ Lint/SyntaxDPQ )PQFGVMMZ BGVUVSF FSSPSUPMFSBOUQBSTFS XJMMIBOEMFUIJT Error Tolerance

Slide 84

Slide 84 text

&SSPS5PMFSBODFPG1SJTN $ ruby -rprism -e 'p Prism.parse("(42)").value' @ ProgramNode (location: (1,0)-(1,4)) β”œβ”€β”€ locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,4)) └── body: (length: 1) └── @ ParenthesesNode (location: (1,0)-(1,4)) β”œβ”€β”€ body: β”‚ @ StatementsNode (location: (1,1)-(1,3)) β”‚ └── body: (length: 1) β”‚ └── @ IntegerNode (location: (1,1)-(1,3)) β”‚ β”œβ”€β”€ flags: decimal β”‚ └── value: 42 β”œβ”€β”€ opening_loc: (1,0)-(1,1) = "(" └── closing_loc: (1,3)-(1,4) = ")" $ ruby -rprism -e 'p Prism.parse("(42").value' @ ProgramNode (location: (1,0)-(1,3)) β”œβ”€β”€ locals: [] └── statements: @ StatementsNode (location: (1,0)-(1,3)) └── body: (length: 1) └── @ ParenthesesNode (location: (1,0)-(1,3)) β”œβ”€β”€ body: β”‚ @ StatementsNode (location: (1,1)-(1,3)) β”‚ └── body: (length: 2) β”‚ β”œβ”€β”€ @ IntegerNode (location: (1,1)-(1,3)) β”‚ β”‚ β”œβ”€β”€ flags: decimal β”‚ β”‚ └── value: 42 β”‚ └── @ MissingNode (location: (1,1)-(1,3)) β”œβ”€β”€ opening_loc: (1,0)-(1,1) = "(" └── closing_loc: (1,3)-(1,3) = "" Parse the valid syntax (42) Parse the invalid syntax (42 8IFOQBSTJOHJOWBMJETZOUBY /0&3303PDDVST BOEBMissingNodeJTJOTFSUFEJOTUFBE

Slide 85

Slide 85 text

w 5IFPrism::Translation::Parser BJNFEBU1BSTFSHFNDPNQBUJCJMJUZJTOPU &SSPS5PMFSBODF w 5IVT 3VCP$PQEPFTOPUZFUTVQQPSU &SSPS5PMFSBODF &SSPS5PMFSBODFPG1BSTFS

Slide 86

Slide 86 text

w πŸ˜€$PEFDPNQMFUJPO"OBMZ[JOHJOWBMJEDPEFJT FTTFOUJBMGPSUZQFCBTFEDPNQMFUJPO w πŸ˜”-JOUFS8IFOEFQSFDBUFENFUIPETJHOBUVSF JTEFUFSNJOFE UIFDPEFJTHFOFSBMMZWBMJE w πŸ€”'PSNBUUFS*TGPSNBUUJOHCFOF fi DJBMEVSJOH XSJUJOH VODMFBS -41BOE&SSPS5PMFSBODF

Slide 87

Slide 87 text

w 6OBCMFUPVTF&SSPS5PMFSBODF w /PUBTGBTUBTUIFWBOJMMB1SJTN 5IF-JNJUBUJPOTPG5SBOTMBUJPO1BSTFS There is room to pioneer further potential

Slide 88

Slide 88 text

8IZJTJUOPUOBNFE 1BSTFS&OHJOFQSJTN

Slide 89

Slide 89 text

1BSTFS#BTF w 6TF1SJTNXJUIUIF1BSTFSHFNJOUFSGBDF 1SJTN5SBOTMBUJPO1BSTFS "IBOEXSJUUFO3VCZ QBSTFSJO$FYUFOTJPO "DMBTTUIBUTFSWFTBTBO "EBQUFSCFUXFFOUIF 1BSTFSHFNBOE1SJTN 1SJTN 3VC$PQ"45 1SPDFTTFE4PVSDF 1SJTN5SBOTMBUJPO 1BSTFS 1SJTN5SBOTMBUJPO 1BSTFS 1SJTN5SBOTMBUJPO 1BSTFS <> <> <>

Slide 90

Slide 90 text

1BSTFS#BTF w 6TF1SJTNXJUIUIF1BSTFSHFNJOUFSGBDF 1SJTN5SBOTMBUJPO1BSTFS "IBOEXSJUUFO3VCZ QBSTFSJO$FYUFOTJPO "DMBTTUIBUTFSWFTBTBO "EBQUFSCFUXFFOUIF 1BSTFSHFNBOE1SJTN 1SJTN 3VC$PQ"45 1SPDFTTFE4PVSDF 1SJTN5SBOTMBUJPO 1BSTFS 1SJTN5SBOTMBUJPO 1BSTFS 1SJTN5SBOTMBUJPO 1BSTFS <> <> <>

Slide 91

Slide 91 text

1BSTFS#BTF w 6TF1SJTNXJUIUIF1BSTFSHFNJOUFSGBDF 1SJTN "IBOEXSJUUFO3VCZ QBSTFSJO$FYUFOTJPO "DMBTTUIBUTFSWFTBTBO "EBQUFSCFUXFFOUIF 1BSTFSHFNBOE1SJTN 1SJTN 3VC$PQ"45 1SPDFTTFE4PVSDF 1SJTN5SBOTMBUJPO 1BSTFS 1SJTN5SBOTMBUJPO 1BSTFS 1SJTN5SBOTMBUJPO 1BSTFS <> <> <>

Slide 92

Slide 92 text

<> QBSTFZ %FQFOEPO"CTUSBDUJPO BOE4UBCJMJUZ 1SJTN"1* 5SBOTMBUJPO-BZFS 3VCZQBSTFSHFOFSBUFECBTFEPOUIFQBSTFZGPSFBDI3VCZWFSTJPO 0S1SJTN"1*XJUI-SBNB (FOFSBUFQBSTFSDPEF CBTFEPOBTZOUBY fi MF BDDPSEJOHUP14-3 3VCP$PQ"45 1SPDFTTFE4PVSDF "3VCZ1BSTFS QBSTFD QBSTFTP GPS3VCZ "3VCZ1BSTFS QBSTFD QBSTFTP GPS3VCZ $ lrama QBSTFZ <> <> <> <> <> ruby/ruby

Slide 93

Slide 93 text

w .PSF'BTUFS w (BJO&SSPS5PMFSBODF w "MNPTUOPOFFEGPS1BSTFSHFNNBJOUFOBODF XPParser::Source::TreeRewriter w 5IFUniversal ParserXJMMFOBCMFUIFBCJMJUZUP SVOUIFTBNFQBSTFSVOJWFSTBMMZJOUIFGVUVSF #FOF fi UTPG.JHSBUJOHUP7BOJMMB1SJTN

Slide 94

Slide 94 text

w $PNQBUJCMFXJUI1SJTNT"45OPEFT -FYFS UPLFOT BOE%JBHOPTUJDT w .BLF/PEF1BUUFSOTNBDSPDPNQBUJCMFXJUI 1SJTNT"45OPEFT w &OBCMFNJHSBUJPOUISPVHIQBSBMMFMPQFSBUJPO PGUIFTF 5IF3PBEJT-POHBOE$IBMMFOHJOH 4PNFGFBUVSFTBOEDPQT

Slide 95

Slide 95 text

"SPVOE3VCZπŸ€”

Slide 96

Slide 96 text

0SFOIBODF1SJTN 5SBOTMBUJPO1BSTFSπŸ˜… *UTNPSFQSBDUJDBMUIBO1BSTFSHFNTFSSPSUPMFSBODFTVQQPSU

Slide 97

Slide 97 text

3VCP$PQT1BSTFS&OHJOFT 1BSTFSHFNβœ… 1SJTN5SBOTMBUJPO1BSTFSβœ… 1SJTN "1* β˜‘ 5IF/BNFPG 1BSTFS&OHJOF QBSTFS@XIJUFRVBSL QBSTFS@QSJTN QSJTN 1BSTJOH4QFFE YdY Y 4VQQPSUGPS 1BSTJOH3VCZ 3VCZ 3VCZ 3VCZ &SSPS5PMFSBODF /FWFS4VQQPSUFE /PU4VQQPSUFE 4VQQPSUFE 6OJWFSTBM1BSTFS /P "NCJHVPVT :FT %FWFMPQNFOU 4UBUVT 4UBCMF &YQFSJNFOUBM $PODFQUVBM βœ…4VQQPSUFE β˜‘6OTVQQPSUFE

Slide 98

Slide 98 text

w (FO3FHFYQ w (FO3JQQFS w (FOXIJUFRVBSLQBSTFS w (FO1SJTN5SBOTMBUJPO1SJTN w (FO1SJTN"1* TBD 1BSTFS(FOFSBUJPOT"HBJOTU3VCP$PQ IUUQTSVCZLBJHJPSHQSFTFOUBUJPOTCCBUTPWIUNMNBZ

Slide 99

Slide 99 text

4XJUDIJOH3VCP$PQTQBTTFSUP1SJTN 4XJUDIJOH3VCZTQBTTFSUP1SJTN "1SJODJQMFPGB6OJWFSTBM1BSTFS AllCops: ParserEngine: parser_prism TargetRubyVersion: 3.3 RUBYOPT='--parser=prism' bundle exec rubocop Use the same parser in Ruby and RuboCop!

Slide 100

Slide 100 text

(JU)VC!LPJD 4QFDJBM5IBOLT #P[IJEBS#BUTPW +VTUJO4FBSMT ,FWJO/FXUPO :VJDIJSP,BOFLP ,BJHJ&GGFDU 8JMM4IBQF :PVS'VUVSF