diary

I like Hatena Star with a text selection.

2019-12-30

github.com

Steepを試しにKibelaに突っ込んでいて、エラーが標準出力に出ていて邪魔だったので標準エラー出力に出すようにしてみた。


最低限クラスがあることがrbsで書かれていないと、部分的に型を書いたとしてもSteepは使い物にならなさそうなので、まずは全部のクラスの型を生成する必要がありそう。 これはruby-signatureにある適当なコマンドでいけるかな。

# Userクラスの型定義
#   class User
#     def self.find: (Integer) -> instnace
#     def name: () -> String
#   end

user = User.find(1)
user.name # これはok
user.full_name # これはNoMethodErrorがちゃんと見つかる


class UsersController
  def show
    # Userクラスがanyにfallbackしてしまう
    # 当然user変数もanyにfallbackする
    user = User.find(1) 
    user.name      # anyに対するメソッド呼び出しなのでチェックが無
    user.full_name # これもanyに対するメソッド呼び出しなのでチェックが無
  end
end

つまりなんらかのクラス定義の中にある定数参照は、外側のクラス定義が型として定義されていなければすべてanyにfallbackするので、解析が無になる。


github.com

たしかに🦀と思ったのでrevertした。勉強になった。


github.com

rbsコマンドのヘルプメッセージをいい感じにした。OptionParserではbannerに文字列をセットするといい感じにできる。


github.com

rbs prototype rbコマンドがうまく動かないので直している。 想定してないnode (今回は引数なしのFCALLとyield)にぶつかったときはまあ直せばいいので簡単。

syntax errorのコードを吐いているのがむずかしくて、typeキーワード引数があると死ぬ。というか普通の引数でも死ぬ。

class X
  # ダメ
  #
  # def foo: (type: untyped type) -> untyped
  def foo(type:)
  end

  # これもダメ
  #
  # def bar: (untyped type) -> untyped
  def bar(type)
  end
end

上のクラス定義はコメントのようにrbsが生成されるけど、rbsではtypeは予約語であり、かつvar_name_opt(うしろのtype)では予約語は許されていないので死ぬ。 keyword_name(まえのtype)では予約語が許されているからこちらはokぽい。

どうするのがいいのだろう。とりあえず次の2つは思いつく。

  • var_name_opt予約語を許す
    • とりあえずconflictを増やさず実現はできそう。
  • メソッド名みたいにbacktickでescapeできるようにする

rbs prototype rbコマンドが生成するrbsの名前を適当にunderscoreとかつけてごまかすこともできるけど、rbsを手書きする時にtypeって書きたい人もいるだろうし、書けるようになっていたほうが便利な気がするなあ。

……ということをIssueに書いた。

github.com


hanachinさんがruby-signatureに出していたPRをレビューしてた。

https://github.com/ruby/ruby-signature/pull/150#discussion_r362002475 これは型検査器がメソッドのオーバーロードを見る時に定義順で見ることをruby-signatureが前提として置いていいのか、というのが気になった。 前提としていいのならこの型定義でいいんだけど(便利)、前提にするべきでないなら壊れる可能性があるからやめたほうがよさそう。

https://github.com/ruby/ruby-signature/pull/149#discussion_r361998221 もっと狭い型を返せそうだったからコメントした


github.com

ruby_hl_lvar.vim でmassignが壊れているのを直してくれているPR。 そのうちレビューしよう…。