追記(2020/02/27): セットアップ方法が変更されたので記事に反映しました
型プロファイラとは?
型プロファイラは、
型注釈がない素の Ruby プログラムを入力して、
型エラーの可能性を警告したり(Testing)、
型シグネチャのプロトタイプを生成したり(Understanding)
できるツールです
※開発者である遠藤さんのブログ記事から引用
この機能は2020年にリリースが予定されている Ruby3 の新機能の中の静的解析の一要素となっています。
その他の静的解析の情報については Ruby の型関連の情報まとめ にまとめてあるので良ければ見てください。
環境
- Ruby 2.7.0
セットアップ
$ git clone --recursive https://github.com/mame/ruby-type-profiler.git
$ cd ruby-type-profiler
$ bundle install
デモ
README の DEMO と同じものを動かしてみる。
以下のコードを ruby-type-profiler/tmp/test.rb
として保存。
def foo(x)
if x > 10
x.to_s
else
x.boo()
x + 42
end
end
foo(42)
$ cd ~/work/ruby-type-profiler
$ ./run.sh tmp/test.rb
上記を実行すると、以下のように、定義が存在しない定義が検出される。また、推定された型シグネチャも出力されている。
# Errors
tmp/test.rb:6: [error] undefined method: Integer#boo
# Classes
class Object
foo : (Integer) -> (Integer | String)
end
ここで x.boo()
の行をコメントアウトしてみると、予想通りエラーが消える。
$ ./run.sh tmp/test.rb
# Classes
class Object
foo : (Integer) -> (Integer | String)
end
次に、引数を文字列にしてみる。
def foo(x)
if x
x + '42'
else
x + 42
end
end
foo('a')
型プロファイラの実行結果は以下のようになる。
$ ./run.sh tmp/test.rb
# Errors
tmp/test.rb:6: [error] failed to resolve overload: String#+
# Classes
class Object
foo : (String) -> (String | any)
end
x が文字列のとき、 x + 42
を実行すると TypeError が発生するが、上のコードでは else ブロックに入らなくてもそれを検出できている。
引数を文字列にしたことで、推定される型が先程は Integer だったのが String に変わっている。
サンプルコード
smoke/
に大量のサンプルコードがあるので、これらで遊んでみると良さそう。
$ ./run.sh smoke/demo.rb
# Classes
class Object
foo : (FalseClass | TrueClass) -> (Integer | String)
identity : (:sym | Integer | String) -> (:sym | Integer | String)
fib : (Integer) -> Integer
end
class A
foo : (Integer | String) -> NilClass
bar : (Integer | String) -> NilClass
end
class B
bar : (Integer | String) -> NilClass
end
テスト
./smoke.sh
を利用することでテストを実行できる。
OK の場合はそれ以外表示されず、NG の場合エラー内容が表示される。
$ ./smoke.sh smoke/demo.rb
# OK: smoke/demo.rb
$ ./smoke.sh tmp/test.rb
# NG: tmp/test.rb
expected:
actual:
# Errors
tmp/test.rb:6: [error] failed to resolve overload: String#+
# Classes
class Object
foo : (String) -> (String | any)
end
参考
type-profiler のレポジトリ
https://github.com/mame/ruby-type-profiler
開発者である遠藤さんによる解説記事
https://techlife.cookpad.com/entry/2019/04/16/164858
A Static Type Analyzer of Untyped Ruby Code for Ruby 3
https://www.slideshare.net/mametter/a-static-type-analyzer-of-untyped-ruby-code-for-ruby-3