【Otemachi.rb#12】Atomでrubocop-auto-correctを使う際の注意点
自己紹介
堀崎誠治
- https://qiita.com/horisakis
- https://twitter.com/horisakis
- 昔はCとかC++とか(もう書けない。。)エクセルお絵描きマンとか
- Ruby,Rails歴はPGスクール半年と業務委託3ヶ月
事の始まり
Otemachi.rb #10でボッチ演算子を知ったので使ってみたところ、rubocop-auto-correctが反応しなくなった。
rubocop-auto-correct
Atomの拡張機能。
Atom上でrubocopを-aオプションで実行してくれる。
(ファイル保存時に実行する設定もできる)
期待する動作
実際の動作
無反応。。
設定を変更して情報を増やす
Ruby2.2で動作してる
(ボッチ演算子は2.3から)
RubocopのRubyバージョン特定方法
rubocopがrubyのバージョンを特定する優先順位は以下のとおり。
.rubocop.ymlのTargetRubyVersion の値 >
.ruby-versionの値 >
Gemfile.lockのRubyバージョンの値 >
デフォルト値(2.2)
当時の環境
- .rubocop.ymlなし
$ ls .rubocop.yml ~/.rubocop.yml
ls: .rubocop.yml: No such file or directory
ls: /Users/user/.rubocop.yml: No such file or directory
- .ruby-veversionあり
$ cat .ruby-version
2.3.1
- Gemfile.lockにrubyのバージョン指定なし
$ grep -A 1 "RUBY VERSION" Gemfile.lock | wc -l
0
手動で実行してみる
$ rubocop -a sample.rb
Inspecting 1 file
C
Offenses:
sample.rb:1:1: C: [Corrected] Style/FrozenStringLiteralComment: Missing magic comment # frozen_string_literal: true.
def sample(sample_arg)
^
1 file inspected, 1 offense detected, 1 offense corrected
手動なら動くので、拡張機能での実行時との差分を詰めていく
rubocop-auto-correctの実装
autoCorrectBuffer: (editor) ->
buffer = editor.getBuffer()
tempFilePath = @makeTempFile("rubocop.rb")
fs.writeFileSync(tempFilePath, buffer.getText())
rubocopCommand = @rubocopCommand()
command = rubocopCommand[0]
args = rubocopCommand[1]
.concat(['-a', tempFilePath])
.concat(@rubocopConfigPath(buffer.getPath()))
which command, (err) =>
return @rubocopNotFoundError() if (err)
rubocop = spawnSync(command, args, { encoding: 'utf-8', timeout: 5000 })
ログを埋め込んでみる
args = rubocopCommand[1]
.concat(['-a', tempFilePath])
.concat(@rubocopConfigPath(buffer.getPath()))
//ログ埋め込み
console.log (command + " " + args.join(" "))
実行されたコマンド
- rubocop.ymlなし
/Users/user/.anyenv/envs/rbenv/shims/rubocop --format json -a /var/folders/09/xr1wrst90lb_295d2pprm6f80000gn/T/d-118916-6808-ed0mea.2qqbj/rubocop.rb
- rubocop.ymlあり
/Users/user/.anyenv/envs/rbenv/versions/2.5.1/bin/rubocop --format json -a /var/folders/09/xr1wrst90lb_295d2pprm6f80000gn/T/d-1181111-42791-1nbrcij.sdpz/rubocop.rb --config /Users/user/develop/work/qiita/rubocop_auto/.rubocop.yml
- HOMEディレクトリにのみ.rubocop.ymlあり
/Users/user/.anyenv/envs/rbenv/versions/2.5.1/bin/rubocop --format json -a /var/folders/09/xr1wrst90lb_295d2pprm6f80000gn/T/d-1181111-42791-qw10yv.5336/rubocop.rb --config /Users/user/.rubocop.yml
Rubocopの実装
def target_ruby_version
@target_ruby_version ||=
if for_all_cops['TargetRubyVersion']
@target_ruby_version_source = :rubocop_yml
for_all_cops['TargetRubyVersion']
elsif target_ruby_version_from_version_file
@target_ruby_version_source = :ruby_version_file
target_ruby_version_from_version_file
elsif target_ruby_version_from_bundler_lock_file
@target_ruby_version_source = :bundler_lock_file
target_ruby_version_from_bundler_lock_file
else
DEFAULT_RUBY_VERSION
end
end
def target_ruby_version_from_version_file
file = ruby_version_file
return unless file && File.file?(file)
@target_ruby_version_from_version_file ||=
File.read(file).match(/\A(ruby-)?(?<version>\d+\.\d+)/) do |md|
md[:version].to_f
end
end
def ruby_version_file
@ruby_version_file ||=
find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters)
end
def ruby_version_file
@ruby_version_file ||=
find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters)
end
# Paths specified in configuration files starting with .rubocop are
# relative to the directory where that file is. Paths in other config files
# are relative to the current directory. This is so that paths in
# config/default.yml, for example, are not relative to RuboCop's config
# directory since that wouldn't work.
def base_dir_for_path_parameters
@base_dir_for_path_parameters ||=
if File.basename(loaded_path).start_with?('.rubocop') &&
loaded_path != File.join(Dir.home, ConfigLoader::DOTFILE)
File.expand_path(File.dirname(loaded_path))
else
Dir.pwd
end
end
ログを仕込んでみる
File.open("/Users/user/rubocop_auto.out", "a") {|f|
f.puts "Dir.pwd: #{Dir.pwd}"
}
結果
/Users/user/rubocop_auto.out
Dir.pwd: /
rootディレクトリから実行されていたので設定ファイルが見つけられていなかった
あれ?
File.basename(loaded_path).start_with?('.rubocop')
.rubocopで始まるファイルさえあればいい
$ wc -l .rubocop.yml
0 .rubocop.yml
$ cat .ruby-version
2.3.1
Dir.pwd: /
File.basename(loaded_path).start_with?('.rubocop')
$ wc -l .rubocop.yml
0 .rubocop.yml
$ cat .ruby-version
2.3.1
動いた!
調査結果
ファイル | 結果 | ファイル | 結果 | ||
---|---|---|---|---|---|
1 | .rubocop.yml | ○ | 6 | 1+3 | ○ |
2 | ~/.rubocop.yml | × | 7 | 1+4 | ○ |
3 | .ruby-version | × | 8 | 1+5 | ○ |
4 | ~/.ruby-version | × | 9 | 2+3 | × |
5 | Gemfile.lock | × | 10 | 2+4 | × |
11 | 2+5 | × |
※6~11の.rubocop.ymlは空ファイル
まとめ
- --configオプションを指定しない場合はカレントディレクトリからファイルを探す。
- atomから見たカレントディレクトリはrootディレクトリ。
- プロジェクトディレクトリに.rubocop.ymlを配置する以外の手段は不可。
- 拡張機能側で~/.rubocop.ymlを探してコマンドに渡しているがコマンド側で受け付けていない。(コマンド側の動きが変わった?)
- rbenvを使っているならtouch .rubocop.ymlするだけで使える。
- とはいえデフォルト設定ではrubocopの指摘は厳しいので.rubocop.ymlは設定したほうがいい。
参考
- RuboCopが静的解析のRubyバージョンを決める流れ
Author And Source
この問題について(【Otemachi.rb#12】Atomでrubocop-auto-correctを使う際の注意点), 我々は、より多くの情報をここで見つけました https://qiita.com/horisakis/items/cb2b9f3d5da6ea79c4c9著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .