reek 4.8.2 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (213) hide show
  1. checksums.yaml +5 -5
  2. data/{samples/configuration/more_than_one_configuration_file/regular.reek → .reek.yml} +0 -0
  3. data/.rubocop.yml +17 -3
  4. data/.simplecov +1 -0
  5. data/.travis.yml +0 -5
  6. data/.yardopts +1 -1
  7. data/CHANGELOG.md +28 -0
  8. data/Gemfile +1 -1
  9. data/README.md +113 -98
  10. data/Rakefile +16 -3
  11. data/bin/reek +1 -3
  12. data/docs/API.md +2 -9
  13. data/docs/Basic-Smell-Options.md +51 -11
  14. data/docs/Code-Smells.md +1 -1
  15. data/docs/Command-Line-Options.md +14 -4
  16. data/docs/Duplicate-Method-Call.md +49 -1
  17. data/docs/Feature-Envy.md +44 -0
  18. data/docs/How-To-Write-New-Detectors.md +2 -3
  19. data/docs/{Prima-Donna-Method.md → Missing-Safe-Method.md} +11 -9
  20. data/docs/Rake-Task.md +1 -1
  21. data/docs/Reek-4-to-Reek-5-migration.md +193 -0
  22. data/docs/Reek-Driven-Development.md +1 -1
  23. data/docs/Uncommunicative-Method-Name.md +43 -4
  24. data/docs/Uncommunicative-Module-Name.md +48 -6
  25. data/docs/Uncommunicative-Parameter-Name.md +42 -4
  26. data/docs/Uncommunicative-Variable-Name.md +73 -2
  27. data/docs/Unused-Private-Method.md +1 -1
  28. data/docs/defaults.reek.yml +129 -0
  29. data/docs/yard_plugin.rb +1 -0
  30. data/features/command_line_interface/options.feature +46 -4
  31. data/features/command_line_interface/stdin.feature +27 -5
  32. data/features/configuration_files/accept_setting.feature +39 -22
  33. data/features/configuration_files/directory_specific_directives.feature +58 -53
  34. data/features/configuration_files/exclude_directives.feature +8 -7
  35. data/features/configuration_files/masking_smells.feature +35 -6
  36. data/features/configuration_files/mix_accept_reject_setting.feature +24 -21
  37. data/features/configuration_files/reject_setting.feature +45 -34
  38. data/features/configuration_files/schema_validation.feature +59 -0
  39. data/features/configuration_files/unused_private_method.feature +14 -12
  40. data/features/configuration_loading.feature +50 -7
  41. data/features/rake_task/rake_task.feature +5 -5
  42. data/features/reports/json.feature +4 -1
  43. data/features/reports/reports.feature +12 -12
  44. data/features/reports/yaml.feature +3 -0
  45. data/features/rspec_matcher.feature +9 -1
  46. data/features/step_definitions/reek_steps.rb +4 -0
  47. data/features/step_definitions/sample_file_steps.rb +9 -4
  48. data/features/support/env.rb +2 -2
  49. data/features/todo_list.feature +16 -13
  50. data/lib/reek/ast/node.rb +3 -6
  51. data/lib/reek/ast/object_refs.rb +1 -1
  52. data/lib/reek/ast/sexp_extensions/if.rb +1 -1
  53. data/lib/reek/ast/sexp_extensions/methods.rb +1 -1
  54. data/lib/reek/cli/application.rb +4 -3
  55. data/lib/reek/cli/command/report_command.rb +1 -2
  56. data/lib/reek/cli/command/todo_list_command.rb +4 -2
  57. data/lib/reek/cli/options.rb +27 -13
  58. data/lib/reek/cli/silencer.rb +14 -3
  59. data/lib/reek/code_comment.rb +14 -16
  60. data/lib/reek/configuration/app_configuration.rb +32 -28
  61. data/lib/reek/configuration/configuration_converter.rb +110 -0
  62. data/lib/reek/configuration/configuration_file_finder.rb +15 -40
  63. data/lib/reek/configuration/configuration_validator.rb +12 -23
  64. data/lib/reek/configuration/default_directive.rb +17 -3
  65. data/lib/reek/configuration/directory_directives.rb +17 -11
  66. data/lib/reek/configuration/excluded_paths.rb +1 -1
  67. data/lib/reek/configuration/rake_task_converter.rb +29 -0
  68. data/lib/reek/configuration/schema.yml +210 -0
  69. data/lib/reek/configuration/schema_validator.rb +38 -0
  70. data/lib/reek/context/attribute_context.rb +1 -1
  71. data/lib/reek/context/code_context.rb +4 -4
  72. data/lib/reek/context/method_context.rb +2 -2
  73. data/lib/reek/context/module_context.rb +1 -1
  74. data/lib/reek/context_builder.rb +9 -9
  75. data/lib/reek/detector_repository.rb +6 -0
  76. data/lib/reek/documentation_link.rb +2 -2
  77. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +1 -1
  78. data/lib/reek/errors/bad_detector_in_comment_error.rb +1 -1
  79. data/lib/reek/errors/config_file_error.rb +11 -0
  80. data/lib/reek/errors/encoding_error.rb +2 -2
  81. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +1 -1
  82. data/lib/reek/errors/incomprehensible_source_error.rb +2 -2
  83. data/lib/reek/errors/syntax_error.rb +41 -0
  84. data/lib/reek/examiner.rb +9 -19
  85. data/lib/reek/rake/task.rb +3 -3
  86. data/lib/reek/report.rb +15 -10
  87. data/lib/reek/report/base_report.rb +8 -12
  88. data/lib/reek/report/code_climate/code_climate_configuration.yml +5 -9
  89. data/lib/reek/report/documentation_link_warning_formatter.rb +17 -0
  90. data/lib/reek/report/heading_formatter.rb +54 -0
  91. data/lib/reek/report/json_report.rb +1 -1
  92. data/lib/reek/report/location_formatter.rb +40 -0
  93. data/lib/reek/report/progress_formatter.rb +79 -0
  94. data/lib/reek/report/simple_warning_formatter.rb +34 -0
  95. data/lib/reek/report/text_report.rb +1 -2
  96. data/lib/reek/report/xml_report.rb +3 -3
  97. data/lib/reek/report/yaml_report.rb +1 -1
  98. data/lib/reek/smell_configuration.rb +2 -2
  99. data/lib/reek/smell_detectors.rb +1 -2
  100. data/lib/reek/smell_detectors/attribute.rb +0 -1
  101. data/lib/reek/smell_detectors/base_detector.rb +8 -11
  102. data/lib/reek/smell_detectors/boolean_parameter.rb +0 -1
  103. data/lib/reek/smell_detectors/class_variable.rb +0 -1
  104. data/lib/reek/smell_detectors/control_parameter.rb +17 -32
  105. data/lib/reek/smell_detectors/data_clump.rb +3 -4
  106. data/lib/reek/smell_detectors/duplicate_method_call.rb +5 -6
  107. data/lib/reek/smell_detectors/feature_envy.rb +0 -1
  108. data/lib/reek/smell_detectors/instance_variable_assumption.rb +0 -1
  109. data/lib/reek/smell_detectors/irresponsible_module.rb +0 -1
  110. data/lib/reek/smell_detectors/long_parameter_list.rb +1 -2
  111. data/lib/reek/smell_detectors/long_yield_list.rb +2 -3
  112. data/lib/reek/smell_detectors/manual_dispatch.rb +2 -2
  113. data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +6 -7
  114. data/lib/reek/smell_detectors/module_initialize.rb +0 -1
  115. data/lib/reek/smell_detectors/nested_iterators.rb +4 -5
  116. data/lib/reek/smell_detectors/nil_check.rb +0 -1
  117. data/lib/reek/smell_detectors/repeated_conditional.rb +3 -4
  118. data/lib/reek/smell_detectors/subclassed_from_core_class.rb +0 -1
  119. data/lib/reek/smell_detectors/too_many_constants.rb +1 -2
  120. data/lib/reek/smell_detectors/too_many_instance_variables.rb +1 -2
  121. data/lib/reek/smell_detectors/too_many_methods.rb +1 -2
  122. data/lib/reek/smell_detectors/too_many_statements.rb +1 -2
  123. data/lib/reek/smell_detectors/uncommunicative_method_name.rb +2 -3
  124. data/lib/reek/smell_detectors/uncommunicative_module_name.rb +2 -3
  125. data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +2 -3
  126. data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +4 -5
  127. data/lib/reek/smell_detectors/unused_parameters.rb +0 -1
  128. data/lib/reek/smell_detectors/unused_private_method.rb +0 -1
  129. data/lib/reek/smell_detectors/utility_function.rb +1 -2
  130. data/lib/reek/smell_warning.rb +10 -8
  131. data/lib/reek/source/source_code.rb +40 -55
  132. data/lib/reek/source/source_locator.rb +7 -7
  133. data/lib/reek/spec.rb +6 -6
  134. data/lib/reek/spec/should_reek.rb +2 -2
  135. data/lib/reek/spec/should_reek_of.rb +9 -16
  136. data/lib/reek/spec/should_reek_only_of.rb +4 -4
  137. data/lib/reek/tree_dresser.rb +5 -5
  138. data/lib/reek/version.rb +1 -1
  139. data/reek.gemspec +3 -3
  140. data/samples/checkstyle.xml +1 -1
  141. data/samples/{clean.rb → clean_source/clean.rb} +0 -0
  142. data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +29 -0
  143. data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +30 -0
  144. data/samples/configuration/full_configuration.reek +8 -4
  145. data/samples/configuration/full_mask.reek +5 -4
  146. data/samples/{exceptions.reek → configuration/home/home.reek.yml} +0 -0
  147. data/samples/configuration/partial_mask.reek +3 -2
  148. data/samples/configuration/regular_configuration/.reek.yml +4 -0
  149. data/samples/configuration/{more_than_one_configuration_file/todo.reek → regular_configuration/empty_sub_directory/.gitignore} +0 -0
  150. data/samples/{configuration/single_configuration_file/.reek → no_config_file/.keep} +0 -0
  151. data/samples/paths.rb +5 -4
  152. data/samples/{inline.rb → smelly_source/inline.rb} +0 -0
  153. data/samples/{optparse.rb → smelly_source/optparse.rb} +0 -0
  154. data/samples/{redcloth.rb → smelly_source/redcloth.rb} +0 -0
  155. data/samples/{smelly.rb → smelly_source/smelly.rb} +0 -0
  156. data/samples/source_with_hidden_directories/.hidden/hidden.rb +1 -0
  157. data/samples/source_with_hidden_directories/not_hidden.rb +1 -0
  158. data/samples/{source_with_hidden_directories/uncommunicative_parameter_name.rb → source_with_non_ruby_files/ruby.rb} +0 -0
  159. data/spec/reek/ast/node_spec.rb +5 -5
  160. data/spec/reek/cli/application_spec.rb +18 -4
  161. data/spec/reek/cli/command/todo_list_command_spec.rb +4 -2
  162. data/spec/reek/cli/silencer_spec.rb +28 -0
  163. data/spec/reek/code_comment_spec.rb +0 -7
  164. data/spec/reek/configuration/app_configuration_spec.rb +44 -31
  165. data/spec/reek/configuration/configuration_file_finder_spec.rb +133 -49
  166. data/spec/reek/configuration/default_directive_spec.rb +1 -1
  167. data/spec/reek/configuration/directory_directives_spec.rb +3 -4
  168. data/spec/reek/configuration/excluded_paths_spec.rb +5 -5
  169. data/spec/reek/configuration/rake_task_converter_spec.rb +33 -0
  170. data/spec/reek/configuration/schema_validator_spec.rb +165 -0
  171. data/spec/reek/context/code_context_spec.rb +1 -1
  172. data/spec/reek/examiner_spec.rb +28 -1
  173. data/spec/reek/report/json_report_spec.rb +13 -46
  174. data/spec/reek/report/{formatter/location_formatter_spec.rb → location_formatter_spec.rb} +5 -5
  175. data/spec/reek/report/{formatter/progress_formatter_spec.rb → progress_formatter_spec.rb} +4 -4
  176. data/spec/reek/report/text_report_spec.rb +4 -4
  177. data/spec/reek/report/xml_report_spec.rb +1 -1
  178. data/spec/reek/report/yaml_report_spec.rb +9 -38
  179. data/spec/reek/report_spec.rb +3 -3
  180. data/spec/reek/smell_detectors/feature_envy_spec.rb +2 -2
  181. data/spec/reek/smell_detectors/{prima_donna_method_spec.rb → missing_safe_method_spec.rb} +9 -9
  182. data/spec/reek/smell_detectors/too_many_constants_spec.rb +3 -3
  183. data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +1 -1
  184. data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +6 -6
  185. data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +6 -4
  186. data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +6 -4
  187. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +6 -6
  188. data/spec/reek/smell_detectors/unused_private_method_spec.rb +1 -1
  189. data/spec/reek/smell_warning_spec.rb +4 -0
  190. data/spec/reek/source/source_code_spec.rb +16 -22
  191. data/spec/reek/source/source_locator_spec.rb +11 -11
  192. data/spec/reek/spec/should_reek_of_spec.rb +0 -4
  193. data/spec/reek/spec/should_reek_only_of_spec.rb +2 -2
  194. data/spec/reek/spec/should_reek_spec.rb +1 -1
  195. data/spec/reek/tree_dresser_spec.rb +2 -6
  196. data/spec/spec_helper.rb +3 -5
  197. data/tasks/configuration.rake +8 -5
  198. metadata +56 -35
  199. data/defaults.reek +0 -131
  200. data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
  201. data/lib/reek/report/formatter.rb +0 -33
  202. data/lib/reek/report/formatter/heading_formatter.rb +0 -52
  203. data/lib/reek/report/formatter/location_formatter.rb +0 -42
  204. data/lib/reek/report/formatter/progress_formatter.rb +0 -81
  205. data/lib/reek/report/formatter/simple_warning_formatter.rb +0 -35
  206. data/lib/reek/report/formatter/wiki_link_warning_formatter.rb +0 -23
  207. data/lib/reek/smell_detectors/syntax.rb +0 -37
  208. data/samples/configuration/non_public_modifiers_mask.reek +0 -3
  209. data/samples/smelly_with_inline_mask.rb +0 -8
  210. data/samples/smelly_with_modifiers.rb +0 -12
  211. data/samples/source_with_hidden_directories/.hidden/uncommunicative_method_name.rb +0 -5
  212. data/samples/source_with_non_ruby_files/uncommunicative_parameter_name.rb +0 -6
  213. data/spec/reek/smell_detectors/syntax_spec.rb +0 -17
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Reek
4
+ module Report
5
+ module ProgressFormatter
6
+ #
7
+ # Base class for progress formatters.
8
+ # Is responsible for formatting the progress emitted for each examiner
9
+ #
10
+ # @abstract Override {#header, #progress, #footer} to implement a progress formatter.
11
+ class Base
12
+ attr_reader :sources_count
13
+
14
+ def initialize(sources_count)
15
+ @sources_count = sources_count
16
+ end
17
+
18
+ def header
19
+ raise NotImplementedError
20
+ end
21
+
22
+ def progress(_examiner)
23
+ raise NotImplementedError
24
+ end
25
+
26
+ def footer
27
+ raise NotImplementedError
28
+ end
29
+ end
30
+
31
+ #
32
+ # Shows the status of each source as either a dot (.) or an S
33
+ #
34
+ class Dots < Base
35
+ NO_WARNINGS_COLOR = :green
36
+ WARNINGS_COLOR = :red
37
+
38
+ def header
39
+ "Inspecting #{sources_count} file(s):\n"
40
+ end
41
+
42
+ def progress(examiner)
43
+ examiner.smelly? ? display_smelly : display_clean
44
+ end
45
+
46
+ def footer
47
+ "\n\n"
48
+ end
49
+
50
+ private
51
+
52
+ def display_clean
53
+ Rainbow('.').color(NO_WARNINGS_COLOR)
54
+ end
55
+
56
+ def display_smelly
57
+ Rainbow('S').color(WARNINGS_COLOR)
58
+ end
59
+ end
60
+
61
+ #
62
+ # Does not show progress
63
+ #
64
+ class Quiet < Base
65
+ def header
66
+ ''
67
+ end
68
+
69
+ def progress(_examiner)
70
+ ''
71
+ end
72
+
73
+ def footer
74
+ ''
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'code_climate/code_climate_formatter'
4
+
5
+ module Reek
6
+ module Report
7
+ #
8
+ # Basic formatter that just shows a simple message for each warning,
9
+ # prepended with the result of the passed-in location formatter.
10
+ #
11
+ class SimpleWarningFormatter
12
+ def initialize(location_formatter: BlankLocationFormatter)
13
+ @location_formatter = location_formatter
14
+ end
15
+
16
+ def format(warning)
17
+ "#{location_formatter.format(warning)}#{warning.base_message}"
18
+ end
19
+
20
+ # @quality :reek:UtilityFunction
21
+ def format_code_climate_hash(warning)
22
+ CodeClimateFormatter.new(warning).render
23
+ end
24
+
25
+ def format_list(warnings)
26
+ warnings.map { |warning| " #{format(warning)}" }.join("\n")
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :location_formatter
32
+ end
33
+ end
34
+ end
@@ -49,8 +49,7 @@ module Reek
49
49
  def summarize_single_examiner(examiner)
50
50
  result = heading_formatter.header(examiner)
51
51
  if examiner.smelly?
52
- formatted_list = report_formatter.format_list(examiner.smells,
53
- formatter: warning_formatter)
52
+ formatted_list = warning_formatter.format_list(examiner.smells)
54
53
  result += ":\n#{formatted_list}"
55
54
  end
56
55
  result
@@ -34,8 +34,8 @@ module Reek
34
34
  end
35
35
  end
36
36
 
37
- # :reek:FeatureEnvy
38
- # :reek:NestedIterators: { max_allowed_nesting: 2 }
37
+ # @quality :reek:FeatureEnvy
38
+ # @quality :reek:NestedIterators { max_allowed_nesting: 2 }
39
39
  def file(name, smells)
40
40
  REXML::Element.new('file').tap do |file|
41
41
  file.add_attribute 'name', File.realpath(name)
@@ -47,7 +47,7 @@ module Reek
47
47
  end
48
48
  end
49
49
 
50
- # :reek:UtilityFunction
50
+ # @quality :reek:UtilityFunction
51
51
  def error(smell, line)
52
52
  REXML::Element.new('error').tap do |error|
53
53
  error.add_attributes 'column' => 0,
@@ -12,7 +12,7 @@ module Reek
12
12
  #
13
13
  class YAMLReport < BaseReport
14
14
  def show(out = $stdout)
15
- out.print smells.map { |smell| warning_formatter.format_hash(smell) }.to_yaml
15
+ out.print smells.map(&:yaml_hash).to_yaml
16
16
  end
17
17
  end
18
18
  end
@@ -7,11 +7,11 @@ module Reek
7
7
  class SmellConfiguration
8
8
  # The name of the config field that specifies whether a smell is
9
9
  # enabled. Set to +true+ or +false+.
10
- ENABLED_KEY = 'enabled'.freeze
10
+ ENABLED_KEY = 'enabled'
11
11
 
12
12
  # The name of the config field that sets scope-specific overrides
13
13
  # for other values in the current smell detector's configuration.
14
- OVERRIDES_KEY = 'overrides'.freeze
14
+ OVERRIDES_KEY = 'overrides'
15
15
 
16
16
  def initialize(hash)
17
17
  @options = hash
@@ -15,10 +15,9 @@ require_relative 'smell_detectors/manual_dispatch'
15
15
  require_relative 'smell_detectors/module_initialize'
16
16
  require_relative 'smell_detectors/nested_iterators'
17
17
  require_relative 'smell_detectors/nil_check'
18
- require_relative 'smell_detectors/prima_donna_method'
18
+ require_relative 'smell_detectors/missing_safe_method'
19
19
  require_relative 'smell_detectors/repeated_conditional'
20
20
  require_relative 'smell_detectors/subclassed_from_core_class'
21
- require_relative 'smell_detectors/syntax'
22
21
  require_relative 'smell_detectors/too_many_instance_variables'
23
22
  require_relative 'smell_detectors/too_many_constants'
24
23
  require_relative 'smell_detectors/too_many_methods'
@@ -28,7 +28,6 @@ module Reek
28
28
  def sniff
29
29
  attributes_in_context.map do |_attribute, line|
30
30
  smell_warning(
31
- context: context,
32
31
  lines: [line],
33
32
  message: 'is a writable attribute')
34
33
  end
@@ -15,14 +15,14 @@ module Reek
15
15
  # - {file:README.md}
16
16
  # for details.
17
17
  #
18
- # :reek:UnusedPrivateMethod: { exclude: [ smell_warning ] }
19
- # :reek:TooManyMethods: { max_methods: 18 }
18
+ # @quality :reek:UnusedPrivateMethod { exclude: [ smell_warning ] }
19
+ # @quality :reek:TooManyMethods { max_methods: 18 }
20
20
  class BaseDetector
21
21
  attr_reader :config
22
22
  # The name of the config field that lists the names of code contexts
23
23
  # that should not be checked. Add this field to the config for each
24
24
  # smell that should ignore this code element.
