RubyConf 2021

Enjoy Ruby Programming in IDE and TypeProf

Enjoy Ruby Programming in IDE and TypeProf

by Yusuke Endoh

In the presentation titled "Enjoy Ruby Programming in IDE and TypeProf" by Yusuke Endoh at RubyConf 2021, the focus is on enhancing the Ruby programming experience using TypeProf, a static type analyzer integrated into Ruby 3.0. The discussion emphasizes how modern development features, often reliant on type annotations, can be implemented for non-type-annotated Ruby code through TypeProf. The speaker, a member of the Ruby core committee, introduces the presentation by highlighting his background and previous contributions to Ruby, including keyword arguments and test coverage features.

The agenda covers:
- Introduction to TypeProf and its capabilities.
- Integration of TypeProf with Integrated Development Environments (IDEs), especially VS Code.
- Practical demonstration of how TypeProf helps identify coding errors and enhance development efficiency.

Key Points Discussed:
- TypeProf analyzes Ruby code without requiring developers to add type annotations, making it accessible for conventional Ruby programmers.
- The tool provides on-the-fly error reporting, method signature completion, and real-time feedback directly within supported IDEs, thus streamlining the development process.
- There are various tools associated with Ruby's type systems, such as RBS (the official type definition language for Ruby) and other static analyzers (like Steep and Sorbet), each catering to different programming philosophies. TypeProf aims to operate without extensive modifications required in the language.
- TypeProf's approach contrasts with other analyzers that necessitate type annotations, thus fostering ease of use for Ruby developers who may not be accustomed to type systems.
- A demonstration showcases how TypeProf effectively detects potential type errors and provides method suggestions, enhancing the development workflow in real time.
- The discussion also touches on configuration steps for using TypeProf in a development environment and the simple test framework approach that aids in inferring method signatures.

Additionally, the speaker acknowledges that while TypeProf seeks to improve the developer experience, it remains in early stages and is best suited for small, straightforward codebases, encouraging community contributions to improve its database of RBS files for popular gems.

In conclusion, the presentation underscores that modern development experiences can be realized without full type annotations, providing a promising vision for Ruby programming that could lead to enhanced productivity in coding practices.

