くりにっき

フルスタックキュアエンジニアです

YARDで継承関係を明示的に伝えたい

こないだgemを作ってて調べたやつのメモ。

前置き

例えば下記のように Hashie::Mash を継承した Pixela::Response があるとします

module Pixela
  require "hashie/mash"

  # Pixela API response
  #
  # @see https://www.rubydoc.info/gems/hashie/Hashie/Hash
  # @see https://www.rubydoc.info/gems/hashie/Hashie/Mash
  class Response < Hashie::Mash
    disable_warnings
  end
end

Hashie::Mash はさらに Hashie::HashHash を継承しているため *1、実際には「 Pixela::Response < Hashie::Mash < Hashie::Hash < Hash < Object」という継承関係になります。

これを YARD でリファレンスを生成した場合下記のように、「 Pixela::Response < Hashie::Mash < Object」という継承関係になってしまいます。

これはYARDが Hashie::Mash の実装を知らないためなんですが、3rd party製のgemの継承関係をどうやってYARDに伝えればいいか困ったので調べました。

解決方法:@!parse で書く

@!parse *2 を使うとYARDのコメントの中だけで有効なRubyのコードを書けるので、そこで外部のgemの最低限のクラス定義を書いてやれば表示されるようになります。

# @!parse
#   module Hashie
#     # @see https://www.rubydoc.info/gems/hashie/Hashie/Hash
#     class Hash < ::Hash
#     end
#
#     # @see https://www.rubydoc.info/gems/hashie/Hashie/Mash
#     class Mash < Hash
#     end
#   end

module Pixela
  require "hashie/mash"

  # Pixela API response
  #
  # @see https://www.rubydoc.info/gems/hashie/Hashie/Hash
  # @see https://www.rubydoc.info/gems/hashie/Hashie/Mash
  class Response < Hashie::Mash
    disable_warnings
  end
end

moduleの外側に書くのがポイントで、 moduleの内側に書くと class Pixela::Hashie::Mash のようなクラスのリファレンスが作られたので、 @!parse はスコープを解釈してるらしいです。

実際のパッチとYARDで生成されたリファレンスは下記