No day younger than today

RubyとかRailsとか蒙古タンメンとか

RBS の CLI コマンドをざっくりながめる

こんにちは、ふーが です。
この記事はぼくの勤務先である永和システムマネジメントで開催している ESM Advent Calendar 2022 の 4 日目の記事です。

さて、rbsリポジトリを眺めていたら、README に使ったことのないコマンドがいくつも書いてあることに気が付きました。

$ rbs version
$ rbs list
$ rbs ancestors ::Object
$ rbs methods ::Object
$ rbs method Object then

github.com

とても今更ですがそれぞれどんなコマンドなのか見てみます。
rbs のバージョンは 2.8.1 で試します。

$ rbs -v
rbs 2.8.1

rbs version

実行結果:

$ rbs version
rbs 2.8.1

これはそのまんまですね。バージョン番号が出力されます。

RBS::CLI#run に定義されていて、実装はこのあたりです。 github.com

rbs list

実行結果:

$ rbs list
::Array (class)
::BasicObject (class)
::Binding (class)
::Class (class)
::Comparable (module)
::Complex (class)
::Dir (class)
.
.
()

型定義されている Class, Module, Interface が出力されます。

引数として --class のように指定ができて、指定されたもののみ出力されるようにできます。 例えば以下なら、型定義のうち Class と Module のみ出力されるようにする、といった具合です。

# Interface は出力されない
$ rbs list --class --module

rbs ancestors

実行結果:

$ rbs ancestors ::Object
::Object
::Kernel
::BasicObject

引数で指定した Class, Module の(自身を含む)祖先が出力されます。
オプションとして --singleton , --instance があり、デフォルトでは --instance を指定したことになります。 --singleton を指定すると singleton クラスを含んだ結果が出力されます。

$ rbs ancestors --singleton ::Object
singleton(::Object)
singleton(::BasicObject)
::Class
::Module
::Object
::Kernel
::BasicObject

実装はこの辺からです。 github.com

rbs methods

実行結果:

$ rbs methods ::Object
! (public)
!= (public)
!~ (public)
<=> (public)
== (public)
=== (public)
=~ (public)
Array (private)
.
.
()

引数で指定した Class, Module のメソッドの一覧を可視性付きで出力します。
オプションの --instance--singleton については rbs ancestors コマンドと同じ意味合いのようですが、こちらのコマンドには --inherit, --no-inherit というオプションもあります。 --inherit オプションは super class や mix-in した Module で定義されているメソッドについても出力します。これはデフォルトの動作です。 --no-inherit オプションはその逆で、それらのメソッドについては出力しません。

実装はこの辺からです。 github.com

rbs method

実行結果:

$ rbs method String to_i
::String#to_i
  defined_in: ::String
  implementation: ::String
  accessibility: public
  types:
      (?::int base) -> ::Integer

第一引数に Class (Module)、第二引数にメソッド名を渡すことで、そのメソッドの型定義情報が出力されます。定義元や可視性、型情報などが出力されています。 こちらもオプションは --instance--singleton があり、--instance がデフォルトです。

実装はこの辺からです。 github.com

おわりに

クラスやメソッドの型定義を出力できるコマンド類があることを知り「これを使って型と実装の乖離を検知できたりしないかな」と思ったのですが、実装を読んでみると標準ライブラリと gem の型定義のみを読み込んで出力しているようでした(たぶん。違ったら教えてください)。つまり自分で定義した sig/ 以下にあるような型定義は対象外っぽい…。

COMMANDS の配列 を見る限り他にもまだコマンドがあるようなので、折を見てそちらもどんなコマンドなのかを追ってみたいと思います。