reek 1.6.6 → 2.0.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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +6 -9
  3. data/features/command_line_interface/options.feature +20 -16
  4. data/features/command_line_interface/stdin.feature +1 -1
  5. data/features/rake_task/rake_task.feature +0 -12
  6. data/features/reports/reports.feature +63 -23
  7. data/features/reports/yaml.feature +3 -3
  8. data/features/samples.feature +3 -3
  9. data/lib/reek/cli/application.rb +5 -5
  10. data/lib/reek/cli/input.rb +1 -1
  11. data/lib/reek/cli/option_interpreter.rb +77 -0
  12. data/lib/reek/cli/options.rb +89 -82
  13. data/lib/reek/cli/report/formatter.rb +33 -24
  14. data/lib/reek/cli/report/heading_formatter.rb +45 -0
  15. data/lib/reek/cli/report/location_formatter.rb +23 -0
  16. data/lib/reek/cli/report/report.rb +32 -17
  17. data/lib/reek/configuration/app_configuration.rb +2 -2
  18. data/lib/reek/configuration/configuration_file_finder.rb +10 -10
  19. data/lib/reek/core/smell_repository.rb +3 -28
  20. data/lib/reek/rake/task.rb +35 -76
  21. data/lib/reek/smell_warning.rb +31 -16
  22. data/lib/reek/smells/nested_iterators.rb +1 -1
  23. data/lib/reek/smells/smell_detector.rb +9 -0
  24. data/lib/reek/smells/utility_function.rb +2 -1
  25. data/lib/reek/spec/should_reek.rb +0 -3
  26. data/lib/reek/spec/should_reek_of.rb +61 -12
  27. data/lib/reek/spec/should_reek_only_of.rb +12 -10
  28. data/lib/reek/version.rb +1 -1
  29. data/reek.gemspec +2 -2
  30. data/spec/factories/factories.rb +2 -5
  31. data/spec/reek/cli/html_report_spec.rb +28 -0
  32. data/spec/reek/cli/option_interperter_spec.rb +14 -0
  33. data/spec/reek/cli/text_report_spec.rb +95 -0
  34. data/spec/reek/cli/yaml_report_spec.rb +23 -0
  35. data/spec/reek/configuration/configuration_file_finder_spec.rb +5 -6
  36. data/spec/reek/core/module_context_spec.rb +1 -1
  37. data/spec/reek/core/smell_repository_spec.rb +17 -0
  38. data/spec/reek/smell_warning_spec.rb +9 -11
  39. data/spec/reek/smells/boolean_parameter_spec.rb +11 -11
  40. data/spec/reek/smells/control_parameter_spec.rb +40 -40
  41. data/spec/reek/smells/data_clump_spec.rb +17 -17
  42. data/spec/reek/smells/duplicate_method_call_spec.rb +56 -33
  43. data/spec/reek/smells/feature_envy_spec.rb +44 -40
  44. data/spec/reek/smells/irresponsible_module_spec.rb +1 -1
  45. data/spec/reek/smells/long_parameter_list_spec.rb +12 -12
  46. data/spec/reek/smells/long_yield_list_spec.rb +4 -4
  47. data/spec/reek/smells/module_initialize_spec.rb +3 -3
  48. data/spec/reek/smells/nested_iterators_spec.rb +71 -52
  49. data/spec/reek/smells/nil_check_spec.rb +6 -6
  50. data/spec/reek/smells/prima_donna_method_spec.rb +2 -2
  51. data/spec/reek/smells/too_many_statements_spec.rb +34 -34
  52. data/spec/reek/smells/uncommunicative_method_name_spec.rb +1 -1
  53. data/spec/reek/smells/uncommunicative_module_name_spec.rb +7 -3
  54. data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +12 -12
  55. data/spec/reek/smells/uncommunicative_variable_name_spec.rb +28 -38
  56. data/spec/reek/smells/unused_parameters_spec.rb +16 -17
  57. data/spec/reek/smells/utility_function_spec.rb +21 -8
  58. data/spec/reek/spec/should_reek_of_spec.rb +18 -5
  59. data/spec/reek/spec/should_reek_only_of_spec.rb +7 -1
  60. data/spec/spec_helper.rb +22 -14
  61. metadata +15 -20
  62. data/lib/reek/cli/help_command.rb +0 -15
  63. data/lib/reek/cli/report/strategy.rb +0 -64
  64. data/lib/reek/cli/version_command.rb +0 -16
  65. data/spec/matchers/smell_of_matcher.rb +0 -95
  66. data/spec/reek/cli/help_command_spec.rb +0 -25
  67. data/spec/reek/cli/report_spec.rb +0 -132
  68. data/spec/reek/cli/version_command_spec.rb +0 -31
