Slide 1

Slide 1 text

TypeProf for IDE: Enrich Development Experience without Annotations Yusuke Endoh (@mametter) RubyKaigi Takeout 2021

Slide 2

Slide 2 text

Yusuke Endoh / @mametter •A Ruby committer working at Cookpad w/ @ko1 • TypeProf: A static type analyzer for Ruby 3 •An esoteric Ruby programmer • See my RubyKaigi bio 2

Slide 3

Slide 3 text

A recent contribution: error_highlight 3 json = { foo: { bar: { baz: 42 } } } json[:foo][:barr][:baz] # Ruby 3.0 $ ruby t.rb t.rb:2:in `': undefined method `[]' for nil:NilClass (NoMethodError) # Ruby 3.1 $ ruby t.rb t.rb:2:in `': undefined method `[]' for nil:NilClass (NoMethodError) json[:foo][:barr][:baz] ^^^^^^ Credit: The original author of its prototype is @yui-knk https://github.com/ruby/ruby/pull/4470

Slide 4

Slide 4 text

"I love static typing" … or do you? •Static typing is a means, not an end •The end is the modern development experience • Demo: TypeScript 4

Slide 5

Slide 5 text

The modern development experience with TypeScript 5 On-the-fly error reporting

Slide 6

Slide 6 text

The modern development experience with TypeScript 6 On-the-fly type inference

Slide 7

Slide 7 text

The modern development experience with TypeScript 7 Go to definition

Slide 8

Slide 8 text

The modern development experience with TypeScript 8 •Completion Completion

Slide 9

Slide 9 text

The modern development experience with TypeScript 9 Hint for arguments

Slide 10

Slide 10 text

"I love static typing" … or do you? •Static typing is a means, not an end • The end is the modern development experience • On-the-fly error reporting, go-to-definition, completion, argument hint, etc. •Q: Isn't it possible to achieve the experience without changing the Ruby language? • My answer is "Possible!" 10 (under some conditions)

Slide 11

Slide 11 text

Today's topic: TypeProf for IDE •A VSCode extension for Ruby • Powered by TypeProf (a static type analyzer for Ruby) •Demo 11

Slide 12

Slide 12 text

The modern development experience with TypeProf for IDE 12 On-the-fly method signature

Slide 13

Slide 13 text

The modern development experience with TypeProf for IDE 13 On-the-fly error reporting

Slide 14

Slide 14 text

The modern development experience with TypeProf for IDE 14

Slide 15

Slide 15 text

The modern development experience with TypeProf for IDE 15 On-the-fly type inference Completion

Slide 16

Slide 16 text

The modern development experience with TypeProf for IDE 16 Hint for arguments

Slide 17

Slide 17 text

Demo: Summary •The modern development experience is possible without full type annotations by TypeProf for IDE 17

Slide 18

Slide 18 text

Agenda ➔ Recap: Types for Ruby 3  •TypeProf • TypeProf for IDE • Conclusion 18

Slide 19

Slide 19 text

Recap: Types for Ruby 3 19 Name What RBS TypeProf Steep Sorbet The Ruby official type definition language A static type analyzer for Ruby A static type analyzer for Ruby A static type analyzer for Ruby

Slide 20

Slide 20 text

RBS: Ruby official type definition language 20 class User def initialize: (String) -> void def name: () -> String end

Slide 21

Slide 21 text

What a static type analyzer does •Infers the types of a given program • Reports a potential runtime type error • Supports IDE 21 msg = "Hello, " + user.name msg: String msg = "Hello, " + user.naame Error!

Slide 22

Slide 22 text

Differences of each static analyzer 22 Type inference Error reporting IDE support Analysis speed TypeProf 🙂Strong ☹️Weak No → Yes ☹️Slow Steep ☹️Weak 🙂Strong Yes 🙂Fast

Slide 23

Slide 23 text

Agenda •Recap: Types for Ruby 3 ➔ TypeProf  • TypeProf for IDE • Conclusion 23

Slide 24

Slide 24 text

