reek 3.6.1 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/features/command_line_interface/basic_usage.feature +8 -8
- data/features/command_line_interface/options.feature +2 -1
- data/features/command_line_interface/smell_selection.feature +1 -1
- data/features/command_line_interface/smells_count.feature +8 -8
- data/features/command_line_interface/stdin.feature +3 -3
- data/features/configuration_files/directory_specific_directives.feature +9 -9
- data/features/configuration_files/masking_smells.feature +5 -5
- data/features/configuration_loading.feature +6 -6
- data/features/programmatic_access.feature +3 -3
- data/features/rake_task/rake_task.feature +9 -9
- data/features/reports/json.feature +4 -0
- data/features/reports/reports.feature +49 -37
- data/features/reports/yaml.feature +4 -0
- data/features/samples.feature +265 -265
- data/lib/reek/cli/options.rb +5 -4
- data/lib/reek/cli/warning_collector.rb +1 -1
- data/lib/reek/report.rb +2 -1
- data/lib/reek/report/code_climate_formatter.rb +46 -0
- data/lib/reek/report/formatter.rb +13 -8
- data/lib/reek/report/report.rb +12 -0
- data/lib/reek/smells/smell_warning.rb +2 -2
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +5 -4
- data/spec/reek/report/code_climate_formatter_spec.rb +63 -0
- data/spec/reek/report/code_climate_report_spec.rb +68 -0
- data/spec/reek/report/json_report_spec.rb +18 -18
- data/spec/reek/report/yaml_report_spec.rb +17 -17
- data/spec/reek/smells/smell_warning_spec.rb +11 -11
- data/spec/samples/checkstyle.xml +1 -1
- metadata +20 -3
data/lib/reek/cli/options.rb
CHANGED
@@ -9,7 +9,7 @@ module Reek
|
|
9
9
|
#
|
10
10
|
# See {file:docs/Command-Line-Options.md} for details.
|
11
11
|
#
|
12
|
-
# :reek:TooManyInstanceVariables: { max_instance_variables:
|
12
|
+
# :reek:TooManyInstanceVariables: { max_instance_variables: 7 }
|
13
13
|
# :reek:Attribute: { enabled: false }
|
14
14
|
class Options
|
15
15
|
attr_reader :argv, :parser, :smells_to_detect
|
@@ -26,6 +26,7 @@ module Reek
|
|
26
26
|
@parser = OptionParser.new
|
27
27
|
@report_format = :text
|
28
28
|
@location_format = :numbers
|
29
|
+
@show_links = true
|
29
30
|
@smells_to_detect = []
|
30
31
|
@colored = color_support?
|
31
32
|
|
@@ -72,9 +73,9 @@ module Reek
|
|
72
73
|
def set_alternative_formatter_options
|
73
74
|
parser.separator "\nReport format:"
|
74
75
|
parser.on(
|
75
|
-
'-f', '--format FORMAT', [:html, :text, :yaml, :json, :xml],
|
76
|
+
'-f', '--format FORMAT', [:html, :text, :yaml, :json, :xml, :code_climate],
|
76
77
|
'Report smells in the given format:',
|
77
|
-
' html', ' text (default)', ' yaml', ' json', ' xml'
|
78
|
+
' html', ' text (default)', ' yaml', ' json', ' xml', ' code_climate'
|
78
79
|
) do |opt|
|
79
80
|
self.report_format = opt
|
80
81
|
end
|
@@ -112,7 +113,7 @@ module Reek
|
|
112
113
|
self.show_empty = show_empty
|
113
114
|
end
|
114
115
|
parser.on('-U', '--[no-]wiki-links',
|
115
|
-
'Show link to related wiki page for each smell (default:
|
116
|
+
'Show link to related wiki page for each smell (default: true)') do |show_links|
|
116
117
|
self.show_links = show_links
|
117
118
|
end
|
118
119
|
end
|
data/lib/reek/report.rb
CHANGED
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'codeclimate_engine'
|
2
|
+
require 'private_attr'
|
3
|
+
|
4
|
+
module Reek
|
5
|
+
module Report
|
6
|
+
# Generates a hash in the structure specified by the Code Climate engine spec
|
7
|
+
class CodeClimateFormatter
|
8
|
+
private_attr_reader :warning
|
9
|
+
|
10
|
+
def initialize(warning)
|
11
|
+
@warning = warning
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_hash
|
15
|
+
CCEngine::Issue.new(check_name: check_name,
|
16
|
+
description: description,
|
17
|
+
categories: categories,
|
18
|
+
location: location
|
19
|
+
).to_hash
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def description
|
25
|
+
[warning.context, warning.message].join(' ')
|
26
|
+
end
|
27
|
+
|
28
|
+
def check_name
|
29
|
+
[warning.smell_category, warning.smell_type].join('/')
|
30
|
+
end
|
31
|
+
|
32
|
+
def categories
|
33
|
+
# TODO: provide mappings for Reek's smell categories
|
34
|
+
['Complexity']
|
35
|
+
end
|
36
|
+
|
37
|
+
def location
|
38
|
+
warning_lines = warning.lines
|
39
|
+
CCEngine::Location::LineRange.new(
|
40
|
+
path: warning.source,
|
41
|
+
line_range: warning_lines.first..warning_lines.last
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'private_attr/everywhere'
|
2
2
|
require_relative 'location_formatter'
|
3
|
+
require_relative '../report/code_climate_formatter'
|
3
4
|
|
4
5
|
module Reek
|
5
6
|
module Report
|
@@ -9,13 +10,13 @@ module Reek
|
|
9
10
|
# passed-in warning formatter.
|
10
11
|
#
|
11
12
|
module Formatter
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
module_function
|
14
|
+
|
15
|
+
def format_list(warnings, formatter: SimpleWarningFormatter.new)
|
16
|
+
warnings.map { |warning| " #{formatter.format(warning)}" }.join("\n")
|
16
17
|
end
|
17
18
|
|
18
|
-
def
|
19
|
+
def header(examiner)
|
19
20
|
count = examiner.smells_count
|
20
21
|
result = Rainbow("#{examiner.description} -- ").cyan +
|
21
22
|
Rainbow("#{count} warning").yellow
|
@@ -42,6 +43,11 @@ module Reek
|
|
42
43
|
warning.yaml_hash
|
43
44
|
end
|
44
45
|
|
46
|
+
# :reek:UtilityFunction
|
47
|
+
def format_code_climate_hash(warning)
|
48
|
+
CodeClimateFormatter.new(warning).to_hash
|
49
|
+
end
|
50
|
+
|
45
51
|
private_attr_reader :location_formatter
|
46
52
|
end
|
47
53
|
|
@@ -53,12 +59,11 @@ module Reek
|
|
53
59
|
BASE_URL_FOR_HELP_LINK = 'https://github.com/troessner/reek/blob/master/docs/'
|
54
60
|
|
55
61
|
def format(warning)
|
56
|
-
"#{super} "
|
57
|
-
"[#{explanatory_link(warning)}]"
|
62
|
+
"#{super} [#{explanatory_link(warning)}]"
|
58
63
|
end
|
59
64
|
|
60
65
|
def format_hash(warning)
|
61
|
-
super
|
66
|
+
super.merge('wiki_link' => explanatory_link(warning))
|
62
67
|
end
|
63
68
|
|
64
69
|
private
|
data/lib/reek/report/report.rb
CHANGED
@@ -143,6 +143,18 @@ module Reek
|
|
143
143
|
end
|
144
144
|
end
|
145
145
|
|
146
|
+
#
|
147
|
+
# Displays a list of smells in Code Climate engine format
|
148
|
+
# (https://github.com/codeclimate/spec/blob/master/SPEC.md)
|
149
|
+
# JSON with empty array for 0 smells
|
150
|
+
#
|
151
|
+
class CodeClimateReport < Base
|
152
|
+
# @public
|
153
|
+
def show(out = $stdout)
|
154
|
+
out.print ::JSON.generate smells.map { |smell| warning_formatter.format_code_climate_hash(smell) }
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
146
158
|
#
|
147
159
|
# Saves the report as a HTML file
|
148
160
|
#
|
@@ -61,13 +61,13 @@ module Reek
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def base_message
|
64
|
-
"#{
|
64
|
+
"#{smell_type}: #{context} #{message}"
|
65
65
|
end
|
66
66
|
|
67
67
|
protected
|
68
68
|
|
69
69
|
def sort_key
|
70
|
-
[context, message
|
70
|
+
[smell_type, context, message]
|
71
71
|
end
|
72
72
|
|
73
73
|
private
|
data/lib/reek/version.rb
CHANGED
data/reek.gemspec
CHANGED
@@ -22,10 +22,11 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.required_ruby_version = '>= 2.0.0'
|
23
23
|
s.summary = 'Code smell detector for Ruby'
|
24
24
|
|
25
|
-
s.add_runtime_dependency '
|
26
|
-
s.add_runtime_dependency '
|
27
|
-
s.add_runtime_dependency '
|
28
|
-
s.add_runtime_dependency '
|
25
|
+
s.add_runtime_dependency 'codeclimate-engine-rb', '~> 0.1.0'
|
26
|
+
s.add_runtime_dependency 'parser', '~> 2.2', '>= 2.2.2.5'
|
27
|
+
s.add_runtime_dependency 'private_attr', '~> 1.1'
|
28
|
+
s.add_runtime_dependency 'rainbow', '~> 2.0'
|
29
|
+
s.add_runtime_dependency 'unparser', '~> 0.2.2'
|
29
30
|
|
30
31
|
s.add_development_dependency 'activesupport', '~> 4.2'
|
31
32
|
s.add_development_dependency 'aruba', '~> 0.10.0'
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
require_lib 'reek/report/code_climate_formatter'
|
3
|
+
|
4
|
+
RSpec.describe Reek::Report::CodeClimateFormatter, '#to_hash' do
|
5
|
+
it "sets the type as 'issue'" do
|
6
|
+
warning = FactoryGirl.build(:smell_warning)
|
7
|
+
issue = Reek::Report::CodeClimateFormatter.new(warning)
|
8
|
+
|
9
|
+
result = issue.to_hash
|
10
|
+
|
11
|
+
expect(result).to include(type: 'issue')
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'sets the category' do
|
15
|
+
warning = FactoryGirl.build(:smell_warning)
|
16
|
+
issue = Reek::Report::CodeClimateFormatter.new(warning)
|
17
|
+
|
18
|
+
result = issue.to_hash
|
19
|
+
|
20
|
+
expect(result).to include(categories: ['Complexity'])
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'constructs a description based on the context and message' do
|
24
|
+
warning = FactoryGirl.build(:smell_warning,
|
25
|
+
context: 'context foo',
|
26
|
+
message: 'message bar')
|
27
|
+
issue = Reek::Report::CodeClimateFormatter.new(warning)
|
28
|
+
|
29
|
+
result = issue.to_hash
|
30
|
+
|
31
|
+
expect(result).to include(
|
32
|
+
description: 'context foo message bar')
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'sets a check name based on the smell detector' do
|
36
|
+
warning = FactoryGirl.build(:smell_warning,
|
37
|
+
smell_detector: Reek::Smells::UtilityFunction.new)
|
38
|
+
issue = Reek::Report::CodeClimateFormatter.new(warning)
|
39
|
+
|
40
|
+
result = issue.to_hash
|
41
|
+
|
42
|
+
expect(result).to include(check_name: 'LowCohesion/UtilityFunction')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'sets the location' do
|
46
|
+
warning = FactoryGirl.build(:smell_warning,
|
47
|
+
lines: [1, 2],
|
48
|
+
source: 'a/ruby/source/file.rb')
|
49
|
+
issue = Reek::Report::CodeClimateFormatter.new(warning)
|
50
|
+
|
51
|
+
result = issue.to_hash
|
52
|
+
|
53
|
+
expect(result).to include(
|
54
|
+
location: {
|
55
|
+
path: 'a/ruby/source/file.rb',
|
56
|
+
lines: {
|
57
|
+
begin: 1,
|
58
|
+
end: 2
|
59
|
+
}
|
60
|
+
}
|
61
|
+
)
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
require_lib 'reek/examiner'
|
3
|
+
require_lib 'reek/report/report'
|
4
|
+
require_lib 'reek/report/formatter'
|
5
|
+
|
6
|
+
require 'json'
|
7
|
+
require 'stringio'
|
8
|
+
|
9
|
+
RSpec.describe Reek::Report::CodeClimateReport do
|
10
|
+
let(:options) { {} }
|
11
|
+
let(:instance) { Reek::Report::CodeClimateReport.new(options) }
|
12
|
+
let(:examiner) { Reek::Examiner.new(source) }
|
13
|
+
|
14
|
+
before do
|
15
|
+
instance.add_examiner examiner
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'with empty source' do
|
19
|
+
let(:source) { '' }
|
20
|
+
|
21
|
+
it 'prints empty json' do
|
22
|
+
expect { instance.show }.to output(/^\[\]$/).to_stdout
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with smelly source' do
|
27
|
+
let(:source) { 'def simple(a) a[3] end' }
|
28
|
+
|
29
|
+
it 'prints smells as json' do
|
30
|
+
out = StringIO.new
|
31
|
+
instance.show(out)
|
32
|
+
out.rewind
|
33
|
+
result = JSON.parse(out.read)
|
34
|
+
expected = JSON.parse <<-EOS
|
35
|
+
[
|
36
|
+
{
|
37
|
+
"type": "issue",
|
38
|
+
"check_name": "UncommunicativeName/UncommunicativeParameterName",
|
39
|
+
"description": "simple has the parameter name 'a'",
|
40
|
+
"categories": ["Complexity"],
|
41
|
+
"location": {
|
42
|
+
"path": "string",
|
43
|
+
"lines": {
|
44
|
+
"begin": 1,
|
45
|
+
"end": 1
|
46
|
+
}
|
47
|
+
}
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"type": "issue",
|
51
|
+
"check_name": "LowCohesion/UtilityFunction",
|
52
|
+
"description": "simple doesn't depend on instance state (maybe move it to another class?)",
|
53
|
+
"categories": ["Complexity"],
|
54
|
+
"location": {
|
55
|
+
"path": "string",
|
56
|
+
"lines": {
|
57
|
+
"begin": 1,
|
58
|
+
"end": 1
|
59
|
+
}
|
60
|
+
}
|
61
|
+
}
|
62
|
+
]
|
63
|
+
EOS
|
64
|
+
|
65
|
+
expect(result).to eq expected
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -36,20 +36,20 @@ RSpec.describe Reek::Report::JSONReport do
|
|
36
36
|
{
|
37
37
|
"context": "simple",
|
38
38
|
"lines": [1],
|
39
|
-
"message": "
|
40
|
-
"smell_category": "
|
41
|
-
"smell_type": "
|
39
|
+
"message": "has the parameter name 'a'",
|
40
|
+
"smell_category": "UncommunicativeName",
|
41
|
+
"smell_type": "UncommunicativeParameterName",
|
42
42
|
"source": "string",
|
43
|
-
"name": "
|
43
|
+
"name": "a"
|
44
44
|
},
|
45
45
|
{
|
46
46
|
"context": "simple",
|
47
47
|
"lines": [1],
|
48
|
-
"message": "
|
49
|
-
"smell_category": "
|
50
|
-
"smell_type": "
|
48
|
+
"message": "doesn't depend on instance state (maybe move it to another class?)",
|
49
|
+
"smell_category": "LowCohesion",
|
50
|
+
"smell_type": "UtilityFunction",
|
51
51
|
"source": "string",
|
52
|
-
"name": "
|
52
|
+
"name": "simple"
|
53
53
|
}
|
54
54
|
]
|
55
55
|
EOS
|
@@ -67,16 +67,6 @@ RSpec.describe Reek::Report::JSONReport do
|
|
67
67
|
result = JSON.parse(out.read)
|
68
68
|
expected = JSON.parse <<-EOS
|
69
69
|
[
|
70
|
-
{
|
71
|
-
"context": "simple",
|
72
|
-
"lines": [1],
|
73
|
-
"message": "doesn't depend on instance state (maybe move it to another class?)",
|
74
|
-
"smell_category": "LowCohesion",
|
75
|
-
"smell_type": "UtilityFunction",
|
76
|
-
"source": "string",
|
77
|
-
"name": "simple",
|
78
|
-
"wiki_link": "https://github.com/troessner/reek/blob/master/docs/Utility-Function.md"
|
79
|
-
},
|
80
70
|
{
|
81
71
|
"context": "simple",
|
82
72
|
"lines": [1],
|
@@ -86,6 +76,16 @@ RSpec.describe Reek::Report::JSONReport do
|
|
86
76
|
"source": "string",
|
87
77
|
"name": "a",
|
88
78
|
"wiki_link": "https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Parameter-Name.md"
|
79
|
+
},
|
80
|
+
{
|
81
|
+
"context": "simple",
|
82
|
+
"lines": [1],
|
83
|
+
"message": "doesn't depend on instance state (maybe move it to another class?)",
|
84
|
+
"smell_category": "LowCohesion",
|
85
|
+
"smell_type": "UtilityFunction",
|
86
|
+
"source": "string",
|
87
|
+
"name": "simple",
|
88
|
+
"wiki_link": "https://github.com/troessner/reek/blob/master/docs/Utility-Function.md"
|
89
89
|
}
|
90
90
|
]
|
91
91
|
EOS
|
@@ -33,14 +33,6 @@ RSpec.describe Reek::Report::YAMLReport do
|
|
33
33
|
result = YAML.load(out.read)
|
34
34
|
expected = YAML.load <<-EOS
|
35
35
|
---
|
36
|
-
- context: "simple"
|
37
|
-
lines:
|
38
|
-
- 1
|
39
|
-
message: "doesn't depend on instance state (maybe move it to another class?)"
|
40
|
-
smell_category: "LowCohesion"
|
41
|
-
smell_type: "UtilityFunction"
|
42
|
-
source: "string"
|
43
|
-
name: "simple"
|
44
36
|
- context: "simple"
|
45
37
|
lines:
|
46
38
|
- 1
|
@@ -49,6 +41,14 @@ RSpec.describe Reek::Report::YAMLReport do
|
|
49
41
|
smell_type: "UncommunicativeParameterName"
|
50
42
|
source: "string"
|
51
43
|
name: "a"
|
44
|
+
- context: "simple"
|
45
|
+
lines:
|
46
|
+
- 1
|
47
|
+
message: "doesn't depend on instance state (maybe move it to another class?)"
|
48
|
+
smell_category: "LowCohesion"
|
49
|
+
smell_type: "UtilityFunction"
|
50
|
+
source: "string"
|
51
|
+
name: "simple"
|
52
52
|
EOS
|
53
53
|
|
54
54
|
expect(result).to eq expected
|
@@ -63,15 +63,6 @@ RSpec.describe Reek::Report::YAMLReport do
|
|
63
63
|
result = YAML.load(out.read)
|
64
64
|
expected = YAML.load <<-EOS
|
65
65
|
---
|
66
|
-
- context: "simple"
|
67
|
-
lines:
|
68
|
-
- 1
|
69
|
-
message: "doesn't depend on instance state (maybe move it to another class?)"
|
70
|
-
smell_category: "LowCohesion"
|
71
|
-
smell_type: "UtilityFunction"
|
72
|
-
source: "string"
|
73
|
-
name: "simple"
|
74
|
-
wiki_link: "https://github.com/troessner/reek/blob/master/docs/Utility-Function.md"
|
75
66
|
- context: "simple"
|
76
67
|
lines:
|
77
68
|
- 1
|
@@ -81,6 +72,15 @@ RSpec.describe Reek::Report::YAMLReport do
|
|
81
72
|
source: "string"
|
82
73
|
name: "a"
|
83
74
|
wiki_link: "https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Parameter-Name.md"
|
75
|
+
- context: "simple"
|
76
|
+
lines:
|
77
|
+
- 1
|
78
|
+
message: "doesn't depend on instance state (maybe move it to another class?)"
|
79
|
+
smell_category: "LowCohesion"
|
80
|
+
smell_type: "UtilityFunction"
|
81
|
+
source: "string"
|
82
|
+
name: "simple"
|
83
|
+
wiki_link: "https://github.com/troessner/reek/blob/master/docs/Utility-Function.md"
|
84
84
|
EOS
|
85
85
|
|
86
86
|
expect(result).to eq expected
|