@@ -8,7 +8,7 @@ describe ShouldReekOnlyOf do
8
8
  before :each do
9
9
  @expected_smell_type = :NestedIterators
10
10
  @expected_context_name = 'SmellyClass#big_method'
11
- @matcher = ShouldReekOnlyOf.new(@expected_smell_type, [/#{@expected_context_name}/])
11
+ @matcher = ShouldReekOnlyOf.new(@expected_smell_type)
12
12
  @examiner = double('examiner').as_null_object
13
13
  expect(@examiner).to receive(:smells) { smells }
14
14
  @match = @matcher.matches_examiner?(@examiner)
@@ -18,14 +18,17 @@ describe ShouldReekOnlyOf do
18
18
  it 'does not match' do
19
19
  expect(@match).to be_falsey
20
20
  end
21
+
21
22
  context 'when a match was expected' do
22
23
  before :each do
23
24
  @source = 'the_path/to_a/source_file.rb'
24
25
  expect(@examiner).to receive(:description).and_return(@source)
25
26
  end
27
+
26
28
  it 'reports the source' do
27
29
  expect(@matcher.failure_message).to match(@source)
28
30
  end
31
+
29
32
  it 'reports the expected smell class' do
30
33
  expect(@matcher.failure_message).to match(@expected_smell_type.to_s)
31
34
  end
@@ -86,12 +89,15 @@ describe ShouldReekOnlyOf do
86
89
  [build(:smell_warning, smell_detector: detector,
87
90
  message: "message mentioning #{@expected_context_name}")]
88
91
  end
92
+
89
93
  it 'matches' do
90
94
  expect(@match).to be_truthy
91
95
  end
96
+
92
97
  it 'reports the expected smell when no match was expected' do
93
98
  expect(@matcher.failure_message_when_negated).to match(@expected_smell_type.to_s)
94
99
  end
100
+
95
101
  it 'reports the source when no match was expected' do
96
102
  source = 'the_path/to_a/source_file.rb'
97
103
  expect(@examiner).to receive(:description).and_return(source)
@@ -1,7 +1,7 @@
1
1
  require 'reek/spec'
2
2
  require 'reek/source/ast_node_class_map'
3
+ require 'reek/configuration/app_configuration'
3
4
 
4
- require 'matchers/smell_of_matcher'
5
5
  require 'factory_girl'
6
6
 
7
7
  begin
@@ -13,22 +13,30 @@ FactoryGirl.find_definitions
13
13
 
14
14
  SAMPLES_DIR = 'spec/samples'
15
15
 
16
- # :reek:UncommunicativeMethodName
17
- def s(type, *children)
18
- @klass_map ||= Reek::Source::AstNodeClassMap.new
19
- @klass_map.klass_for(type).new(type, children)
20
- end
21
-
22
- def ast(*args)
23
- s(*args)
24
- end
25
-
26
16
  # Simple helpers for our specs.
27
17
  module Helpers
28
- def with_test_config(path)
29
- Configuration::AppConfiguration.load_from_file(path)
18
+ def with_test_config(config)
19
+ if config.is_a? String
20
+ Reek::Configuration::AppConfiguration.load_from_file(config)
21
+ elsif config.is_a? Hash
22
+ Reek::Configuration::AppConfiguration.class_eval do
23
+ @configuration = config
24
+ end
25
+ else
26
+ raise "Unknown config given in `with_test_config`: #{config.inspect}"
27
+ end
30
28
  yield if block_given?
31
- Configuration::AppConfiguration.reset
29
+ Reek::Configuration::AppConfiguration.reset
30
+ end
31
+
32
+ # :reek:UncommunicativeMethodName
33
+ def s(type, *children)
34
+ @klass_map ||= Reek::Source::AstNodeClassMap.new
35
+ @klass_map.klass_for(type).new(type, children)
36
+ end
37
+
38
+ def ast(*args)
39
+ s(*args)
32
40
  end
33
41
  end
34
42
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reek
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.6
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kevin Rutherford
@@ -18,14 +18,14 @@ dependencies:
18
18
  requirements:
19
19
  - - "~>"
20
20
  - !ruby/object:Gem::Version
21
- version: 2.2.0.pre.7
21
+ version: '2.2'
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  requirements:
26
26
  - - "~>"
27
27
  - !ruby/object:Gem::Version
28
- version: 2.2.0.pre.7
28
+ version: '2.2'
29
29
  - !ruby/object:Gem::Dependency
30
30
  name: unparser
31
31
  requirement: !ruby/object:Gem::Requirement
@@ -44,22 +44,16 @@ dependencies:
44
44
  name: rainbow
45
45
  requirement: !ruby/object:Gem::Requirement
46
46
  requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: '1.99'
50
- - - "<"
47
+ - - "~>"
51
48
  - !ruby/object:Gem::Version
52
- version: '3.0'
49
+ version: '2.0'
53
50
  type: :runtime
54
51
  prerelease: false
55
52
  version_requirements: !ruby/object:Gem::Requirement
56
53
  requirements:
57
- - - ">="
58
- - !ruby/object:Gem::Version
59
- version: '1.99'
60
- - - "<"
54
+ - - "~>"
61
55
  - !ruby/object:Gem::Version
62
- version: '3.0'
56
+ version: '2.0'
63
57
  - !ruby/object:Gem::Dependency
64
58
  name: bundler
65
59
  requirement: !ruby/object:Gem::Requirement
@@ -208,14 +202,14 @@ files:
208
202
  - lib/reek.rb
209
203
  - lib/reek/cli/application.rb
210
204
  - lib/reek/cli/command.rb
211
- - lib/reek/cli/help_command.rb
212
205
  - lib/reek/cli/input.rb
206
+ - lib/reek/cli/option_interpreter.rb
213
207
  - lib/reek/cli/options.rb
214
208
  - lib/reek/cli/reek_command.rb
215
209
  - lib/reek/cli/report/formatter.rb
210
+ - lib/reek/cli/report/heading_formatter.rb
211
+ - lib/reek/cli/report/location_formatter.rb
216
212
  - lib/reek/cli/report/report.rb
217
- - lib/reek/cli/report/strategy.rb
218
- - lib/reek/cli/version_command.rb
219
213
  - lib/reek/configuration/app_configuration.rb
220
214
  - lib/reek/configuration/configuration_file_finder.rb
221
215
  - lib/reek/core/code_context.rb
@@ -281,11 +275,11 @@ files:
281
275
  - spec/factories/factories.rb
282
276
  - spec/gem/updates_spec.rb
283
277
  - spec/gem/yard_spec.rb
284
- - spec/matchers/smell_of_matcher.rb
285
278
  - spec/quality/reek_source_spec.rb
286
- - spec/reek/cli/help_command_spec.rb
287
- - spec/reek/cli/report_spec.rb
288
- - spec/reek/cli/version_command_spec.rb
279
+ - spec/reek/cli/html_report_spec.rb
280
+ - spec/reek/cli/option_interperter_spec.rb
281
+ - spec/reek/cli/text_report_spec.rb
282
+ - spec/reek/cli/yaml_report_spec.rb
289
283
  - spec/reek/configuration/app_configuration_spec.rb
290
284
  - spec/reek/configuration/configuration_file_finder_spec.rb
291
285
  - spec/reek/core/code_context_spec.rb
@@ -295,6 +289,7 @@ files:
295
289
  - spec/reek/core/object_refs_spec.rb
296
290
  - spec/reek/core/singleton_method_context_spec.rb
297
291
  - spec/reek/core/smell_configuration_spec.rb
292
+ - spec/reek/core/smell_repository_spec.rb
298
293
  - spec/reek/core/stop_context_spec.rb
299
294
  - spec/reek/core/warning_collector_spec.rb
300
295
  - spec/reek/examiner_spec.rb
@@ -1,15 +0,0 @@
1
- require 'reek/cli/command'
2
-
3
- module Reek
4
- module Cli
5
- #
6
- # A command to display usage information for this application.
7
- #
8
- class HelpCommand < Command
9
- def execute(view)
10
- view.output(@options.help_text)
11
- view.report_success
12
- end
13
- end
14
- end
15
- end
@@ -1,64 +0,0 @@
1
- module Reek
2
- module Cli
3
- module Report
4
- module Strategy
5
- #
6
- # Base class for report startegies.
7
- # Each gathers results according to strategy chosen
8
- #
9
- class Base
10
- attr_reader :report_formatter, :warning_formatter, :examiners
11
-
12
- def initialize(report_formatter, warning_formatter, examiners)
13
- @report_formatter = report_formatter
14
- @warning_formatter = warning_formatter
15
- @examiners = examiners
16
- end
17
-
18
- def summarize_single_examiner(examiner)
19
- result = report_formatter.header examiner
20
- if examiner.smelly?
21
- formatted_list = report_formatter.format_list(examiner.smells,
22
- warning_formatter)
23
- result += ":\n#{formatted_list}"
24
- end
25
- result
26
- end
27
- end
28
-
29
- #
30
- # Lists out each examiner, even if it has no smell
31
- #
32
- class Verbose < Base
33
- def gather_results
34
- examiners.each_with_object([]) do |examiner, result|
35
- result << summarize_single_examiner(examiner)
36
- end
37
- end
38
- end
39
-
40
- #
41
- # Lists only smelly examiners
42
- #
43
- class Quiet < Base
44
- def gather_results
45
- examiners.each_with_object([]) do |examiner, result|
46
- result << summarize_single_examiner(examiner) if examiner.smelly?
47
- end
48
- end
49
- end
50
-
51
- #
52
- # Lists smells without summarization
53
- # Used for yaml and html reports
54
- #
55
- class Normal < Base
56
- def gather_results
57
- examiners.each_with_object([]) { |examiner, smells| smells << examiner.smells }.
58
- flatten
59
- end
60
- end
61
- end
62
- end
63
- end
64
- end
@@ -1,16 +0,0 @@
1
- require 'reek'
2
- require 'reek/cli/command'
3
-
4
- module Reek
5
- module Cli
6
- #
7
- # A command to report the application's current version number.
8
- #
9
- class VersionCommand < Command
10
- def execute(view)
11
- view.output("#{@options.program_name} #{Reek::VERSION}\n")
12
- view.report_success
13
- end
14
- end
15
- end
16
- end
@@ -1,95 +0,0 @@
1
- module SmellOfMatcher
2
- class SmellOf
3
- def initialize(klass, *expected_smells)
4
- @klass = klass
5
- @expected_smells = expected_smells
6
- @config = {}
7
- end
8
-
9
- def failure_message
10
- "Expected #{@source.desc} to smell of #{@klass}, but it didn't: #{@reason}"
11
- end
12
-
13
- def failure_message_when_negated
14
- "Expected #{@source.desc} not to smell of #{@klass}, but it did"
15
- end
16
-
17
- def matches?(src)
18
- @source = src.to_reek_source
19
-
20
- detect_smells
21
-
22
- return false if no_smells_found?
23
- return false if wrong_number_of_smells_found?
24
- return false if wrong_smell_details_found?
25
-
26
- true
27
- end
28
-
29
- def with_config(options)
30
- @config = options
31
- self
32
- end
33
-
34
- private
35
-
36
- def detect_smells
37
- tree = @source.syntax_tree
38
- ctx = case tree.type
39
- when :def, :defs
40
- MethodContext.new(nil, tree)
41
- when :module, :class
42
- ModuleContext.new(nil, tree)
43
- else
44
- CodeContext.new(nil, tree)
45
- end
46
- detector = @klass.new(@source.desc, @klass.default_config.merge(@config))
47
- detector.examine(ctx)
48
- @actual_smells = detector.smells_found.to_a
49
- end
50
-
51
- def no_smells_found?
52
- return false if @actual_smells.any?
53
- @reason = 'no smells found by detector'
54
- true
55
- end
56
-
57
- def wrong_number_of_smells_found?
58
- return false if @expected_smells.empty?
59
- return false if expected_number_of_smells == actual_number_of_smells
60
-
61
- @reason = "expected #{expected_number_of_smells} smell(s), " \
62
- "found #{actual_number_of_smells}"
63
- true
64
- end
65
-
66
- def expected_number_of_smells
67
- @expected_number_of_smells ||= @expected_smells.length
68
- end
69
-
70
- def actual_number_of_smells
71
- @actual_number_of_smells ||= @actual_smells.length
72
- end
73
-
74
- def wrong_smell_details_found?
75
- @expected_smells.zip(@actual_smells).each do |expected_smell, actual_smell|
76
- expected_smell.each do |key, value|
77
- actual_value = actual_smell.parameters[key]
78
- next if actual_value == value
79
-
80
- @reason = "expected #{key} to be #{value}, was #{actual_value}"
81
- return true
82
- end
83
- end
84
- false
85
- end
86
- end
87
-
88
- def smell_of(klass, *smells)
89
- SmellOf.new(klass, *smells)
90
- end
91
- end
92
-
93
- RSpec.configure do |config|
94
- config.include(SmellOfMatcher)
95
- end
@@ -1,25 +0,0 @@
1
- require 'spec_helper'
2
- require 'reek/cli/help_command'
3
-
4
- include Reek::Cli
5
-
6
- describe HelpCommand do
7
- before :each do
8
- @help_text = 'Piece of interesting text'
9
- @parser = double('parser')
10
- allow(@parser).to receive(:help_text).and_return @help_text
11
- @cmd = HelpCommand.new(@parser)
12
- @view = double('view').as_null_object
13
- end
14
-
15
- it 'displays the correct text on the view' do
16
- expect(@view).to receive(:output).with(@help_text)
17
- @cmd.execute(@view)
18
- end
19
-
20
- it 'tells the view it succeeded' do
21
- expect(@view).not_to receive(:report_smells)
22
- expect(@view).to receive(:report_success)
23
- @cmd.execute(@view)
24
- end
25
- end
@@ -1,132 +0,0 @@
1
- require 'spec_helper'
2
- require 'reek/examiner'
3
- require 'reek/cli/report/report'
4
- require 'reek/cli/report/formatter'
5
- require 'reek/cli/report/strategy'
6
- require 'rainbow'
7
- require 'stringio'
8
-
9
- include Reek
10
- include Reek::Cli
11
-
12
- def capture_output_stream
13
- $stdout = StringIO.new
14
- yield
15
- $stdout.string
16
- ensure
17
- $stdout = STDOUT
18
- end
19
-
20
- def report_options
21
- {
22
- warning_formatter: Report::SimpleWarningFormatter,
23
- report_formatter: Report::Formatter,
24
- strategy: Report::Strategy::Quiet
25
- }
26
- end
27
-
28
- describe Report::TextReport, ' when empty' do
29
- context 'empty source' do
30
- let(:examiner) { Examiner.new('') }
31
-
32
- def report(obj)
33
- obj.add_examiner examiner
34
- end
35
-
36
- it 'has an empty quiet_report' do
37
- tr = Report::TextReport.new
38
- tr.add_examiner(examiner)
39
- expect { tr.show }.to_not output.to_stdout
40
- end
41
-
42
- context 'when output format is html' do
43
- it 'has the text 0 total warnings' do
44
- html_report = report(Report::HtmlReport.new(report_options))
45
- html_report.show
46
-
47
- file = File.expand_path('../../../../reek.html', __FILE__)
48
- text = File.read(file)
49
- File.delete(file)
50
-
51
- expect(text).to include('0 total warnings')
52
- end
53
- end
54
-
55
- context 'when output format is yaml' do
56
- it 'prints empty yaml' do
57
- yaml_report = report(Report::YamlReport.new(report_options))
58
- result = capture_output_stream { yaml_report.show }
59
- expect(result).to match(/^--- \[\]\n.*$/)
60
- end
61
- end
62
-
63
- context 'when output format is text' do
64
- it 'prints nothing' do
65
- text_report = report(Report::TextReport.new)
66
- expect { text_report.show }.to_not output.to_stdout
67
- end
68
- end
69
- end
70
-
71
- context 'with a couple of smells' do
72
- before :each do
73
- @examiner = Examiner.new('def simple(a) a[3] end')
74
- @rpt = Report::TextReport.new report_options
75
- end
76
-
77
- context 'with colors disabled' do
78
- before :each do
79
- Rainbow.enabled = false
80
- @result = @rpt.add_examiner(@examiner).smells.first
81
- end
82
-
83
- it 'has a header' do
84
- expect(@result).to match('string -- 2 warnings')
85
- end
86
-
87
- it 'should mention every smell name' do
88
- expect(@result).to include('UncommunicativeParameterName')
89
- expect(@result).to include('FeatureEnvy')
90
- end
91
- end
92
-
93
- context 'with colors enabled' do
94
- before :each do
95
- Rainbow.enabled = true
96
- end
97
-
98
- context 'with non smelly files' do
99
- before :each do
100
- Rainbow.enabled = true
101
- @rpt.add_examiner(Examiner.new('def simple() puts "a" end'))
102
- @rpt.add_examiner(Examiner.new('def simple() puts "a" end'))
103
- @result = @rpt.smells
104
- end
105
-
106
- it 'has a footer in color' do
107
- result = capture_output_stream { @rpt.show }
108
- expect(result).to end_with "\e[32m0 total warnings\n\e[0m"
109
- end
110
- end
111
-
112
- context 'with smelly files' do
113
- before :each do
114
- Rainbow.enabled = true
115
- @rpt.add_examiner(Examiner.new('def simple(a) a[3] end'))
116
- @rpt.add_examiner(Examiner.new('def simple(a) a[3] end'))
117
- @result = @rpt.smells
118
- end
119
-
120
- it 'has a header in color' do
121
- expect(@result.first).
122
- to start_with "\e[36mstring -- \e[0m\e[33m2 warning\e[0m\e[33ms\e[0m"
123
- end
124
-
125
- it 'has a footer in color' do
126
- result = capture_output_stream { @rpt.show }
127
- expect(result).to end_with "\e[31m4 total warnings\n\e[0m"
128
- end
129
- end
130
- end
131
- end
132
- end