reek 4.7.2 → 4.7.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +18 -4
  3. data/.travis.yml +0 -5
  4. data/CHANGELOG.md +8 -0
  5. data/CONTRIBUTING.md +1 -1
  6. data/Gemfile +4 -4
  7. data/docs/How-To-Write-New-Detectors.md +6 -5
  8. data/docs/Unused-Private-Method.md +1 -1
  9. data/features/configuration_via_source_comments/erroneous_source_comments.feature +1 -1
  10. data/features/locales.feature +32 -0
  11. data/features/rake_task/rake_task.feature +46 -6
  12. data/features/rspec_matcher.feature +32 -0
  13. data/features/step_definitions/reek_steps.rb +0 -4
  14. data/features/support/env.rb +0 -9
  15. data/lib/reek/ast/builder.rb +1 -1
  16. data/lib/reek/ast/sexp_extensions/send.rb +0 -4
  17. data/lib/reek/cli/options.rb +2 -2
  18. data/lib/reek/configuration/app_configuration.rb +3 -2
  19. data/lib/reek/configuration/configuration_file_finder.rb +3 -3
  20. data/lib/reek/context/ghost_context.rb +0 -2
  21. data/lib/reek/context/module_context.rb +0 -3
  22. data/lib/reek/context_builder.rb +2 -4
  23. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +2 -2
  24. data/lib/reek/errors/bad_detector_in_comment_error.rb +2 -2
  25. data/lib/reek/errors/encoding_error.rb +38 -0
  26. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +3 -3
  27. data/lib/reek/errors/incomprehensible_source_error.rb +4 -4
  28. data/lib/reek/examiner.rb +15 -11
  29. data/lib/reek/rake/task.rb +5 -1
  30. data/lib/reek/smell_detectors/attribute.rb +6 -11
  31. data/lib/reek/smell_detectors/base_detector.rb +9 -1
  32. data/lib/reek/smell_detectors/boolean_parameter.rb +4 -5
  33. data/lib/reek/smell_detectors/class_variable.rb +5 -6
  34. data/lib/reek/smell_detectors/control_parameter.rb +3 -3
  35. data/lib/reek/smell_detectors/data_clump.rb +13 -6
  36. data/lib/reek/smell_detectors/duplicate_method_call.rb +18 -11
  37. data/lib/reek/smell_detectors/feature_envy.rb +9 -7
  38. data/lib/reek/smell_detectors/instance_variable_assumption.rb +14 -14
  39. data/lib/reek/smell_detectors/irresponsible_module.rb +6 -12
  40. data/lib/reek/smell_detectors/long_parameter_list.rb +10 -6
  41. data/lib/reek/smell_detectors/long_yield_list.rb +9 -5
  42. data/lib/reek/smell_detectors/manual_dispatch.rb +3 -4
  43. data/lib/reek/smell_detectors/module_initialize.rb +4 -5
  44. data/lib/reek/smell_detectors/nested_iterators.rb +11 -19
  45. data/lib/reek/smell_detectors/nil_check.rb +9 -15
  46. data/lib/reek/smell_detectors/prima_donna_method.rb +17 -16
  47. data/lib/reek/smell_detectors/repeated_conditional.rb +11 -8
  48. data/lib/reek/smell_detectors/subclassed_from_core_class.rb +8 -8
  49. data/lib/reek/smell_detectors/too_many_constants.rb +10 -8
  50. data/lib/reek/smell_detectors/too_many_instance_variables.rb +10 -5
  51. data/lib/reek/smell_detectors/too_many_methods.rb +11 -6
  52. data/lib/reek/smell_detectors/too_many_statements.rb +10 -5
  53. data/lib/reek/smell_detectors/uncommunicative_method_name.rb +8 -8
  54. data/lib/reek/smell_detectors/uncommunicative_module_name.rb +12 -15
  55. data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +10 -13
  56. data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +23 -23
  57. data/lib/reek/smell_detectors/unused_parameters.rb +5 -6
  58. data/lib/reek/smell_detectors/unused_private_method.rb +11 -18
  59. data/lib/reek/smell_detectors/utility_function.rb +12 -15
  60. data/lib/reek/source/source_code.rb +27 -6
  61. data/lib/reek/source/source_locator.rb +1 -1
  62. data/lib/reek/spec.rb +1 -1
  63. data/lib/reek/version.rb +1 -1
  64. data/reek.gemspec +0 -2
  65. data/spec/reek/ast/sexp_extensions_spec.rb +12 -32
  66. data/spec/reek/cli/application_spec.rb +4 -6
  67. data/spec/reek/configuration/configuration_file_finder_spec.rb +0 -2
  68. data/spec/reek/examiner_spec.rb +38 -1
  69. data/spec/reek/rake/task_spec.rb +25 -2
  70. data/spec/reek/smell_detectors/base_detector_spec.rb +4 -5
  71. data/spec/reek/smell_detectors/prima_donna_method_spec.rb +3 -3
  72. data/spec/reek/source/source_code_spec.rb +28 -1
  73. data/spec/reek/spec/should_reek_of_spec.rb +18 -18
  74. data/spec/reek/spec/should_reek_spec.rb +5 -5
  75. data/spec/reek/spec/smell_matcher_spec.rb +20 -20
  76. data/spec/spec_helper.rb +1 -1
  77. metadata +6 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a57753b0b855d7182054e7551940eac44cf57f60