The key idea of TypeProf Runs a Ruby code in "type-level" Traditional interpreter def foo(n) n.to_s end foo(42) Calls w/ 42 Returns "42" TypeProf def foo(n) n.to_s end foo(42) Calls w/ Integer Returns String Object#foo :: (Integer) -> String 24

Slide 25

Slide 25 text

The user-facing feature of TypeProf •Ruby 3.0 • A type inference tool to create a prototype of RBS • No IDE support • Ruby 3.1~ • + IDE support! 25

Slide 26

Slide 26 text

Demo (memo) •Test instead of type annotations •Passing an unknown type • Manual RBS specification • Flow-sensitive analysis • Manual overloading •Block, RBSWiki example 26

Slide 27

Slide 27 text

Demo: Tests instead of type annotations 27 untyped String

Slide 28

Slide 28 text

Demo: Passing an unknown type 28 The method signature is changed to accept a new type Error in the callee side

Slide 29

Slide 29 text

Demo: Manual RBS specification 29 Click here A prototype RBS is created

Slide 30

Slide 30 text

Demo: Manual RBS specification (cont'd) 30 Error in the caller side # means RBS-defined

Slide 31

Slide 31 text

Demo: Flow-sensitive analysis 31 No error type case

Slide 32

Slide 32 text

Demo: Manual overloading 32 No error Write RBS for overloading Argument hint is selectable

Slide 33

Slide 33 text

Demo: Block 33

Slide 34

Slide 34 text

Demo: Works with a simple Rack app 34

Slide 35

Slide 35 text

Agenda •Recap: Types for Ruby 3 •TypeProf ➔TypeProf for IDE • Conclusion 35

Slide 36

Slide 36 text

Language Server Protocol (LSP) 36 LSP client (vscode) LSP server (TypeProf for IDE) code changed error found complete "5.ti" maybe "5.times" 5.ti| Do you mean: 5.times 1 + "str" 1 + "str" Is this a bug?

Slide 37

Slide 37 text

Currently supported LSP features •Show method signatures •Show potential errors • Go to definition of methods/variables • Find references of methods/variables • Completion •Show hint about method arguments 37

Slide 38

Slide 38 text

Not-implemented-yet LSP Features 38 Type hover Documentation • More challenging features • Auto refactoring (renaming), quick fix suggestion, etc. • Contribution is welcome!!!

Slide 39

Slide 39 text

Future work: the parser needs more ♥ •An AST node knows only the beginning and end of the source code • The parser returns nothing when syntax is broken • Cannot complete an incomplete call 39 current implementation desired behavior foo(k:)

Slide 40

Slide 40 text

About analysis performance •TypeProf is very slow • It traces "require 'foo'" (even if it is a gem) •TypeProf for IDE stops the analysis in one second • Nothing will be reported where it couldn't analyze within the time limit 40

Slide 41

Slide 41 text

How to make TypeProf fast •Write RBS for gems • so that TypeProf don't have to analyze gem sources • Watch pocke's talk (Day 2) • Divide your application to components • and write RBS against their interfaces • We need experiment with a practical use case 41

Slide 42

Slide 42 text

Agenda •Recap: Types for Ruby 3 •TypeProf • TypeProf for IDE • Implementation ➔Conclusion 42

Slide 43

Slide 43 text

Release plan •TypeProf for IDE will be released in Ruby 3.1 • Happy if you could play with it and give us feedback • How to run the development version https://gist.github.com/mame/86234de6a58352b9f994e0f8a6d6fbc2 (in Japanese) •Ready for production? • Experimental, but hopefully works for small programs • For large code base, please write RBS for gems first! 43

Slide 44

Slide 44 text

Special thanks •Hideki Miura • Ruby committers: matz, akr, ko1, soutaro • Katsuhiro Ueno & Eijiro Sumii •Stripe team & Shopify team & Jeff Foster • Yuta Saito (@kateinoigakukun) • Many improvements of TypeProf for IDE 44

Slide 45

Slide 45 text

Conclusion •The modern development experience is possible without full type annotations by TypeProf for IDE •Ruby 3.1 will bundle TypeProf for IDE 45