DEV Community

Fred Snyder
Fred Snyder

Posted on

Type Checking Ruby with Solargraph

Proper type checking can be challenging in dynamically typed languages like Ruby. Nonetheless, I wound up going down this road as a side effect of my work on Solargraph. The current version (0.39.7 at time of writing) now ships with a type checking tool. While it's still a work in progress, it's mature enough that I use it regularly in my own projects. In this post, I'll discuss the history behind it and provide a brief introduction to how it works.

Origins

I started Solargaph several years ago out of an interest in improving the tooling ecosystem around Ruby. At the time, I was developing an Eclipse plugin for Gamefic, another Ruby project of mine. The plugin quickly grew from a domain-specific application to a general-purpose Ruby tool. After the release of Visual Studio Code and the introduction of the Language Server Protocol, I decided to turn Solargraph into an editor-agnostic language server.

Most of my early work focused on capabilities like autocompletion and inline documentation. My early approach was to provide basic mapping of class and method definitions augmented by YARD annotation. Over time, the mapping evolved to provide type inference through static analysis.

As the static analysis improved, it seemed like a natural progression to add type checking as a diagnostics feature.

How It Works

The type checker is somewhat similar to Sorbet, with the key difference being that Solargraph uses YARD comments for annotation. Type safety isn't enforced at run-time. My approach has been to treat type discrepancies as code smells. You can use the checker to report problems in your editor or add it to your CI/CD workflow with varying degrees of strictness.

Code smells that the type checker can detect include the following:

  • Invalid method call arity (e.g., not enough or too many arguments)
  • Undefined or unknown types
  • Unresolved method or variable names
  • Incomplete documentation (e.g., methods without @return tags)
  • @return tags that disagree with types inferred from code
  • @param tags that disagree with types inferred from method arguments

The type checker can run at four levels: normal, typed, strict, and strong. See the type checker documentation for more information about the rules enforced at each level.

Using the Type Checker

There are two primary ways to use Solargraph's type checker: the command-line tool and the language server's diagnostics capability.

The Command Line

You can run the type checker from the command line in the root directory of your project. We'll use a directory containing the following example.rb:

class Example
  # @return [String]
  def foo
    "foo"
  end

  # @return [InvalidClassName]
  def bar
    "bar"
  end

  # @return [Integer]
  def baz
    "baz"
  end
end

Example.new.foo.downcase
Example.new.foo.uppercase

Run the type checker:

$ solargraph typecheck
./example/example.rb:8 - Unresolved return type InvalidClassName for Example#bar

The default normal level enforces the bare minimum of type safety, so the only error it finds is the unrecognized InvalidClassName class. At the typed level or higher, it'll catch the type discrepancy in Example#baz:

$ solargraph typecheck --level typed
./example/example.rb:8 - Unresolved return type InvalidClassName for Example#bar
./example/example.rb:13 - Declared return type Integer does not match inferred type String for Example#baz
2 problems found.

At the strict level, it will also catch the unknown uppercase method:

$ solargraph typecheck --level strict
./example/example.rb:8 - Unresolved return type InvalidClassName for Example#bar
./example/example.rb:13 - Declared return type Integer does not match inferred type String for Example#baz
./example/example.rb:19 - Unresolved call to uppercase
3 problems found.

Diagnostics in VS Code

If you use the Solargraph extension for VS Code, you can configure your editor to use the type checker for diagnostics by adding it to your project's .solargraph.yml file:

reporters:
- typecheck

You can also specify a level:

reporters:
- typecheck:strict

Type errors will appear in the Problems console.

The Problems console

This feature should also work in any other language client that supports diagnostics.

Further Reading

Check the following links to learn more about Solargraph and try it for yourself.

Top comments (0)