4
- data.tar.gz: 245074bd6e150589a1bc7a69830a34e3db600a83
3
+ metadata.gz: a71c30d4b1f39eee7c330e391cb1e80afa0a2d3b
4
+ data.tar.gz: fad4cfa8b8d369ff2e5c6ac5a22f3be8abc03891
5
5
  SHA512:
6
- metadata.gz: 4c422c0a25421d8d0abc337766f7b2defae5f7044137c3e5fb7c34fffea7ee409d165f56922f433565fa8643d716cdbb3e9a3c7cec568bfa50bf15b2eed8b254
7
- data.tar.gz: d4b77922d2745ab3d7f6f053931193b543f646e605a0b3a7f7a444ddf24d3462df4bf7732a248f14fd49f9253925afbf441d3fda578df736b130bfbf80db5096
6
+ metadata.gz: 15725dcd429906aba55b5dd379f01b1bf5e6eb08dd8df814a8403752c1356481137e0804618a449010c1b6dbb90da5543f21cf9401d2faaacbb6254734b01f68
7
+ data.tar.gz: 4a7a38b3b04059de3f93bb90ee14354fc0052f6c8a23ff3f96b8f456643087aa9f51aca3ff22758ef118f4c3fc05c741892a9658c512c0f0f171ee7cbbbfbd9a
@@ -36,6 +36,15 @@ Layout/MultilineOperationIndentation:
36
36
  Lint/AmbiguousBlockAssociation:
37
37
  Enabled: false
38
38
 
39
+ # Some of our source examples include interpolation explicitely.
40
+ Lint/InterpolationCheck:
41
+ Exclude:
42
+ - 'spec/**/*'
43
+
44
+ # We use :true and :false as AST node types.
45
+ Lint/BooleanSymbol:
46
+ Enabled: false
47
+
39
48
  Lint/HandleExceptions:
40
49
  Exclude:
41
50
  - 'spec/reek/configuration/configuration_file_finder_spec.rb'
@@ -63,6 +72,15 @@ Metrics/LineLength:
63
72
  Metrics/ParameterLists:
64
73
  CountKeywordArgs: false
65
74
 
75
+ Naming/AccessorMethodName:
76
+ Exclude:
77
+ - 'lib/reek/context/visibility_tracker.rb'
78
+
79
+ # EOS is a fine name to use in our specs
80
+ Naming/HeredocDelimiterNaming:
81
+ Exclude:
82
+ - 'spec/**/*'
83
+
66
84
  # FIXME: Update specs to avoid offenses
67
85
  RSpec/AnyInstance:
68
86
  Exclude:
@@ -109,10 +127,6 @@ RSpec/FilePath:
109
127
  - 'spec/reek/report/code_climate/code_climate_formatter_spec.rb'
110
128
  - 'spec/reek/report/code_climate/code_climate_report_spec.rb'
111
129
 
