<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Fred Snyder</title>
    <description>The latest articles on DEV Community by Fred Snyder (@castwide).</description>
    <link>https://dev.to/castwide</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F392258%2Fa7417d00-b586-4354-b606-c8ad35194254.png</url>
      <title>DEV Community: Fred Snyder</title>
      <link>https://dev.to/castwide</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/castwide"/>
    <language>en</language>
    <item>
      <title>Type Checking Ruby with Solargraph</title>
      <dc:creator>Fred Snyder</dc:creator>
      <pubDate>Thu, 21 May 2020 19:46:52 +0000</pubDate>
      <link>https://dev.to/castwide/type-checking-ruby-with-solargraph-2f6o</link>
      <guid>https://dev.to/castwide/type-checking-ruby-with-solargraph-2f6o</guid>
      <description>&lt;p&gt;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 &lt;a href="https://solargraph.org"&gt;Solargraph&lt;/a&gt;. 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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Origins
&lt;/h2&gt;

&lt;p&gt;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 &lt;a href="https://gamefic.com"&gt;Gamefic&lt;/a&gt;, 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;As the static analysis improved, it seemed like a natural progression to add type checking as a diagnostics feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  How It Works
&lt;/h2&gt;

&lt;p&gt;The type checker is somewhat similar to &lt;a href="https://sorbet.org/"&gt;Sorbet&lt;/a&gt;, with the key difference being that Solargraph uses &lt;a href="https://yardoc.org"&gt;YARD&lt;/a&gt; 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.&lt;/p&gt;

&lt;p&gt;Code smells that the type checker can detect include the following:&lt;/p&gt;

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

&lt;p&gt;The type checker can run at four levels: &lt;code&gt;normal&lt;/code&gt;, &lt;code&gt;typed&lt;/code&gt;, &lt;code&gt;strict&lt;/code&gt;, and &lt;code&gt;strong&lt;/code&gt;. See the &lt;a href="https://solargraph.org/guides/type-checking"&gt;type checker documentation&lt;/a&gt; for more information about the rules enforced at each level.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Type Checker
&lt;/h2&gt;

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

&lt;h3&gt;
  
  
  The Command Line
&lt;/h3&gt;

&lt;p&gt;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 &lt;code&gt;example.rb&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Example&lt;/span&gt;
  &lt;span class="c1"&gt;# @return [String]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;foo&lt;/span&gt;
    &lt;span class="s2"&gt;"foo"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# @return [InvalidClassName]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;bar&lt;/span&gt;
    &lt;span class="s2"&gt;"bar"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="c1"&gt;# @return [Integer]&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;baz&lt;/span&gt;
    &lt;span class="s2"&gt;"baz"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;downcase&lt;/span&gt;
&lt;span class="no"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uppercase&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Run the type checker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ solargraph typecheck
./example/example.rb:8 - Unresolved return type InvalidClassName for Example#bar
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



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

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ 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.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At the &lt;code&gt;strict&lt;/code&gt; level, it will also catch the unknown &lt;code&gt;uppercase&lt;/code&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ 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.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Diagnostics in VS Code
&lt;/h3&gt;

&lt;p&gt;If you use the &lt;a href="https://marketplace.visualstudio.com/items?itemName=castwide.solargraph"&gt;Solargraph extension for VS Code&lt;/a&gt;, you can configure your editor to use the type checker for diagnostics by adding it to your project's &lt;code&gt;.solargraph.yml&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reporters:
- typecheck
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can also specify a level:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;reporters:
- typecheck:strict
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Type errors will appear in the Problems console.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4yvq8C8k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fl9yixy4ra96twdboj6r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4yvq8C8k--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/fl9yixy4ra96twdboj6r.png" alt="The Problems console"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This feature should also work in any other language client that supports diagnostics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;p&gt;Check the following links to learn more about Solargraph and try it for yourself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://solargraph.org"&gt;The Solargraph website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/castwide/solargraph"&gt;The GitHub repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=castwide.solargraph"&gt;Solargraph for VS Code&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>ruby</category>
      <category>vscode</category>
    </item>
  </channel>
</rss>
