環境
項目 | バージョン |
---|---|
OS | Mac Catalina 10.15.6 |
Visual Studio Code | 1.49.0 |
Ruby | 2.7.1 |
Rubyのバージョン管理として、 rbenv を使用していた
前提
デバッグに必要な gem は Gemfile に追加しており、インストール済みの状態だった
gem "ruby-debug-ide"
gem "debase"
エラー
Visual Studio Code 左側の Run を選択し、 [Add Config] -> [RSpec - active spec file only] を選ぶ
上記の設定でデバッグしたところ、画面下のステータスバーが実行中を示すオレンジ色のまま、何も進まない状態になった
ReRunすると下記のように [OUTPUT] ビューに以下のエラーが出力される
Uncaught exception: /Users/pldb/.rbenv/shims/rspec:3: syntax error, unexpected tSTRING_BEG, expecting do or '{' or '('
[ -n "$RBENV_DEBUG" ] && set -x
^
/Users/pldb/.rbenv/shims/rspec:3: syntax error, unexpected ']', expecting end-of-input
[ -n "$RBENV_DEBUG" ] && set -x
^
/Users/pldb/.rbenv/versions/2.6.6/bin/rdebug-ide:23:in `load': /Users/pldb/.rbenv/shims/rspec:3: syntax error, unexpected tSTRING_BEG, expecting do or '{' or '(' (SyntaxError)
[ -n "$RBENV_DEBUG" ] && set -x
^
/Users/pldb/.rbenv/shims/rspec:3: syntax error, unexpected ']', expecting end-of-input
[ -n "$RBENV_DEBUG" ] && set -x
^
from /Users/pldb/.rbenv/versions/2.6.6/bin/rdebug-ide:23:in `<main>'
結果
.vscode/launch.json を以下のように変更した
変更前
{
"version": "0.2.0",
"configurations": [
{
"name": "RSpec - active spec file only",
"type": "Ruby",
"request": "launch",
"program": "/Users/pldb/.rbenv/shims/rspec",
"args": [
"-I",
"${workspaceRoot}",
"${file}"
]
}
]
}
変更後
{
"version": "0.2.0",
"configurations": [
{
"name": "RSpec - active spec file only",
"type": "Ruby",
"request": "launch",
"program": "${workspaceRoot}/bin/rspec",
"args": [
"-I",
"${workspaceRoot}",
"${file}"
]
}
]
}
これは Visual Studio Code のデフォルト設定そのままである
ただし、binstub を使用した
原因
launch.json を生成した時点の "program"
は "${workspaceRoot}/bin/rspec"
だった
ところが使用しているrspecのパスが正しいものと考えて以下のパスに差し替えた
% which rspec
/Users/pldb/.rbenv/shims/rspec
表題のエラーはこれによって発生した
参考: rspec doesn't execute as a program, it is parsed as if it's a code file.
実際に参照していた shims配下のrspec の中身はこれである
#!/usr/bin/env bash
set -e
[ -n "$RBENV_DEBUG" ] && set -x
program="${0##*/}"
if [ "$program" = "ruby" ]; then
for arg; do
case "$arg" in
-e* | -- ) break ;;
*/* )
if [ -f "$arg" ]; then
export RBENV_DIR="${arg%/*}"
break
fi
;;
esac
done
fi
export RBENV_ROOT="/Users/pldb/.rbenv"
exec "/usr/local/Cellar/rbenv/1.1.2/libexec/rbenv" exec "$program" "$@"
これはrbenvが生成した(rspecを参照するための)bashファイルであり、これをそのまま読み込んだ結果エラーになっていた
つまり rspec を十分に理解していないことが原因であった
対策
binstub を使用する
参考: 【翻訳+解説】binstubをしっかり理解する: RubyGems、rbenv、bundlerの挙動
プロジェクト内で使用するrspecにするために、 binstub で ${workspaceRoot}/bin/rspec
を生成する
${workspaceRoot}
はVisual Studio Code で展開したディレクトリのフォルダを指す
このディレクトリまで移動してから以下を実行する
% bundle binstubs rspec-core
% ./bin/rspec -v
RSpec 3.9
- rspec-core 3.9.2
- rspec-expectations 3.9.2
- rspec-mocks 3.9.1
- rspec-support 3.9.3
これでデフォルトの設定のまま実行できる
gem を作成している場合は、(他コントリビュータに影響しないよう)binフォルダを避ける
% bundle binstubs rspec-core --path exe
% ./exe/rspec -v
RSpec 3.9
- rspec-core 3.9.2
- rspec-expectations 3.9.2
- rspec-mocks 3.9.1
- rspec-support 3.9.3
この場合は launch.json の "program"
のパスが ${workspaceRoot}/exe/rspec
になる
余禄
プロジェクトの rspec のバージョンに拘らない場合は、以下のように /usr/local/bin/rsepc
を指定しても動作する
{
"version": "0.2.0",
"configurations": [
{
"name": "RSpec - active spec file only",
"type": "Ruby",
"request": "launch",
"program": "/usr/local/bin/rspec",
"args": [
"-I",
"${workspaceRoot}",
"${file}"
]
}
]
}
それと、これは別件ではあるが、 launch.json の設定に関してもう一つ取り上げる
gemspec でエンコーディングのエラーが発生した
Uncaught exception:
[!] There was an error parsing `Gemfile`:
[!] There was an error while loading `xxx.gemspec`: invalid byte sequence in US-ASCII. Bundler cannot continue.
見ての通り、エンコーディングの設定が原因である
参考: Encoding issue when using gem 'xcodeproj'
gem 開発時にデバッグする場合の launch.json は、最終的に以下のようになった
{
"version": "0.2.0",
"configurations": [
{
"name": "RSpec - active spec file only",
"type": "Ruby",
"request": "launch",
"program": "${workspaceRoot}/exe/rspec",
"args": [
"-I",
"${workspaceRoot}",
"${file}"
],
"env": {
"LANG": "en_US.UTF-8",
"LC_COLLATE": "en_US.UTF-8",
"LC_CTYPE": "en_US.UTF-8",
"LC_MESSAGES": "en_US.UTF-8",
"LC_MONETARY": "en_US.UTF-8",
"LC_NUMERIC": "en_US.UTF-8",
"LC_TIME": "en_US.UTF-8",
"LC_ALL": "en_US.UTF-8"
}
}
]
}