25
- EXCLUDE_KEY = 'exclude'.freeze
25
+ EXCLUDE_KEY = 'exclude'
26
26
 
27
27
  # The default value for the +EXCLUDE_KEY+ if it isn't specified
28
28
  # in any configuration file.
@@ -78,12 +78,9 @@ module Reek
78
78
  ctx.config_for(self.class)
79
79
  end
80
80
 
81
- # :reek:FeatureEnvy
82
- def smell_warning(options = {})
83
- context = options.fetch(:context)
84
- exp = context.exp
81
+ def smell_warning(**options)
85
82
  SmellWarning.new(self,
86
- source: exp.source,
83
+ source: expression.source,
87
84
  context: context.full_name,
88
85
  lines: options.fetch(:lines),
89
86
  message: options.fetch(:message),
@@ -99,7 +96,7 @@ module Reek
99
96
  [:def, :defs]
100
97
  end
101
98
 
102
- # :reek:UtilityFunction
99
+ # @quality :reek:UtilityFunction
103
100
  def default_config
104
101
  {
105
102
  SmellConfiguration::ENABLED_KEY => true,
@@ -138,14 +135,14 @@ module Reek
138
135
  # Note that we assume a valid name - exceptions are not handled here.
139
136
  #
140
137
  # @param detector_name [String] the detector in question, e.g. 'DuplicateMethodCall'
141
- # @return [SmellDetector] - this will return the class, not an instance
138
+ # @return [SmellDetector] this will return the class, not an instance
142
139
  #
143
140
  def to_detector(detector_name)
144
141
  SmellDetectors.const_get detector_name
145
142
  end
146
143
 
147
144
  #
148
- # @return [Set<Symbol>] - all configuration keys that are available for this detector
145
+ # @return [Set<Symbol>] all configuration keys that are available for this detector
149
146
  #
150
147
  def configuration_keys
151
148
  Set.new(default_config.keys.map(&:to_sym))
@@ -24,7 +24,6 @@ module Reek
24
24
  [:true, :false].include?(value.type)
25
25
  end.map do |parameter, _value|
26
26
  smell_warning(
27
- context: context,
28
27
  lines: [source_line],
29
28
  message: "has boolean parameter '#{parameter}'",
30
29
  parameters: { parameter: parameter.to_s })
@@ -28,7 +28,6 @@ module Reek
28
28
  class_variables_in_context.map do |variable, occurences|
29
29
  lines = occurences.map(&:line)
30
30
  smell_warning(
31
- context: context,
32
31
  lines: lines,
33
32
  message: "declares the class variable '#{variable}'",
34
33
  parameters: { name: variable.to_s })
@@ -49,18 +49,32 @@ module Reek
49
49
  #
50
50
  # @return [Array<SmellWarning>]
51
51
  #
52
- # :reek:FeatureEnvy
53
52
  def sniff
54
- ControlParameterCollector.new(context).control_parameters.map do |control_parameter|
53
+ control_parameters.map do |control_parameter|
55
54
  argument = control_parameter.name.to_s
56
55
  smell_warning(
57
- context: context,
58
56
  lines: control_parameter.lines,
59
57
  message: "is controlled by argument '#{argument}'",
60
58
  parameters: { argument: argument })
61
59
  end
62
60
  end
63
61
 
62
+ private
63
+
64
+ def control_parameters
65
+ potential_parameters.
66
+ map { |param| FoundControlParameter.new(param, find_matches(param)) }.
67
+ select(&:smells?)
68
+ end
69
+
70
+ def potential_parameters
71
+ expression.parameter_names
72
+ end
73
+
74
+ def find_matches(param)
75
+ ControlParameterFinder.new(expression, param).find_matches
76
+ end
77
+
64
78
  #
65
79
  # Collects information about a single control parameter.
66
80
  #
@@ -166,35 +180,6 @@ module Reek
166
180
  end
167
181
 
168
182
  private_constant :ControlParameterFinder
169
-
170
- #
171
- # Collects all control parameters in a given context.
172
- #
173
- class ControlParameterCollector
174
- def initialize(context)
175
- @context = context
176
- end
177
-
178
- def control_parameters
179
- potential_parameters.
180
- map { |param| FoundControlParameter.new(param, find_matches(param)) }.
181
- select(&:smells?)
182
- end
183
-
184
- private
185
-
186
- attr_reader :context
187
-
188
- def potential_parameters
189
- context.exp.parameter_names
190
- end
191
-
192
- def find_matches(param)
193
- ControlParameterFinder.new(context.exp, param).find_matches
194
- end
195
- end
196
-
197
- private_constant :ControlParameterCollector
198
183
  end
199
184
  end
200
185
  end
@@ -24,7 +24,7 @@ module Reek
24
24
  # reported as a DataClump unless there are more than this many
25
25
  # methods containing those parameters.
26
26
  #
27
- MAX_COPIES_KEY = 'max_copies'.freeze
27
+ MAX_COPIES_KEY = 'max_copies'
28
28
  DEFAULT_MAX_COPIES = 2
29
29
 
30
30
  #
@@ -32,7 +32,7 @@ module Reek
32
32
  # size. No group of common parameters will be reported as
33
33
  # a DataClump unless it contains at least this many parameters.
34
34
  #
35
- MIN_CLUMP_SIZE_KEY = 'min_clump_size'.freeze
35
+ MIN_CLUMP_SIZE_KEY = 'min_clump_size'
36
36
  DEFAULT_MIN_CLUMP_SIZE = 2
37
37
 
38
38
  def self.contexts # :nodoc:
@@ -54,7 +54,6 @@ module Reek
54
54
  MethodGroup.new(context, min_clump_size, max_copies).clumps.map do |clump, methods|
55
55
  methods_length = methods.length
56
56
  smell_warning(
57
- context: context,
58
57
  lines: methods.map(&:line),
59
58
  message: "takes parameters #{DataClump.print_clump(clump)} " \
60
59
  "to #{methods_length} methods",
@@ -101,7 +100,7 @@ module Reek
101
100
  end.uniq
102
101
  end
103
102
 
104
- # :reek:UtilityFunction
103
+ # @quality :reek:UtilityFunction
105
104
  def common_argument_names_for(methods)
106
105
  methods.map(&:arg_names).inject(:&)
107
106
  end
@@ -21,13 +21,13 @@ module Reek
21
21
  class DuplicateMethodCall < BaseDetector
22
22
  # The name of the config field that sets the maximum number of
23
23
  # identical calls to be permitted within any single method.
24
- MAX_ALLOWED_CALLS_KEY = 'max_calls'.freeze
24
+ MAX_ALLOWED_CALLS_KEY = 'max_calls'
25
25
  DEFAULT_MAX_CALLS = 1
26
26
 
27
27
  # The name of the config field that sets the names of any
28
28
  # methods for which identical calls should be to be permitted
29
29
  # within any single method.
30
- ALLOW_CALLS_KEY = 'allow_calls'.freeze
30
+ ALLOW_CALLS_KEY = 'allow_calls'
31
31
  DEFAULT_ALLOW_CALLS = [].freeze
32
32
 
33
33
  def self.default_config
@@ -47,7 +47,6 @@ module Reek
47
47
  call = found_call.call
48
48
  occurs = found_call.occurs
49
49
  smell_warning(
50
- context: context,
51
50
  lines: found_call.lines,
52
51
  message: "calls '#{call}' #{occurs} times",
53
52
  parameters: { name: call, count: occurs })
@@ -118,8 +117,8 @@ module Reek
118
117
 
119
118
  attr_reader :allow_calls, :max_allowed_calls
120
119
 
121
- # :reek:TooManyStatements: { max_statements: 6 }
122
- # :reek:DuplicateMethodCall: { max_calls: 2 }
120
+ # @quality :reek:TooManyStatements { max_statements: 6 }
121
+ # @quality :reek:DuplicateMethodCall { max_calls: 2 }
123
122
  def collect_calls(result)
124
123
  context.local_nodes(:send, [:mlhs]) do |call_node|
125
124
  next if call_node.object_creation_call?
@@ -135,7 +134,7 @@ module Reek
135
134
  found_call.occurs > max_allowed_calls && !allow_calls?(found_call.call)
136
135
  end
137
136
 
138
- # :reek:UtilityFunction
137
+ # @quality :reek:UtilityFunction
139
138
  def simple_method_call?(call_node)
140
139
  !call_node.receiver && call_node.args.empty?
141
140
  end
@@ -47,7 +47,6 @@ module Reek
47
47
  return [] unless context.references_self?
48
48
  envious_receivers.map do |name, lines|
49
49
  smell_warning(
50
- context: context,
51
50
  lines: lines,
52
51
  message: "refers to '#{name}' more than self (maybe move it to another class?)",
53
52
  parameters: { name: name.to_s })
@@ -37,7 +37,6 @@ module Reek
37
37
  message = "assumes too much for instance variable '#{assumption}'"
38
38
 
39
39
  smell_warning(
40
- context: context,
41
40
  lines: [source_line],
42
41
  message: message,
43
42
  parameters: { assumption: assumption.to_s })
@@ -22,7 +22,6 @@ module Reek
22
22
  def sniff
23
23
  return [] if descriptive_context? || context.namespace_module?
24
24
  [smell_warning(
25
- context: context,
26
25
  lines: [source_line],
27
26
  message: 'has no descriptive comment')]
28
27
  end