reek 1.6.6 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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