00:00:11.840 Good morning, good evening. Welcome to this presentation!
00:00:15.440 In this presentation, I'll talk about TypeProf IDE, which brings the modern development experience to Ruby.
00:00:21.680 Before diving into the main topic, let me introduce myself. My name is Yusuke Endoh, and my Twitter handle is @mameta.
00:00:28.320 I am a Ruby committee member working at Cookpad. Our company employs two Ruby core team members: Sasada, the author of the previous VM, and myself.
00:00:36.960 My main contributions to Ruby include the design and implementation of keyword arguments. I first implemented keyword arguments in Ruby 2.0 and was involved in the redesign for Ruby 3.
00:00:58.320 Additionally, I implemented coverage.so, which is Ruby's test coverage feature you may have used through SimpleCov, which uses coverage.so as a backend. My recent contribution is the implementation of TypeProf, which is today's topic.
00:01:31.680 Before we get into the main topic, I'd like to share a recent small improvement for Ruby called Highlight.
00:01:40.880 Consider this code: it attempts to extract a value from JSON. However, the type is misspelled as 'b-a-l-l'. When running this, an unhelpful error message is thrown. In the case of debugging, there are two possible exceptions that could arise, making it difficult to distinguish these possibilities solely based on error messages.
00:02:05.119 Since Ruby 3.1, the error message now provides more detailed explanations. For example, it indicates that a NoMethodError was raised when leading a Buzz. Hence, we can understand that 'leading' is returning without 'lila'. This feature was originally created to enhance debugging, and I completed the implementation. It is already included in the development branch of Ruby and will be released as part of Ruby 3.1 this December.
00:02:31.599 Now, let's move on to the agenda of this talk. First, I'll introduce TypeProf and some tools related to typing for Ruby 3. Then, I will discuss its integration with IDEs, such as Visual Studio Code. Finally, I will provide a brief explanation on how to use TypeProf for IDEs and conclude this presentation.
00:03:35.840 So, what is TypeProf? This is a static type analyzer for Ruby. The basic feature of TypeProf is typing the classes in Ruby code.
00:03:43.760 For example, consider this Ruby code that defines a User class with an initialize method and creates its instance. This code is quite plain, lacking any type annotations. When analyzed, it generates method signatures and outputs them in RBS format. In this instance, the generated signature indicates that there is a class called User that has a method named 'initialize', which accepts a string instance as an argument.
00:04:28.160 I will not delve into how TypeProf analyzes Ruby code; if you're interested, please refer to my previous talk at RubyConf 2019.
00:04:42.880 If you've heard about the type system for Ruby 3 before, you may be confused by the various names, such as TypeProf, RBS, Steep, and Sorbet. To clarify, RBS is Ruby's official type definition language. TypeProf and Steep are both static type analyzers for Ruby, while Sorbet is also a static type analyzer. Please remember that RBS is a dedicated mini-language meant to describe class and method signatures for Ruby code, while the others are names of static type analyzers.
00:05:56.559 Next, you may wonder why there are so many type analyzers for Ruby. This is because they hold different philosophies. The goal of TypeProf is to analyze Ruby code without requiring modifications to the language. In other words, we do not want users to write an abundance of type annotations in their Ruby code. Therefore, we put significant effort into typing friends. On the other hand, Steep and Sorbet require users to write type annotations either as comments or using a dedicated DSL language.
00:07:05.280 Steep and Sorbet typically report very little about existing code that lacks type annotations. This can be a bit cumbersome; however, if you add type annotations to your code, their error reporting becomes very accurate. Additionally, their approaches are notably fast—especially Sorbet, as it is written in C++, which is beneficial for users. Conversely, TypeProf's approach is slower, potentially leading to false positives and false negatives, which is a drawback compared to Steep and Sorbet.
00:07:56.960 TypeProf, Steep, and Sorbet all accept the same RBS files and utilize the same definitions for Ruby core features, such as Array and String. However, Steep and Sorbet use their own DSL language. For a long time, TypeProf did not have IDE integration. But this year, I focused on developing this feature, and it is finally functioning.
00:08:36.959 I previously showed you an example of TypeProf's use case. There are many ways to express Ruby code in TypeProf, but I will omit the extensive details during this presentation. The most notable characteristic of RBS is that it resides in a separate file from Ruby code. This design choice was made to avoid embedding any type annotations directly into the Ruby language.
00:09:27.360 Some people critique this design, arguing that separate files complicate things. However, the challenges can be resolved, in part, by using TypeProf for IDE, which I will demonstrate shortly. Next, I would like to introduce TypeProf for IDE.
00:10:32.800 TypeProf for IDE is a VSCode extension for Ruby that uses TypeProf as its backend. Assume you are editing Ruby code in VSCode—TypeProf monitors changes and notifies TypeProf in real-time.
00:11:00.320 For instance, TypeProf recognizes that an operation, such as attempting to add a string with a number, will raise an exception when executed and an error message will be reported to VSCode.
00:11:50.400 Now, let's demonstrate TypeProf for IDE. Here is some Ruby code that defines a User class and features an initialize method, accompanied by a simple test. Let's enable TypeProf. Notice that gray lines indicate method signatures. For instance, the signature of the initialize method indicates that it accepts a string and returns an instance of User.
00:12:40.080 Let's try calling the User constructor with an excessive number of arguments. An underline appears beneath the method call, and hovering over it will display a familiar error message indicating that too many arguments were provided.
00:13:16.640 Next, we can use the 'Go to Definition' feature by right-clicking a method name and selecting the corresponding option. This will navigate to the line where the method is defined.
00:13:20.640 Alternatively, you can click on the method name while holding the Control key. This feature conveniently streamlines navigation within the code.
00:13:41.280 Now, let's explore the completion feature. If we define a variable named 'user' and begin typing a method call, the editor will display relevant suggestions. For example, if I type 'user.s', it offers 'say hello' as a completed suggestion. The method 'say hello' returns a string, indicating that the variable has a string type.
00:14:31.520 Additionally, if you hover over any method, you will see a list of candidate methods. This confirms that TypeProf has accurately inferred the types.
00:15:21.600 The last demonstration involves hints for method arguments. If we write an open parenthesis after a method name, a pop-up will appear showing its expected arguments. This is particularly useful when the method accepts both required and optional parameters.
00:15:38.960 By indicating one argument, it shows a second optional argument. As you type arguments, the emphasized argument changes accordingly, which provides a clear context for the expected parameters.
00:16:10.960 In summary, what I wish to convey through this demonstration is that a modern development experience is feasible, even when working with non-type annotated Ruby code.
00:16:44.000 TypeProf displays informative descriptions by passing them into RBS files. I believe that this provides one solution to the issues surrounding typing in Ruby.
00:17:15.200 Next, I will explain how to configure TypeProf for your codebase. This slide outlines the steps needed to set up TypeProf.
00:17:40.320 First, you need to utilize the development version of Ruby since it depends on Ruby's internal API. Next, you must add TypeProf to your Gemfile as usual. Additionally, configure the RBS collection to enable TypeProf to read RBS files of any gems that your code uses.
00:18:08.160 Then, search for the VSCode extension for TypeProf and install it. Finally, open your project folder in VSCode. It should work, but keep in mind that TypeProf is still in development, and there may be cases where it does not work properly.
00:18:30.720 Unfortunately, TypeProf might not function correctly even when configured properly. There are two helpful tricks: one is to write a simple test in each file, and the other is to write obvious code. These strategies will help TypeProf in analyzing your code effectively.
00:19:16.640 In the example I demonstrated, there is a test at the end of the file, which helps guide TypeProf in making accurate type inferences by ensuring that the code is executed when the file is run directly.
00:19:47.040 Removing the test can cause TypeProf to fail in correctly identifying method signatures. This behavior arises because TypeProf's analysis relies on the presence of method calls to infer types involved.
00:20:11.920 This analysis method leads to some interesting behaviors. For example, if you mistakenly pass an incorrect argument type to a method, TypeProf will adjust the method to accept both expected and unexpected types.
00:20:39.300 While this behavior may be fitting for some situations, in others, it might be confusing. Thus, to accurately convey expected method signatures, you may need to write RBS definitions.
00:21:03.680 In conclusion, TypeProf aims to enhance the Ruby development experience without necessitating major changes to the language itself. TypeProf is still maturing, so I encourage developers to stay tuned for further improvements.
00:21:36.160 Thank you for your attention! I appreciate any feedback regarding TypeProf's integration and functionality.
00:21:49.680 I would like to acknowledge the contributions of various individuals who helped implement and enhance TypeProf, particularly Yuta Saito, who played a vital role in developing the TypeProf IDE as an intern at our company, QuickPad.
00:22:07.680 His contributions, including the go-to definition feature, performance improvements, and packaging the VSCode extension, were completed in just ten days!
00:22:33.280 Without his collaboration, the TypeProf for IDE project would not have been possible. Thank you again for attending this presentation, and I hope to hear your thoughts on TypeProf.