Skip to content

Commit

Permalink
[Fix rubocop#2481] Add WorstOffendersFormatter
Browse files Browse the repository at this point in the history
As requested by Ben Nelson, this formatter lists all the offensive files in
the inspected project, with the most offensive ones first. Output looks like:

    4  test1.rb
    2  test2.rb
    1  test3.rb
    --
    7  Total
  • Loading branch information
alexdowad committed Jan 1, 2016
1 parent 7181b7c commit b266246
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
* [#2399](https://github.com/bbatsov/rubocop/issues/2399): New `start_of_line` style for `Lint/EndAlignment` aligns a closing `end` keyword with the start of the line where the opening keyword appears. ([@alexdowad][])
* [#1545](https://github.com/bbatsov/rubocop/issues/1545): New `Regex` config parameter for `Style/FileName` allows user to provide their own regex for validating file names. ([@alexdowad][])
* [#2253](https://github.com/bbatsov/rubocop/issues/2253): New `DefaultFormatter` config parameter can be used to set formatter from within .rubocop.yml. ([@alexdowad][])
* [#2481](https://github.com/bbatsov/rubocop/issues/2481): New `WorstOffendersFormatter` prints a list of files with offenses (and offense counts), showing the files with the most offenses first. ([@alexdowad][])

### Bug Fixes

Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -763,6 +763,19 @@ $ rubocop --format offenses
134 Total
```

### Worst Offenders Formatter

Similar to the Offense Count formatter, but lists the files which need the most attention:

```sh
$ rubocop --format worst
89 this/file/is/really/bad.rb
2 much/better.rb
--
91 Total
```

### HTML Formatter

Useful for CI environments. It will create an HTML report like [this](http://f.cl.ly/items/0M3029412x3O091a1X1R/expected.html).
Expand Down
1 change: 1 addition & 0 deletions lib/rubocop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,7 @@
require 'rubocop/formatter/html_formatter'
require 'rubocop/formatter/file_list_formatter'
require 'rubocop/formatter/offense_count_formatter'
require 'rubocop/formatter/worst_offenders_formatter'
require 'rubocop/formatter/formatter_set'

require 'rubocop/cached_data'
Expand Down
3 changes: 2 additions & 1 deletion lib/rubocop/formatter/formatter_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class FormatterSet < Array
'html' => HTMLFormatter,
'files' => FileListFormatter,
'offenses' => OffenseCountFormatter,
'disabled' => DisabledLinesFormatter
'disabled' => DisabledLinesFormatter,
'worst' => WorstOffendersFormatter
}

FORMATTER_APIS = [:started, :finished]
Expand Down
60 changes: 60 additions & 0 deletions lib/rubocop/formatter/worst_offenders_formatter.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# encoding: utf-8

require 'pathname'

module RuboCop
module Formatter
# This formatter displays the list of offensive files, sorted by number of
# offenses with the worst offenders first.
#
# Here's the format:
#
# 26 this/file/is/really/bad.rb
# 3 just/ok.rb
# --
# 29 Total
class WorstOffendersFormatter < BaseFormatter
attr_reader :offense_counts

def started(target_files)
super
@offense_counts = {}
end

def file_finished(file, offenses)
unless offenses.empty?
path = Pathname.new(file).relative_path_from(Pathname.new(Dir.pwd))
@offense_counts[path] = offenses.size
end
end

def finished(_inspected_files)
report_summary(@offense_counts)
end

def report_summary(offense_counts)
per_file_counts = ordered_offense_counts(offense_counts)
total_count = total_offense_count(offense_counts)

output.puts

per_file_counts.each do |file_name, count|
output.puts "#{count.to_s.ljust(total_count.to_s.length + 2)}" \
"#{file_name}\n"
end
output.puts '--'
output.puts "#{total_count} Total"

output.puts
end

def ordered_offense_counts(offense_counts)
Hash[offense_counts.sort_by { |k, v| [-v, k] }]
end

def total_offense_count(offense_counts)
offense_counts.values.inject(0, :+)
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ module OptionsHelp
' [h]tml',
' [fi]les',
' [o]ffenses',
' [w]orst',
' custom formatter class name'],
out: ['Write output to a file instead of STDOUT.',
'This option applies to the previously',
Expand Down
43 changes: 43 additions & 0 deletions spec/rubocop/formatter/worst_offenders_formatter_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# encoding: utf-8

require 'spec_helper'

module RuboCop
module Formatter
describe WorstOffendersFormatter do
subject(:formatter) { described_class.new(output) }
let(:output) { StringIO.new }

let(:files) do
%w(lib/rubocop.rb spec/spec_helper.rb bin/rubocop).map do |path|
File.expand_path(path)
end
end

describe '#finished' do
context 'when there are many offenses' do
let(:offense) { double('offense', cop_name: 'SomeCop') }

before do
formatter.started(files)
files.each_with_index do |file, index|
formatter.file_finished(file, [offense] * (index + 2))
end
end

it 'sorts by offense count first and then by cop name' do
formatter.finished(files)
expect(output.string).to eq(['',
'4 bin/rubocop',
'3 spec/spec_helper.rb',
'2 lib/rubocop.rb',
'--',
'9 Total',
'',
''].join("\n"))
end
end
end
end
end
end
1 change: 1 addition & 0 deletions spec/rubocop/options_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def abs(path)
[h]tml
[fi]les
[o]ffenses
[w]orst
custom formatter class name
-o, --out FILE Write output to a file instead of STDOUT.
This option applies to the previously
Expand Down

0 comments on commit b266246

Please sign in to comment.