pockestrap

Web Programmer's memo

Reek 4.7.0 から、Syntax Error の扱いが変わります。

Reek 4.7.0 から、解析対象のファイルに Syntax Error が含まれている場合の挙動が変わります。

TL;DR

Syntax Error も、ひとつの警告として検出されます。

歴史

Reek における Syntax Error の扱いは、ここ最近の間に2度変更されています。

~ v4.5.6

v4.5.6 までは、Syntax Error のあるファイルがあった場合、その Syntax Error のメッセージを標準エラー出力に流していました。

例えば、syntax error が含まれる Ruby ファイルと、正常な Ruby ファイルが両方ある場合、以下のように Syntax Error を標準エラー出力に、Reek の指摘は標準出力に出ます。

$ reek _4.5.6_ syntax_error.rb valid.rb
syntax_error.rb:2:1: error: unexpected token $end
syntax_error.rb:2: 
syntax_error.rb:2: 
syntax_error.rb: Parser::SyntaxError: unexpected token $end
valid.rb -- 2 warnings:
  [1]:IrresponsibleModule: A has no descriptive comment [https://github.com/troessner/reek/blob/master/docs/Irresponsible-Module.md]
  [1]:UncommunicativeModuleName: A has the name 'A' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Module-Name.md]
2 total warnings

そのため、Reek を使用する人が Syntax Error を扱うには標準エラー出力を眺めるしかありません。 また、Reek を扱うプログラムを作成する場合(例: エディタ連携のツール、CIなど)、Syntax Error を適切にハンドリングするには標準エラー出力を適切にパースする必要があり、あまり使いやすいとは言えない状況でした。

v4.6.0 ~ v4.6.2

v4.6.0 では、この挙動が変更されました。(Re-raise parse errors by mvz · Pull Request #1185 · troessner/reek · GitHub)

v4.6.0 では、Syntax Error のあるファイルを解析した場合、例外が発生し Reek が停止します。

$ reek _4.6.0_ syntax_error.rb valid.rb
syntax_error.rb:2:1: error: unexpected token $end
syntax_error.rb:2: 
syntax_error.rb:2: 
/home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/source/source_code.rb:91:in `rescue in syntax_tree': syntax_error.rb: Parser::SyntaxError: unexpected token $end (Reek::Errors::ParseError)
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/source/source_code.rb:88:in `syntax_tree'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/examiner.rb:109:in `syntax_tree'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/examiner.rb:99:in `run'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/examiner.rb:66:in `smells'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/examiner.rb:74:in `smells_count'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/report/base_report.rb:47:in `add_examiner'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/report/text_report.rb:22:in `add_examiner'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/cli/command/report_command.rb:25:in `block in populate_reporter_with_smells'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/cli/command/report_command.rb:24:in `each'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/cli/command/report_command.rb:24:in `populate_reporter_with_smells'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/cli/command/report_command.rb:16:in `execute'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/lib/reek/cli/application.rb:28:in `execute'
    from /home/pocke/.gem/ruby/2.4.0/gems/reek-4.6.0/bin/reek:13:in `<top (required)>'
    from /home/pocke/.gem/ruby/2.4.0/bin/reek:22:in `load'
    from /home/pocke/.gem/ruby/2.4.0/bin/reek:22:in `<main>'

v4.5.6 までと比べて、Syntax Error の存在に確実に気が付けるようになりました。
ですが、一つでも Syntax Error のあるファイルが存在するとそこで解析が停止してしまうため、その他の正常な Ruby ファイルの解析結果を得ることが出来ません。

Syntax Error がある Ruby ファイルが何らかの理由でプロジェクト内に含まれていることは充分考えられます。
例えば、Redmine のレポジトリには、Ruby コードを生成する ERB テンプレートが.rb拡張子で含まれています。 https://github.com/redmine/redmine/blob/b834e81d7f41121fc6d9bef95ee090f8f466493e/lib/generators/redmine_plugin_model/templates/migration.rb

このようなケースでは Reek の解析をまともに行うことが出来ず、何らかの対処が必要となってしまいます。

v4.7.0 ~

上記の問題を解決するため、Reek v4.7.0 では Syntax Error の扱いを変更しました。

v4.7.0 では、Syntax Error のあるファイルを解析した場合、それを他の指摘と混ぜて表示します。

$ reek _4.7.0_ syntax_error.rb valid.rb
syntax_error.rb -- 1 warning:
  [2]:Syntax: This file has unexpected token $end [https://github.com/troessner/reek/blob/master/docs/Syntax.md]
valid.rb -- 2 warnings:
  [1]:IrresponsibleModule: A has no descriptive comment [https://github.com/troessner/reek/blob/master/docs/Irresponsible-Module.md]
  [1]:UncommunicativeModuleName: A has the name 'A' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Module-Name.md]
3 total warnings

Syntax Error の無いvalid.rbには通常の指摘が2つ、Syntax Error のあるsyntax_error.rbにはSyntaxという指摘が出ていることがわかると思います。

これにより Syntax Error を他の指摘と同様に扱うことが出来るため、Syntax Error のハンドリングがとてもやりやすくなります。
なお、この実装は RuboCop の実装をかなり参考にして作っています。