112
- Style/AccessorMethodName:
113
- Exclude:
114
- - 'lib/reek/context/visibility_tracker.rb'
115
-
116
130
  # Allow and/or for control flow only
117
131
  Style/AndOr:
118
132
  EnforcedStyle: conditionals
@@ -20,11 +20,6 @@ matrix:
20
20
  - rvm: ruby-head
21
21
  - rvm: rubinius-3
22
22
  fast_finish: true
23
- before_install:
24
- - rvm use @global
25
- - gem uninstall bundler -x
26
- - gem install bundler --version=1.13.7
27
- - bundler --version
28
23
  notifications:
29
24
  email:
30
25
  - timo.roessner@googlemail.com
@@ -1,5 +1,13 @@
1
1
  # Change log
2
2
 
3
+ ## 4.7.3 (2017-11-05)
4
+
5
+ * (mvz) Handle UTF-8 files in all locales
6
+ * (troessner) Handle encoding and other errors when parsing the source
7
+ * (mvz) Report method source line in PrimaDonnaMethod
8
+ * (mvz) Pick up config file in reek matcher
9
+ * (mvz) Let REEK_SRC override set values in rake task
10
+
3
11
  ## 4.7.2 (2017-07-24)
4
12
 
5
13
  * (mvz) Also report unused uncommunicative parameter names
@@ -111,7 +111,7 @@ regard than if it were run in a terminal.
111
111
 
112
112
  #### Failing Cucumber Scenarios
113
113
 
114
- If there is a failing scenario and you can not figure out why it is failing,
114
+ If there is a failing scenario and you cannot figure out why it is failing,
115
115
  just run the failing scenario: `bundle exec cucumber
116
116
  features/failing_scenario.feature:line`. By doing so Aruba will leave its set
117
117
  up in the `tmp/aruba` directory. You can then `cd` into this directory and run
data/Gemfile CHANGED
@@ -8,16 +8,16 @@ group :development do
8
8
  gem 'activesupport', '>= 4.2'
9
9
  gem 'aruba', '~> 0.14.0'
10
10
  gem 'ataru', '~> 0.2.0'
11
- gem 'cucumber', '~> 2.0'
11
+ gem 'cucumber', '~> 3.0'
12
12
  gem 'factory_girl', '~> 4.0'
13
13
  gem 'rake', '~> 12.0'
14
14
  gem 'rspec', '~> 3.0'
15
- gem 'simplecov', '~> 0.14.0'
15
+ gem 'simplecov', '~> 0.15.0'
16
16
  gem 'yard', '~> 0.9.5'
17
17
 
18
18
  if RUBY_VERSION >= '2.3'
19
- gem 'rubocop', '~> 0.49.1'
20
- gem 'rubocop-rspec', '~> 1.15.0'
19
+ gem 'rubocop', '~> 0.51.0'
20
+ gem 'rubocop-rspec', '~> 1.19.0'
21
21
  end
22
22
 
23
23
  platforms :mri do
@@ -27,20 +27,21 @@ module Reek
27
27
  end
28
28
 
29
29
  #
30
- # Here you should document what you expect "ctx" to look like.
30
+ # Here you should document what you expect the detector's context to look
31
+ # like.
31
32
  #
32
33
  # @return [Array<SmellWarning>]
33
34
  #
34
- def sniff(ctx)
35
+ def sniff
35
36
  # "found_smells" below is just an abstraction for
36
- # "find the smells in question" and iteratore over them.
37
+ # "find the smells in question" and iterate over them.
37
38
  # This can just be a method but it can also be a more sophisticated set up.
38
39
  # Check out other smell detectors to get a feeling for what to do here.
39
- found_smells(ctx).map do |smell|
40
+ found_smells.map do |smell|
40
41
  # "smell_warning" is defined in BaseDetector and should be used by you
41
42
  # to construct smell warnings
