Goの構造体にjsonタグをつけたりするときに便利な、mattn/vim-goaddtagsというプラグインがある。 いつも便利に使っているのだが、いくつかのケースで構造体の中にカーソルがあるにも関わらず offset is not inside a structエラーになることがあったので調査した。 その結果、Vim本体のバグが原因だったのでメモしておく。なお、現在は修正されている。

offset is not inside a struct の原因

issue1

原因は、Vimのバッファの先頭から{lnum}行目までのバイト数を返す line2byte() 関数の結果が不正な値になるケースがあることだった。 そのケースは以下のようなものである。

  1. バッファが400行以上
  2. 400行目以前にテキストプロパティが設定されている
  3. line2byteに400行目より後の行数を渡す

自分は補完などにvim-lspを使っていて、これが有効だとすべての行にテキストプロパティが設定されるので、条件を満たしていた。

このバグはissueを作成したら、すぐに修正された。 https://github.com/vim/vim/issues/8759

400行ごとに分割してバイト数計算しているみたいで、その際のテキストプロパティの考慮が不十分だったようだ。

このissueの修正リリースはVim v8.2.3348である。

issue2

これで直ったかと思いきや、別のケースを見つけてしまった。 条件は以下である。

  1. バッファが520行以上
  2. 400行目以前にテキストプロパティが設定されている。
  3. line2byteに400行目より後の行数を渡す

このバグもissueを作成し、修正された。 https://github.com/vim/vim/issues/8772

このissueの修正リリースはVim v8.2.3372 である。

GoAddTagsが正しく動くVimのバージョン

結論、mattn/vim-goaddtagsで正しくGoの構造体にタグを付与できるVim のバージョンは本体のline2byte() 関数のバグが修正されたv8.2.3372以降ということになる。

issueに書いた再現スクリプトのパラメータをもっと大きいものにしてみたりしたが正しい値が返ってきたので、 このバージョンからは大丈夫そうだ。

Vimは開発が活発で報告するとこういうのはすぐ修正されて助かる。