42
43
  smell_warning(
43
- context: ctx,
44
+ context: context,
44
45
  lines: [], # lines on which the smell was detected
45
46
  message: "...", # the message that is printed on STDOUT
46
47
  # whatever you interpolate into the "message" should go into
@@ -78,7 +78,7 @@ end
78
78
  ## Known limitations
79
79
 
80
80
  * Method calls via dynamic dispatch (e.g. via `send`) is something Reek (or any other
81
- static tool for that matter) can not detect.
81
+ static tool for that matter) cannot detect.
82
82
  * Method calls via callback like [Rails filters](http://guides.rubyonrails.org/action_controller_overview.html#filters)
83
83
  will trigger this as well, e.g.:
84
84
 
@@ -48,7 +48,7 @@ Feature: Erroneous source comments are handled properly
48
48
  """
49
49
  When I run reek bad_comment.rb
50
50
  Then it reports the error "Error: You are trying to configure the smell detector 'UncommunicativeMethodName'"
51
- And it reports the error "Unfortunately we can not parse the configuration you have given."
51
+ And it reports the error "Unfortunately we cannot parse the configuration you have given."
52
52
  And it reports the error "The source is 'bad_comment.rb'"
53
53
  And it reports the error "the comment belongs to the expression starting in line 3"
54
54
 
@@ -0,0 +1,32 @@
1
+ Feature: Handling different locales
2
+ In order to work in a variety of environments
3
+ As a developer
4
+ I want Reek to work properly in any locale
5
+
6
+ Scenario: Running Reek in an UTF-8 locale
7
+ Given I set the environment variable "LANG" to "en_US.utf8"
8
+ And a file "konnichiwa.rb" with:
9
+ """
10
+ puts 'こんにちは世界'
11
+ """
12
+ When I run `reek -V konnichiwa.rb`
13
+ Then it succeeds
14
+ And it reports no errors
15
+ And it reports:
16
+ """
17
+ konnichiwa.rb -- 0 warnings
18
+ """
19
+
20
+ Scenario: Running Reek in the POSIX locale
21
+ Given I set the environment variable "LANG" to "POSIX"
22
+ And a file "konnichiwa.rb" with:
23
+ """
24
+ puts 'こんにちは世界'
25
+ """
26
+ When I run `reek -V konnichiwa.rb`
27
+ Then it succeeds
28
+ And it reports no errors
29
+ And it reports:
30
+ """
31
+ konnichiwa.rb -- 0 warnings
32
+ """
@@ -4,13 +4,16 @@ Feature: Reek can be driven through its Task
4
4
 
5
5
  Scenario: source_files points at the desired files
6
6
  Given the smelly file 'smelly.rb'
7
- When I run rake reek with:
7
+ And a file "Rakefile" with:
8
8
  """
9
+ require 'reek/rake/task'
10
+
9
11
  Reek::Rake::Task.new do |t|
10
12
  t.source_files = 'smelly.rb'
11
13
  t.reek_opts = '--no-color'
12
14
  end
13
15
  """
16
+ When I run `rake reek`
14
17
  Then the exit status indicates an error
15
18
  And it reports:
16
19
  """
@@ -21,13 +24,16 @@ Feature: Reek can be driven through its Task
21
24
 
22
25
  Scenario: source_files using a FileList instead of a String
23
26
  Given the smelly file 'smelly.rb'
24
- When I run rake reek with:
27
+ And a file "Rakefile" with:
25
28
  """
29
+ require 'reek/rake/task'
30
+
26
31
  Reek::Rake::Task.new do |t|
27
32
  t.source_files = FileList['smelly.*']
28
33
  t.reek_opts = '--no-color'
29
34
  end
30
35
  """
36
+ When I run `rake reek`
31
37
  Then the exit status indicates an error
32
38
  And it reports:
33
39
  """
@@ -38,13 +44,16 @@ Feature: Reek can be driven through its Task
38
44
 
39
45
  Scenario: name changes the task name
40
46
  Given the smelly file 'smelly.rb'
41
- When I run rake silky with:
47
+ And a file "Rakefile" with:
42
48
  """
49
+ require 'reek/rake/task'
50
+
43
51
  Reek::Rake::Task.new('silky') do |t|
44
52
  t.source_files = 'smelly.rb'
45
53
  t.reek_opts = '--no-color'
46
54
  end
47
55
  """
56
+ When I run `rake silky`
48
57
  Then the exit status indicates an error
49
58
  And it reports:
50
59
  """
@@ -55,26 +64,32 @@ Feature: Reek can be driven through its Task
55
64
 
56
65
  Scenario: verbose prints the reek command
57
66
  Given the smelly file 'smelly.rb'
58
- When I run rake reek with:
67
+ And a file "Rakefile" with:
59
68
  """
69
+ require 'reek/rake/task'
70
+
60
71
  Reek::Rake::Task.new do |t|
61
72
  t.source_files = 'smelly.rb'
62
73
  t.verbose = true
63
74
  end
64
75
  """
76
+ When I run `rake reek`
65
77
  Then the exit status indicates an error
66
78
  And stdout includes "Running 'reek' rake command"
67
79
 
68
80
  Scenario: fail_on_error can hide the error status
69
81
  Given the smelly file 'smelly.rb'
70
- When I run rake reek with:
82
+ And a file "Rakefile" with:
71
83
  """
84
+ require 'reek/rake/task'
85
+
72
86
  Reek::Rake::Task.new do |t|
73
87
  t.fail_on_error = false
74
88
  t.source_files = 'smelly.rb'
75
89
  t.reek_opts = '--no-color'
76
90
  end
77
91
  """
92
+ When I run `rake reek`
78
93
  Then it reports no errors
79
94
  And it succeeds
80
95
  And it reports:
@@ -87,12 +102,37 @@ Feature: Reek can be driven through its Task
87
102
  Scenario: can be configured with config_file
88
103
  Given the smelly file 'smelly.rb'
89
104
  And a configuration file 'full_mask.reek'
90
- When I run rake reek with:
105
+ And a file "Rakefile" with:
91
106
  """
107
+ require 'reek/rake/task'
108
+
92
109
  Reek::Rake::Task.new do |t|
93
110
  t.config_file = 'full_mask.reek'
94
111
  t.source_files = 'smelly.rb'
95
112
  end
96
113
  """
114
+ When I run `rake reek`
97
115
  Then it succeeds
98
116
  And it reports nothing
117
+
118
+ Scenario: REEK_SRC overrides the files to check
119
+ Given the smelly file 'smelly.rb'
120
+ And the clean file 'clean.rb'
121
+ And a file "Rakefile" with:
122
+ """
123
+ require 'reek/rake/task'
124
+
125
+ Reek::Rake::Task.new do |t|
126
+ t.source_files = 'clean.rb'
127
+ t.reek_opts = '--no-color'
128
+ end
129
+ """
130
+ When I set the environment variable "REEK_SRC" to "smelly.rb"
131
+ And I run `rake reek`
132
+ Then the exit status indicates an error
133
+ And it reports:
134
+ """
135
+ smelly.rb -- 2 warnings:
136
+ [4]:UncommunicativeMethodName: Smelly#x has the name 'x' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Method-Name.md]
137
+ [5]:UncommunicativeVariableName: Smelly#x has the variable name 'y' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Variable-Name.md]
138
+ """
@@ -0,0 +1,32 @@
1
+ Feature: Use reek_of matcher
2
+ As a developer
3
+ In order to check code quality as part of my spec suite
4
+ I want to assert that my code doesn't smell
5
+
6
+ Background:
7
+ Given the smelly file 'smelly.rb'
8
+ And a file "reek_spec.rb" with:
9
+ """
10
+ require 'reek/spec'
11
+
12
+ describe 'smelly.rb' do
13
+ it 'is clean' do
14
+ expect(Pathname.new('smelly.rb')).not_to reek
15
+ end
16
+ end
17
+ """
18
+
19
+ Scenario: Failing on a smelly file
20
+ When I run `rspec reek_spec.rb`
21
+ Then stdout should contain:
22
+ """
23
+ Failure/Error: expect(Pathname.new('smelly.rb')).not_to reek
24
+ """
25
+
26
+ Scenario: Masking smells with a configuration file
27
+ Given a configuration file 'full_mask.reek'
28
+ When I run `rspec reek_spec.rb`
29
+ Then stdout should contain:
30
+ """
31
+ 1 example, 0 failures
32
+ """
@@ -6,10 +6,6 @@ When /^I pass "([^\"]*)" to reek *(.*)$/ do |stdin, args|
6
6
  reek_with_pipe(stdin, args)
7
7
  end
8
8
 
9
- When /^I run rake (\w*) with:$/ do |name, task_def|
10
- rake(name, task_def)
11
- end
12
-
13
9
  Then /^it reports nothing$/ do
14
10
  expect(last_command_started).to have_output_on_stdout('')
15
11
  end
@@ -21,15 +21,6 @@ class ReekWorld
21
21
  type(stdin)
22
22
  close_input
23
23
  end
24
-
25
- def rake(name, task_def)
26
- header = <<-EOS.strip_heredoc
27
- require 'reek/rake/task'
28
-
29
- EOS
30
- write_file 'Rakefile', header + task_def
31
- run_simple("rake #{name}", false)
32
- end
33
24
  end
34
25
 
35
26
  World do
@@ -6,7 +6,7 @@ module Reek
6
6
  # An AST Builder for ruby parser.
7
7
  #
8
8
  class Builder < ::Parser::Builders::Default
9
- # This is a work around for parsing ruby code that has a string with invliad sequence as UTF-8.
9
+ # This is a work around for parsing ruby code that has a string with invalid sequence as UTF-8.
10
10
  # See. https://github.com/whitequark/parser/issues/283
11
11
  def string_value(token)
12
12
  value(token)
@@ -23,10 +23,6 @@ module Reek
23
23
  ([receiver] + args).compact
24
24
  end
25
25
 
26
- def arg_names
27
- args.map { |arg| arg.children.first }
28
- end
29
-
30
26
  def module_creation_call?
31
27
  object_creation_call? && module_creation_receiver?
32
28
  end
@@ -82,7 +82,7 @@ module Reek
82
82
 
83
83
  def set_banner
84
84
  program_name = parser.program_name
85
- parser.banner = <<-EOB.gsub(/^[ ]+/, '')
85
+ parser.banner = <<-BANNER.gsub(/^[ ]+/, '')
86
86
  Usage: #{program_name} [options] [files]
87
87
 
88
88
  Examples:
@@ -93,7 +93,7 @@ module Reek
93
93
 
94
94
  See https://wiki.github.com/troessner/reek for detailed help.
95
95
 
96
- EOB
96
+ BANNER
97
97
  end
98
98
 
99
99
  # :reek:TooManyStatements: { max_statements: 6 }
@@ -17,9 +17,10 @@ module Reek
17
17
  include ConfigurationValidator
18
18
  EXCLUDE_PATHS_KEY = 'exclude_paths'.freeze
19
19
 
20
- # Instantiate a configuration via given path.
20
+ # Instantiate a configuration via given path, or the default path.
21
21
  #
22
- # @param path [Pathname] the path to the config file
22
+ # @param path [Pathname] the path to the config file, or nil to use the
23
+ # default path.
23
24
  #
24
25
  # @return [AppConfiguration]
25
26
  #
@@ -18,7 +18,7 @@ module Reek
18
18
  # The order in which ConfigurationFileFinder tries to find such a
19
19
  # configuration file is exactly like above.
20
20
  module ConfigurationFileFinder
21
- TOO_MANY_CONFIGURATION_FILES_MESSAGE = <<-EOS.freeze
21
+ TOO_MANY_CONFIGURATION_FILES_MESSAGE = <<-MESSAGE.freeze
22
22
 
23
23
  Error: Found multiple configuration files %s
24
24
  while scanning directory %s.
@@ -27,7 +27,7 @@ module Reek
27
27
  1) Remove all offending files.
28
28
  2) Be specific about which one you want to load via the -c switch.
29
29
 
30
- EOS
30
+ MESSAGE
31
31
 
32
32
  class << self
33
33
  #
@@ -64,7 +64,7 @@ module Reek
64
64
  return {} unless path
65
65
  begin
66
66
  configuration = YAML.load_file(path) || {}
67
- rescue => error
67
+ rescue StandardError => error
68
68
  raise ConfigFileException, "Invalid configuration file #{path}, error is #{error}"
69
69
  end
70
70