reek 4.5.1 → 5.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 (311) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +17 -12
  3. data/.rubocop.yml +88 -33
  4. data/.simplecov +1 -0
  5. data/.travis.yml +9 -11
  6. data/.yardopts +1 -1
  7. data/CHANGELOG.md +108 -3
  8. data/CONTRIBUTING.md +1 -1
  9. data/Dockerfile +6 -5
  10. data/Gemfile +10 -9
  11. data/README.md +118 -69
  12. data/Rakefile +16 -3
  13. data/bin/code_climate_reek +1 -0
  14. data/bin/reek +2 -3
  15. data/docs/API.md +2 -9
  16. data/docs/Basic-Smell-Options.md +51 -11
  17. data/docs/Code-Smells.md +1 -1
  18. data/docs/Command-Line-Options.md +14 -4
  19. data/docs/Duplicate-Method-Call.md +49 -1
  20. data/docs/Feature-Envy.md +44 -0
  21. data/docs/How-To-Write-New-Detectors.md +13 -13
  22. data/docs/Instance-Variable-Assumption.md +1 -1
  23. data/docs/Irresponsible-Module.md +8 -1
  24. data/docs/{Prima-Donna-Method.md → Missing-Safe-Method.md} +36 -7
  25. data/docs/Nil-Check.md +1 -1
  26. data/docs/RSpec-matchers.md +5 -10
  27. data/docs/Rake-Task.md +1 -1
  28. data/docs/Reek-4-to-Reek-5-migration.md +193 -0
  29. data/docs/Reek-Driven-Development.md +1 -1
  30. data/docs/Uncommunicative-Method-Name.md +45 -6
  31. data/docs/Uncommunicative-Module-Name.md +49 -7
  32. data/docs/Uncommunicative-Parameter-Name.md +43 -5
  33. data/docs/Uncommunicative-Variable-Name.md +73 -2
  34. data/docs/Unused-Private-Method.md +30 -3
  35. data/docs/defaults.reek.yml +129 -0
  36. data/docs/templates/default/docstring/setup.rb +1 -8
  37. data/docs/yard_plugin.rb +1 -0
  38. data/features/command_line_interface/basic_usage.feature +2 -2
  39. data/features/command_line_interface/options.feature +49 -3
  40. data/features/command_line_interface/show_progress.feature +4 -4
  41. data/features/command_line_interface/smell_selection.feature +1 -1
  42. data/features/command_line_interface/smells_count.feature +6 -6
  43. data/features/command_line_interface/stdin.feature +30 -4
  44. data/features/configuration_files/accept_setting.feature +45 -28
  45. data/features/configuration_files/directory_specific_directives.feature +80 -75
  46. data/features/configuration_files/exclude_directives.feature +11 -10
  47. data/features/configuration_files/exclude_paths_directives.feature +43 -0
  48. data/features/configuration_files/masking_smells.feature +38 -9
  49. data/features/configuration_files/mix_accept_reject_setting.feature +31 -28
  50. data/features/configuration_files/reject_setting.feature +52 -41
  51. data/features/configuration_files/schema_validation.feature +59 -0
  52. data/features/configuration_files/unused_private_method.feature +18 -16
  53. data/features/configuration_loading.feature +53 -10
  54. data/features/configuration_via_source_comments/erroneous_source_comments.feature +3 -3
  55. data/features/configuration_via_source_comments/well_formed_source_comments.feature +2 -2
  56. data/features/locales.feature +32 -0
  57. data/features/rake_task/rake_task.feature +58 -18
  58. data/features/reports/codeclimate.feature +59 -0
  59. data/features/reports/json.feature +3 -3
  60. data/features/reports/reports.feature +34 -34
  61. data/features/reports/yaml.feature +3 -3
  62. data/features/rspec_matcher.feature +40 -0
  63. data/features/samples.feature +290 -295
  64. data/features/step_definitions/reek_steps.rb +19 -7
  65. data/features/step_definitions/sample_file_steps.rb +9 -4
  66. data/features/support/env.rb +2 -11
  67. data/features/todo_list.feature +27 -25
  68. data/lib/reek/ast/ast_node_class_map.rb +1 -0
  69. data/lib/reek/ast/builder.rb +16 -0
  70. data/lib/reek/ast/node.rb +50 -58
  71. data/lib/reek/ast/object_refs.rb +2 -1
  72. data/lib/reek/ast/reference_collector.rb +4 -7
  73. data/lib/reek/ast/sexp_extensions/arguments.rb +1 -5
  74. data/lib/reek/ast/sexp_extensions/attribute_assignments.rb +1 -0
  75. data/lib/reek/ast/sexp_extensions/begin.rb +17 -0
  76. data/lib/reek/ast/sexp_extensions/block.rb +1 -0
  77. data/lib/reek/ast/sexp_extensions/case.rb +2 -1
  78. data/lib/reek/ast/sexp_extensions/constant.rb +2 -0
  79. data/lib/reek/ast/sexp_extensions/if.rb +9 -1
  80. data/lib/reek/ast/sexp_extensions/lambda.rb +1 -0
  81. data/lib/reek/ast/sexp_extensions/literal.rb +1 -0
  82. data/lib/reek/ast/sexp_extensions/logical_operators.rb +2 -1
  83. data/lib/reek/ast/sexp_extensions/methods.rb +5 -6
  84. data/lib/reek/ast/sexp_extensions/module.rb +55 -8
  85. data/lib/reek/ast/sexp_extensions/nested_assignables.rb +1 -0
  86. data/lib/reek/ast/sexp_extensions/self.rb +1 -0
  87. data/lib/reek/ast/sexp_extensions/send.rb +1 -4
  88. data/lib/reek/ast/sexp_extensions/super.rb +1 -0
  89. data/lib/reek/ast/sexp_extensions/symbols.rb +1 -0
  90. data/lib/reek/ast/sexp_extensions/variables.rb +1 -0
  91. data/lib/reek/ast/sexp_extensions/when.rb +1 -0
  92. data/lib/reek/ast/sexp_extensions/yield.rb +1 -0
  93. data/lib/reek/ast/sexp_extensions.rb +2 -0
  94. data/lib/reek/cli/application.rb +12 -11
  95. data/lib/reek/cli/command/base_command.rb +1 -0
  96. data/lib/reek/cli/command/report_command.rb +5 -3
  97. data/lib/reek/cli/command/todo_list_command.rb +9 -8
  98. data/lib/reek/cli/options.rb +56 -24
  99. data/lib/reek/cli/silencer.rb +15 -3
  100. data/lib/reek/cli/status.rb +11 -0
  101. data/lib/reek/code_comment.rb +18 -18
  102. data/lib/reek/configuration/app_configuration.rb +34 -28
  103. data/lib/reek/configuration/configuration_converter.rb +110 -0
  104. data/lib/reek/configuration/configuration_file_finder.rb +67 -31
  105. data/lib/reek/configuration/configuration_validator.rb +13 -23
  106. data/lib/reek/configuration/default_directive.rb +18 -3
  107. data/lib/reek/configuration/directory_directives.rb +18 -11
  108. data/lib/reek/configuration/excluded_paths.rb +2 -1
  109. data/lib/reek/configuration/rake_task_converter.rb +29 -0
  110. data/lib/reek/configuration/schema.yml +210 -0
  111. data/lib/reek/configuration/schema_validator.rb +38 -0
  112. data/lib/reek/context/attribute_context.rb +4 -3
  113. data/lib/reek/context/class_context.rb +1 -0
  114. data/lib/reek/context/code_context.rb +49 -44
  115. data/lib/reek/context/ghost_context.rb +1 -3
  116. data/lib/reek/context/method_context.rb +26 -18
  117. data/lib/reek/context/module_context.rb +11 -11
  118. data/lib/reek/context/root_context.rb +1 -4
  119. data/lib/reek/context/send_context.rb +3 -2
  120. data/lib/reek/context/singleton_attribute_context.rb +1 -0
  121. data/lib/reek/context/singleton_method_context.rb +1 -0
  122. data/lib/reek/context/statement_counter.rb +1 -0
  123. data/lib/reek/context/visibility_tracker.rb +1 -0
  124. data/lib/reek/context_builder.rb +68 -43
  125. data/lib/reek/detector_repository.rb +65 -0
  126. data/lib/reek/documentation_link.rb +28 -0
  127. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +17 -14
  128. data/lib/reek/errors/bad_detector_in_comment_error.rb +15 -12
  129. data/lib/reek/errors/base_error.rb +12 -0
  130. data/lib/reek/errors/config_file_error.rb +11 -0
  131. data/lib/reek/errors/encoding_error.rb +43 -0
  132. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +16 -13
  133. data/lib/reek/errors/incomprehensible_source_error.rb +46 -0
  134. data/lib/reek/errors/syntax_error.rb +41 -0
  135. data/lib/reek/examiner.rb +35 -58
  136. data/lib/reek/logging_error_handler.rb +18 -0
  137. data/lib/reek/rake/task.rb +8 -5
  138. data/lib/reek/report/base_report.rb +9 -12
  139. data/lib/reek/report/code_climate/code_climate_configuration.rb +2 -1
  140. data/lib/reek/report/code_climate/code_climate_configuration.yml +7 -7
  141. data/lib/reek/report/code_climate/code_climate_fingerprint.rb +1 -0
  142. data/lib/reek/report/code_climate/code_climate_formatter.rb +1 -0
  143. data/lib/reek/report/code_climate/code_climate_report.rb +1 -0
  144. data/lib/reek/report/code_climate.rb +1 -0
  145. data/lib/reek/report/documentation_link_warning_formatter.rb +17 -0
  146. data/lib/reek/report/heading_formatter.rb +54 -0
  147. data/lib/reek/report/html_report.rb +1 -0
  148. data/lib/reek/report/json_report.rb +2 -1
  149. data/lib/reek/report/location_formatter.rb +40 -0
  150. data/lib/reek/report/progress_formatter.rb +79 -0
  151. data/lib/reek/report/simple_warning_formatter.rb +34 -0
  152. data/lib/reek/report/text_report.rb +2 -2
  153. data/lib/reek/report/xml_report.rb +4 -3
  154. data/lib/reek/report/yaml_report.rb +2 -1
  155. data/lib/reek/report.rb +16 -10
  156. data/lib/reek/smell_configuration.rb +65 -0
  157. data/lib/reek/smell_detectors/attribute.rb +6 -13
  158. data/lib/reek/smell_detectors/base_detector.rb +36 -30
  159. data/lib/reek/smell_detectors/boolean_parameter.rb +4 -6
  160. data/lib/reek/smell_detectors/class_variable.rb +6 -15
  161. data/lib/reek/smell_detectors/control_parameter.rb +19 -34
  162. data/lib/reek/smell_detectors/data_clump.rb +16 -10
  163. data/lib/reek/smell_detectors/duplicate_method_call.rb +24 -18
  164. data/lib/reek/smell_detectors/feature_envy.rb +10 -8
  165. data/lib/reek/smell_detectors/instance_variable_assumption.rb +15 -24
  166. data/lib/reek/smell_detectors/irresponsible_module.rb +6 -13
  167. data/lib/reek/smell_detectors/long_parameter_list.rb +11 -9
  168. data/lib/reek/smell_detectors/long_yield_list.rb +11 -8
  169. data/lib/reek/smell_detectors/manual_dispatch.rb +7 -9
  170. data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +45 -15
  171. data/lib/reek/smell_detectors/module_initialize.rb +7 -11
  172. data/lib/reek/smell_detectors/nested_iterators.rb +17 -25
  173. data/lib/reek/smell_detectors/nil_check.rb +9 -16
  174. data/lib/reek/smell_detectors/repeated_conditional.rb +14 -12
  175. data/lib/reek/smell_detectors/subclassed_from_core_class.rb +8 -9
  176. data/lib/reek/smell_detectors/too_many_constants.rb +11 -10
  177. data/lib/reek/smell_detectors/too_many_instance_variables.rb +11 -7
  178. data/lib/reek/smell_detectors/too_many_methods.rb +12 -8
  179. data/lib/reek/smell_detectors/too_many_statements.rb +11 -7
  180. data/lib/reek/smell_detectors/uncommunicative_method_name.rb +11 -12
  181. data/lib/reek/smell_detectors/uncommunicative_module_name.rb +15 -19
  182. data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +18 -23
  183. data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +27 -28
  184. data/lib/reek/smell_detectors/unused_parameters.rb +5 -7
  185. data/lib/reek/smell_detectors/unused_private_method.rb +14 -22
  186. data/lib/reek/smell_detectors/utility_function.rb +13 -17
  187. data/lib/reek/smell_detectors.rb +2 -1
  188. data/lib/reek/smell_warning.rb +93 -0
  189. data/lib/reek/source/source_code.rb +65 -45
  190. data/lib/reek/source/source_locator.rb +24 -11
  191. data/lib/reek/spec/should_reek.rb +3 -2
  192. data/lib/reek/spec/should_reek_of.rb +13 -26
  193. data/lib/reek/spec/should_reek_only_of.rb +5 -4
  194. data/lib/reek/spec/smell_matcher.rb +2 -1
  195. data/lib/reek/spec.rb +12 -9
  196. data/lib/reek/tree_dresser.rb +9 -8
  197. data/lib/reek/version.rb +2 -1
  198. data/lib/reek.rb +1 -0
  199. data/reek.gemspec +5 -6
  200. data/samples/checkstyle.xml +1 -1
  201. data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +29 -0
  202. data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +30 -0
  203. data/samples/configuration/full_configuration.reek +8 -4
  204. data/samples/configuration/full_mask.reek +5 -4
  205. data/samples/configuration/partial_mask.reek +3 -2
  206. data/samples/configuration/regular_configuration/.reek.yml +4 -0
  207. data/samples/configuration/regular_configuration/empty_sub_directory/.gitignore +0 -0
  208. data/samples/no_config_file/.keep +0 -0
  209. data/samples/paths.rb +5 -4
  210. data/samples/source_with_hidden_directories/.hidden/hidden.rb +1 -0
  211. data/samples/source_with_hidden_directories/not_hidden.rb +1 -0
  212. data/spec/factories/factories.rb +4 -23
  213. data/spec/quality/reek_source_spec.rb +5 -3
  214. data/spec/reek/ast/node_spec.rb +103 -10
  215. data/spec/reek/ast/reference_collector_spec.rb +1 -18
  216. data/spec/reek/ast/sexp_extensions_spec.rb +15 -34
  217. data/spec/reek/cli/application_spec.rb +77 -43
  218. data/spec/reek/cli/command/report_command_spec.rb +2 -2
  219. data/spec/reek/cli/command/todo_list_command_spec.rb +18 -73
  220. data/spec/reek/cli/options_spec.rb +4 -0
  221. data/spec/reek/cli/silencer_spec.rb +28 -0
  222. data/spec/reek/code_comment_spec.rb +31 -31
  223. data/spec/reek/configuration/app_configuration_spec.rb +46 -33
  224. data/spec/reek/configuration/configuration_file_finder_spec.rb +140 -35
  225. data/spec/reek/configuration/default_directive_spec.rb +1 -1
  226. data/spec/reek/configuration/directory_directives_spec.rb +6 -7
  227. data/spec/reek/configuration/excluded_paths_spec.rb +6 -6
  228. data/spec/reek/configuration/rake_task_converter_spec.rb +33 -0
  229. data/spec/reek/configuration/schema_validator_spec.rb +165 -0
  230. data/spec/reek/context/code_context_spec.rb +72 -108
  231. data/spec/reek/context/ghost_context_spec.rb +9 -9
  232. data/spec/reek/context/method_context_spec.rb +3 -3
  233. data/spec/reek/context/module_context_spec.rb +8 -4
  234. data/spec/reek/context/root_context_spec.rb +1 -1
  235. data/spec/reek/context/statement_counter_spec.rb +1 -0
  236. data/spec/reek/context_builder_spec.rb +20 -0
  237. data/spec/reek/{smell_detectors/detector_repository_spec.rb → detector_repository_spec.rb} +3 -3
  238. data/spec/reek/documentation_link_spec.rb +20 -0
  239. data/spec/reek/errors/base_error_spec.rb +13 -0
  240. data/spec/reek/examiner_spec.rb +173 -66
  241. data/spec/reek/logging_error_handler_spec.rb +24 -0
  242. data/spec/reek/rake/task_spec.rb +25 -2
  243. data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +1 -1
  244. data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +83 -79
  245. data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +6 -6
  246. data/spec/reek/report/code_climate/code_climate_report_spec.rb +22 -22
  247. data/spec/reek/report/json_report_spec.rb +13 -46
  248. data/spec/reek/report/{formatter/location_formatter_spec.rb → location_formatter_spec.rb} +5 -5
  249. data/spec/reek/report/{formatter/progress_formatter_spec.rb → progress_formatter_spec.rb} +4 -4
  250. data/spec/reek/report/text_report_spec.rb +4 -4
  251. data/spec/reek/report/xml_report_spec.rb +3 -3
  252. data/spec/reek/report/yaml_report_spec.rb +18 -47
  253. data/spec/reek/report_spec.rb +3 -3
  254. data/spec/reek/{smell_detectors/smell_configuration_spec.rb → smell_configuration_spec.rb} +3 -3
  255. data/spec/reek/smell_detectors/base_detector_spec.rb +4 -5
  256. data/spec/reek/smell_detectors/boolean_parameter_spec.rb +2 -2
  257. data/spec/reek/smell_detectors/class_variable_spec.rb +26 -32
  258. data/spec/reek/smell_detectors/control_parameter_spec.rb +34 -4
  259. data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +5 -5
  260. data/spec/reek/smell_detectors/feature_envy_spec.rb +65 -10
  261. data/spec/reek/smell_detectors/irresponsible_module_spec.rb +59 -21
  262. data/spec/reek/smell_detectors/manual_dispatch_spec.rb +13 -0
  263. data/spec/reek/smell_detectors/missing_safe_method_spec.rb +62 -0
  264. data/spec/reek/smell_detectors/module_initialize_spec.rb +37 -2
  265. data/spec/reek/smell_detectors/nested_iterators_spec.rb +2 -2
  266. data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -5
  267. data/spec/reek/smell_detectors/too_many_constants_spec.rb +3 -3
  268. data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +1 -1
  269. data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +6 -6
  270. data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +6 -4
  271. data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +36 -15
  272. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +11 -11
  273. data/spec/reek/smell_detectors/unused_parameters_spec.rb +4 -4
  274. data/spec/reek/smell_detectors/unused_private_method_spec.rb +21 -10
  275. data/spec/reek/smell_detectors/utility_function_spec.rb +57 -5
  276. data/spec/reek/{smell_detectors/smell_warning_spec.rb → smell_warning_spec.rb} +21 -17
  277. data/spec/reek/source/source_code_spec.rb +27 -61
  278. data/spec/reek/source/source_locator_spec.rb +95 -33
  279. data/spec/reek/spec/should_reek_of_spec.rb +25 -30
  280. data/spec/reek/spec/should_reek_only_of_spec.rb +6 -6
  281. data/spec/reek/spec/should_reek_spec.rb +8 -8
  282. data/spec/reek/spec/smell_matcher_spec.rb +23 -23
  283. data/spec/reek/tree_dresser_spec.rb +12 -17
  284. data/spec/spec_helper.rb +8 -17
  285. data/tasks/configuration.rake +10 -7
  286. metadata +91 -45
  287. data/defaults.reek +0 -128
  288. data/lib/reek/report/formatter/heading_formatter.rb +0 -51
  289. data/lib/reek/report/formatter/location_formatter.rb +0 -41
  290. data/lib/reek/report/formatter/progress_formatter.rb +0 -80
  291. data/lib/reek/report/formatter/simple_warning_formatter.rb +0 -35
  292. data/lib/reek/report/formatter/wiki_link_warning_formatter.rb +0 -35
  293. data/lib/reek/report/formatter.rb +0 -32
  294. data/lib/reek/smell_detectors/detector_repository.rb +0 -66
  295. data/lib/reek/smell_detectors/smell_configuration.rb +0 -66
  296. data/lib/reek/smell_detectors/smell_warning.rb +0 -88
  297. data/samples/configuration/non_public_modifiers_mask.reek +0 -3
  298. data/samples/smelly_with_inline_mask.rb +0 -8
  299. data/samples/smelly_with_modifiers.rb +0 -12
  300. data/samples/source_with_hidden_directories/.hidden/uncommunicative_method_name.rb +0 -5
  301. data/samples/source_with_non_ruby_files/uncommunicative_parameter_name.rb +0 -6
  302. data/spec/reek/smell_detectors/prima_donna_method_spec.rb +0 -50
  303. data/tasks/mutant.rake +0 -14
  304. /data/{samples/configuration/.reek → .reek.yml} +0 -0
  305. /data/samples/{clean.rb → clean_source/clean.rb} +0 -0
  306. /data/samples/{exceptions.reek → configuration/home/home.reek.yml} +0 -0
  307. /data/samples/{inline.rb → smelly_source/inline.rb} +0 -0
  308. /data/samples/{optparse.rb → smelly_source/optparse.rb} +0 -0
  309. /data/samples/{redcloth.rb → smelly_source/redcloth.rb} +0 -0
  310. /data/samples/{smelly.rb → smelly_source/smelly.rb} +0 -0
  311. /data/samples/{source_with_hidden_directories/uncommunicative_parameter_name.rb → source_with_non_ruby_files/ruby.rb} +0 -0
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  - [Overview](#overview)
8
8
  - [Quickstart](#quickstart)
9
9
  - [Example](#example)
10
- - [Supported rubies](#supported-rubies)
10
+ - [Supported Ruby versions](#supported-ruby-versions)
11
11
  - [Fixing Smell Warnings](#fixing-smell-warnings)
12
12
  - [Sources](#sources)
13
13
  - [Code smells](#code-smells)
@@ -16,8 +16,9 @@
16
16
  - [Configuration file](#configuration-file)
17
17
  - [Configuration loading](#configuration-loading)
18
18
  - [Configuration options](#configuration-options)
19
- - [Source code comments](#source-code-comments)
20
19
  - [Generating a 'todo' list](#generating-a-todo-list)
20
+ - [Beware of multiple configuration files](#beware-of-multiple-configuration-files)
21
+ - [Source code comments](#source-code-comments)
21
22
  - [Usage](#usage)
22
23
  - [Developing Reek / Contributing](#developing-reek--contributing)
23
24
  - [Output formats](#output-formats)
@@ -38,13 +39,18 @@
38
39
  * [![Gem Version](https://badge.fury.io/rb/reek.svg)](https://badge.fury.io/rb/reek)
39
40
  * ![](http://img.shields.io/github/tag/troessner/reek.svg)
40
41
  * ![](http://img.shields.io/badge/license-MIT-brightgreen.svg)
41
- * [![Dependency Status](https://gemnasium.com/badges/github.com/troessner/reek.svg)](https://gemnasium.com/github.com/troessner/reek)
42
42
  * [![Inline docs](https://inch-ci.org/github/troessner/reek.png)](https://inch-ci.org/github/troessner/reek)
43
43
  * [![Code Climate](https://codeclimate.com/github/troessner/reek/badges/gpa.svg)](https://codeclimate.com/github/troessner/reek)
44
44
  * [![codebeat](https://codebeat.co/badges/42fed4ff-3e55-4aed-8ecc-409b4aa539b3)](https://codebeat.co/projects/github-com-troessner-reek)
45
45
  * ![](http://ruby-gem-downloads-badge.herokuapp.com/reek?type=total)
46
46
  * ![](http://ruby-gem-downloads-badge.herokuapp.com/reek?label=downloads-current-version)
47
47
 
48
+ ## Reek 5 is out!
49
+
50
+ Reek 5 is out and with it a bunch of breaking changes. If you're a new user you can just
51
+ continue with the quickstart below. If you're a Reek 4 user and would like to upgrade to 5, don't
52
+ worry, this shouldn't take you more than 10 minutes. Check out our [Upgrade Guide](docs/Reek-4-to-Reek-5-migration.md).
53
+
48
54
  ## Quickstart
49
55
 
50
56
  Reek is a tool that examines Ruby classes, modules and methods and reports any
@@ -52,7 +58,7 @@ Reek is a tool that examines Ruby classes, modules and methods and reports any
52
58
 
53
59
  For an excellent introduction to
54
60
  [Code Smells](docs/Code-Smells.md) and Reek check out [this blog post](https://blog.codeship.com/how-to-find-ruby-code-smells-with-reek/)
55
- or [that one](https://troessner.svbtle.com/the-latest-and-greatest-additions-to-reek). There is also [this talk](https://www.youtube.com/watch?v=ZzqOuHI5MkA) from the [RubyConf Portugal](http://rubyconf.pt/).
61
+ or [that one](https://troessner.svbtle.com/the-latest-and-greatest-additions-to-reek). There is also [this talk](https://www.youtube.com/watch?v=pazYe7WRWRU) from [RubyConfBY](http://rubyconference.by/) (there is also a [slide deck](http://talks.chastell.net/rubyconf-by-lt-2016/) if you prefer that).
56
62
 
57
63
  Install it via rubygems:
58
64
 
@@ -83,24 +89,24 @@ end
83
89
  Reek will report the following code smells in this file:
84
90
 
85
91
  ```
86
- $ reek demo.rb
92
+ $ reek --no-documentation demo.rb
87
93
  Inspecting 1 file(s):
88
94
  S
89
95
 
90
96
  demo.rb -- 2 warnings:
91
- [4]:UncommunicativeMethodName: Smelly#x has the name 'x' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Method-Name.md]
92
- [5]:UncommunicativeVariableName: Smelly#x has the variable name 'y' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Variable-Name.md]
97
+ [4]:UncommunicativeMethodName: Smelly#x has the name 'x'
98
+ [5]:UncommunicativeVariableName: Smelly#x has the variable name 'y'
93
99
  ```
94
100
 
95
- ## Supported rubies
101
+ ## Supported Ruby versions
96
102
 
97
- Reek is officially running on the following MRI rubies:
103
+ Reek is officially supported for the following CRuby versions:
98
104
 
99
- - 2.1
100
- - 2.2
101
105
  - 2.3
106
+ - 2.4
107
+ - 2.5
102
108
 
103
- Other rubies like Rubinius or JRuby are not officially supported but should work as well.
109
+ Other Ruby implementations (like Rubinius or JRuby) are not officially supported but should work as well.
104
110
 
105
111
  ## Fixing Smell Warnings
106
112
 
@@ -251,12 +257,13 @@ For a summary of those CLI options see [Command-Line Options](docs/Command-Line-
251
257
  #### Configuration loading
252
258
 
253
259
  Configuring Reek via a configuration file is by far the most powerful way.
260
+ Reek expects this filename to be `.reek.yml` but you can override this via the CLI `-c` switch (see below).
254
261
 
255
- There are three ways of passing Reek a configuration file:
262
+ There are three ways of passing Reek the configuration file:
256
263
 
257
264
  1. Using the CLI `-c` switch (see [_Command-line interface_](#command-line-interface) above)
258
- 2. Having a file ending with `.reek` either in your current working directory or in a parent directory (more on that later)
259
- 3. Having a file ending with `.reek` in your home directory
265
+ 2. Having the configuration file either in your current working directory or in a parent directory (more on that later)
266
+ 3. Having the configuration file in your home directory
260
267
 
261
268
  The order in which Reek tries to find such a configuration
262
269
  file is exactly the above: first it checks if we have given
@@ -274,43 +281,46 @@ of how many `*.reek` files you might have on your filesystem.
274
281
 
275
282
  We put a lot of effort into making Reek's configuration as self explanatory as possible so the
276
283
  best way to understand it is by looking at a simple
277
- example (e.g. `config.reek` in your project directory):
284
+ example (e.g. `.reek.yml` in your project directory):
278
285
 
279
286
  ```yaml
280
287
  ---
281
288
 
282
289
  ### Generic smell configuration
283
290
 
284
- # You can disable smells completely
285
- IrresponsibleModule:
286
- enabled: false
287
-
288
- # You can use filters to silence Reek warnings.
289
- # Either because you simply disagree with Reek (we are not the police) or
290
- # because you want to fix this at a later point in time.
291
- NestedIterators:
292
- exclude:
293
- - "MyWorker#self.class_method" # should be refactored
294
- - "AnotherWorker#instance_method" # should be refactored as well
295
-
296
- # A lot of smells allow fine tuning their configuration. You can look up all available options
297
- # in the corresponding smell documentation in /docs. In most cases you probably can just go
298
- # with the defaults as documented in defaults.reek.
299
- DataClump:
300
- max_copies: 3
301
- min_clump_size: 3
291
+ detectors:
292
+ # You can disable smells completely
293
+ IrresponsibleModule:
294
+ enabled: false
295
+
296
+ # You can use filters to silence Reek warnings.
297
+ # Either because you simply disagree with Reek (we are not the police) or
298
+ # because you want to fix this at a later point in time.
299
+ NestedIterators:
300
+ exclude:
301
+ - "MyWorker#self.class_method" # should be refactored
302
+ - "AnotherWorker#instance_method" # should be refactored as well
303
+
304
+ # A lot of smells allow fine tuning their configuration. You can look up all available options
305
+ # in the corresponding smell documentation in /docs. In most cases you probably can just go
306
+ # with the defaults as documented in defaults.reek.yml.
307
+ DataClump:
308
+ max_copies: 3
309
+ min_clump_size: 3
302
310
 
303
311
  ### Directory specific configuration
304
312
 
305
313
  # You can configure smells on a per-directory base.
306
314
  # E.g. the classic Rails case: controllers smell of NestedIterators (see /docs/Nested-Iterators.md) and
307
315
  # helpers smell of UtilityFunction (see docs/Utility-Function.md)
308
- "web_app/app/controllers":
309
- NestedIterators:
310
- enabled: false
311
- "web_app/app/helpers":
312
- UtilityFunction:
313
- enabled: false
316
+ # Note that we only allow configuration on a directory level, not a file level, so all paths have to point to directories.
317
+ directories:
318
+ "web_app/app/controllers":
319
+ NestedIterators:
320
+ enabled: false
321
+ "web_app/app/helpers":
322
+ UtilityFunction:
323
+ enabled: false
314
324
 
315
325
  ### Excluding directories
316
326
 
@@ -320,6 +330,14 @@ exclude_paths:
320
330
  - lib/rake/legacy_tasks
321
331
  ```
322
332
 
333
+ As you see above, Reek's configuration consists of 3 different sections denoted by 3 different keys:
334
+
335
+ * detectors
336
+ * directories
337
+ * exclude_paths
338
+
339
+ Whatever you add to your configuration should be scoped under one of those keys.
340
+
323
341
  If you have a directory directive for which a default directive exists, the more specific
324
342
  one (which is the directory directive) will take precedence.
325
343
 
@@ -327,15 +345,12 @@ This configuration for instance:
327
345
 
328
346
  ```yaml
329
347
  ---
330
- IrresponsibleModule:
331
- enabled: false
332
-
333
- TooManyStatements:
334
- max_statements: 5
335
-
336
- "app/controllers":
348
+ detectors:
349
+ IrresponsibleModule:
350
+ enabled: false
351
+
337
352
  TooManyStatements:
338
- max_statements: 10
353
+ max_statements: 5
339
354
  ```
340
355
 
341
356
  translates to:
@@ -344,16 +359,29 @@ translates to:
344
359
  * TooManyStatements#max_statements is 10 in "app/controllers"
345
360
  * TooManyStatements#max_statements is 5 everywhere else
346
361
 
347
- For more details please check out the [Basic Smell Options](docs/Basic-Smell-Options.md)
348
- which are supported by every smell type. As you can see above, certain smell
349
- types offer a configuration that goes beyond that of the basic smell options, for instance
362
+ Every smell detector supports our [Basic Smell Options](docs/Basic-Smell-Options.md). As you can see above,
363
+ certain smell types offer a configuration that goes beyond that of the basic smell options, for instance
350
364
  [Data Clump](docs/Data-Clump.md).
351
365
  All options that go beyond the [Basic Smell Options](docs/Basic-Smell-Options.md)
352
366
  are documented in the corresponding smell type /docs page (if you want to get a quick overview over all possible
353
- configurations you can also check out [the `default.reek` file in this repository](defaults.reek).
367
+ configurations you can also check out [the `defaults.reek.yml` file in this repository](docs/defaults.reek.yml).
354
368
 
355
369
  Note that you do not need a configuration file at all.
356
- If you're fine with all the [defaults](defaults.reek) we set you can skip this completely.
370
+ If you're fine with all the [defaults.reek.yml](docs/defaults.reek.yml) we set you can skip this completely.
371
+
372
+ Don't worry about introducing a mistake in your configuration file that might go unnoticed - Reek uses a
373
+ schema to validate your configuration against on start up and will faily loudly in case you
374
+ misspelled an option or used the wrong data type for a value like this:
375
+
376
+ ```
377
+ Error: We found some problems with your configuration file: [/detectors/DetectorWithTypo] key 'DetectorWithTypo:' is undefined.
378
+ ```
379
+
380
+ Reek takes one configuration file and one configuration file only with `.reek.yml` being the default name.
381
+
382
+ In case you have to have one or more configuration files in the directory (e.g. you're
383
+ toying around with different, mutually exclusive settings) you need to tell Reek
384
+ explicitly which file to use via `reek -c config.reek`.
357
385
 
358
386
  ### Source code comments
359
387
 
@@ -377,7 +405,7 @@ def smelly_method foo
377
405
  end
378
406
  ```
379
407
 
380
- This is an incredible powerful feature and further explained under [Smell Suppresion](docs/Smell-Suppression.md).
408
+ This is an incredibly powerful feature and further explained under [Smell Suppresion](docs/Smell-Suppression.md).
381
409
 
382
410
  ### Generating a 'todo' list
383
411
 
@@ -470,7 +498,9 @@ You can also run:
470
498
  bundle exec rake ci
471
499
  ```
472
500
 
473
- This will run everything the default task runs and also [Ataru](https://github.com/CodePadawans/ataru) and [Mutant](https://github.com/mbj/mutant). This is the task that we run on Travis as well and that determines if your pull request is green or red.
501
+ This will run everything the default task runs and also
502
+ [Ataru](https://github.com/CodePadawans/ataru). This is the task that we run on
503
+ Travis as well and that determines if your pull request is green or red.
474
504
 
475
505
  Another useful Rake task is the `console` task. This will throw you right into an environment where you can play around with Reeks modules and classes:
476
506
 
@@ -512,6 +542,20 @@ If you don't feel like getting your hands dirty with code there are still other
512
542
  * Open up an [issue](https://github.com/troessner/reek/issues) and report bugs
513
543
  * Suggest other improvements like additional smells for instance
514
544
 
545
+ ### Running Code Climate locally
546
+
547
+ If you run into Code Climate issues (e.g., go over code duplication
548
+ threshold) you might want to be able to run Code Climate against
549
+ the Reek codebase locally. To do this, you need to do the following:
550
+
551
+ * [install Docker CE](https://docs.docker.com/engine/installation/)
552
+ * [install Code Climate CLI](https://github.com/codeclimate/codeclimate#installation)
553
+ * `gem install codeclimate`
554
+ * `codeclimate engines:install`
555
+
556
+ Now you can run various Code Climate engines,
557
+ e.g., `codeclimate analyze -e duplication`
558
+
515
559
  ## Output formats
516
560
 
517
561
  Reek supports 5 output formats:
@@ -528,20 +572,24 @@ Making Reek "Rails"-friendly is fairly simple since we support directory specifi
528
572
  Just add this to your configuration file:
529
573
 
530
574
  ```Yaml
531
- "app/controllers":
532
- IrresponsibleModule:
533
- enabled: false
534
- NestedIterators:
535
- max_allowed_nesting: 2
536
- UnusedPrivateMethod:
537
- enabled: false
538
- InstanceVariableAssumption:
539
- enabled: false
540
- "app/helpers":
541
- IrresponsibleModule:
542
- enabled: false
543
- UtilityFunction:
544
- enabled: false
575
+ directories:
576
+ "app/controllers":
577
+ IrresponsibleModule:
578
+ enabled: false
579
+ NestedIterators:
580
+ max_allowed_nesting: 2
581
+ UnusedPrivateMethod:
582
+ enabled: false
583
+ InstanceVariableAssumption:
584
+ enabled: false
585
+ "app/helpers":
586
+ IrresponsibleModule:
587
+ enabled: false
588
+ UtilityFunction:
589
+ enabled: false
590
+ "app/mailers":
591
+ InstanceVariableAssumption:
592
+ enabled: false
545
593
  ```
546
594
 
547
595
  Be careful though, Reek does not merge your configuration entries, so if you already have a directory directive for "app/controllers" or "app/helpers" you need to update those directives instead of copying the above YAML sample into your configuration file.
@@ -554,6 +602,7 @@ Be careful though, Reek does not merge your configuration entries, so if you alr
554
602
  * [TextMate Bundle](https://github.com/peeyush1234/reek.tmbundle)
555
603
  * [Atom plugin](https://atom.io/packages/linter-reek)
556
604
  * [SublimeLinter plugin](https://packagecontrol.io/packages/SublimeLinter-contrib-reek)
605
+ * [VS Code plugin](https://github.com/rubyide/vscode-ruby)
557
606
  * [Emacs plugin](https://github.com/hanmoi-choi/reek-emacs)
558
607
 
559
608
  ### Projects that use or support us
data/Rakefile CHANGED
@@ -3,6 +3,19 @@ require 'rake/clean'
3
3
 
4
4
  Dir['tasks/**/*.rake'].each { |t| load t }
5
5
 
6
- task local_test_run: [:test, :rubocop, 'test:quality']
7
- task ci: [:test, :rubocop, 'test:quality', :ataru]
8
- task default: :local_test_run
6
+ task :ci do
7
+ [
8
+ 'test:spec',
9
+ 'configuration:update_default_configuration',
10
+ 'test:features',
11
+ :rubocop,
12
+ 'test:quality',
13
+ :ataru
14
+ ].each do |name|
15
+ puts "\n=== Running #{name}...\n"
16
+ Rake::Task[name].invoke
17
+ puts "\n=== Running #{name} -> Done\n"
18
+ end
19
+ end
20
+
21
+ task default: :ci
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
+
3
4
  #
4
5
  # Wrapper for the CodeClimate integration.
5
6
 
data/bin/reek CHANGED
@@ -1,10 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
+
3
4
  #
4
5
  # Reek examines Ruby source code for smells.
5
- # Visit https://wiki.github.com/troessner/reek for docs etc.
6
- #
7
- # Author: Kevin Rutherford
6
+ # Visit https://github.com/troessner/reek for docs etc.
8
7
  #
9
8
 
10
9
  require_relative '../lib/reek'
data/docs/API.md CHANGED
@@ -89,7 +89,7 @@ XMLReport
89
89
 
90
90
  ## Configuration
91
91
 
92
- Given you have the following configuration file called `config.reek` in your root directory:
92
+ Given you have the following configuration file called `.reek.yml` in your root directory:
93
93
 
94
94
  ```Yaml
95
95
  ---
@@ -106,7 +106,7 @@ You can now use either
106
106
  Reek::Configuration::AppConfiguration.from_path Pathname.new('config.reek')
107
107
  ```
108
108
 
109
- but you can also pass a hash with the contents of the `config.reek` YAML file
109
+ but you can also pass a hash with the contents of the `.reek.yml` YAML file
110
110
  to `Reek::Configuration::AppConfiguration.from_hash`.
111
111
 
112
112
  Given the example above you would load that as follows:
@@ -140,13 +140,6 @@ string -- 2 warnings:
140
140
  Dirty#call_me has the parameter name 'b' (UncommunicativeParameterName)
141
141
  ```
142
142
 
143
- Instead of the smell detector names you can also use the full detector class in
144
- your configuration hash, for example:
145
-
146
- ```ruby
147
- config_hash = { Reek::SmellDetectors::IrresponsibleModule => { 'enabled' => false } }
148
- ```
149
-
150
143
  Of course, directory specific configuration and excluded paths are supported as
151
144
  well:
152
145
 
@@ -7,14 +7,14 @@ Every smell detector in Reek offers at least the following configuration options
7
7
  | Option | Value | Effect |
8
8
  | ---------------|-------------|---------|
9
9
  | `enabled` | Boolean | Determines whether the smell detector is active. Defaults to `true` |
10
- | `exclude` | an array of strings or regular expressions | Ignores any context whose full description (see <strong>%c</strong> in [Command-Line Options](Command-Line-Options.md)) matches any element of this array. |
10
+ | `exclude` | an array of strings that will be converted into regular expressions | Ignores any context whose full description matches any element of this array. |
11
11
 
12
- The file `defaults.reek` (shipped with the Reek gem) lists any default
12
+ The file `docs/defaults.reek.yml` (shipped with the Reek gem) lists any default
13
13
  exclusions for each smell.
14
14
 
15
15
  ## Examples
16
16
 
17
- <u>An easy one:</u>
17
+ **An easy one:**
18
18
 
19
19
  To stop Reek reporting smells in any method called `write` you might create a configuration file containing this:
20
20
 
@@ -24,15 +24,9 @@ DuplicateMethodCall:
24
24
  - write
25
25
  ```
26
26
 
27
- Or a little more sophisticated using a Ruby regex like this:
27
+ Internally Reek will convert this to the Regexp /write/.
28
28
 
29
- ```yaml
30
- DuplicateMethodCall:
31
- exclude:
32
- - !ruby/regexp /write/
33
- ```
34
-
35
- <u>A more sophisticated one:</u>
29
+ **A more sophisticated one:**
36
30
 
37
31
  ```yaml
38
32
  FeatureEnvy:
@@ -43,3 +37,49 @@ FeatureEnvy:
43
37
  ```
44
38
 
45
39
  This would not report FeatureEnvy for the instance method `MyModel#do_things`, the whole module `MyHelper` and the `respond` instance method of `ApplicationController`
40
+
41
+ ## Advanced configuration
42
+
43
+ Sometimes just strings are not enough for configuration. E.g. consider this code sample:
44
+
45
+ ```Ruby
46
+ class Klass
47
+ def foo1; end
48
+ def foo1bar; end
49
+ end
50
+ ```
51
+ Both "Klass#foo1" and "Klass#foo1bar" will smell of UncommunicativeMethodName. Now let's assume
52
+ you are ok with "Klass#foo1" but not "Klass#foo1bar".
53
+ Just having this configuration
54
+
55
+ ```yaml
56
+ UncommunicativeMethodName:
57
+ exclude:
58
+ - "Klass#foo1"
59
+ ```
60
+
61
+ wouldn't work because now "Klass#foo1bar" wouldn't smell as well.
62
+
63
+ For this reason Reek has a special syntax that allows you to use regexes by using a forward slash at the beginning and the end of the string.
64
+ Everything within the forward slashes will be loaded as a regex.
65
+
66
+ A possible configuration that hat excludes "Klass#foo1" from this scan but not "Klass#foo1bar" could look like this:
67
+
68
+ ```yaml
69
+ UncommunicativeMethodName:
70
+ exclude:
71
+ - "/Klass#foo1$/"
72
+ ```
73
+
74
+ ## Reek 4
75
+
76
+ In Reek 4 you could also pass regexes to `exclude`, meaning this was perfectly valid as well:
77
+
78
+ ```yaml
79
+ DuplicateMethodCall:
80
+ exclude:
81
+ - !ruby/regexp /write/
82
+ ```
83
+
84
+ Support for this has been scrapped with Reek 5 to make the Reek configuration more yaml standard compliant.
85
+ You can still pass in regexes, you just have to wrap them into a string. Please see "Advanced configuration" above.
data/docs/Code-Smells.md CHANGED
@@ -23,7 +23,7 @@ Reek currently includes checks for the following smells:
23
23
  * [Utility Function](Utility-Function.md)
24
24
  * [Module Initialize](Module-Initialize.md)
25
25
  * [Nested Iterators](Nested-Iterators.md)
26
- * [Prima-Donna-Method](Prima-Donna-Method.md)
26
+ * [Missing Safe Method](Missing-Safe-Method.md), formerly known as Prima Donna Method
27
27
  * [Simulated Polymorphism](Simulated-Polymorphism.md), including
28
28
  * [Manual Dispatch](Manual-Dispatch.md)
29
29
  * [Nil Check](Nil-Check.md)
@@ -12,6 +12,16 @@ reek -h
12
12
 
13
13
  for details.
14
14
 
15
+ ## Telling Reek to use a specific configuration file
16
+
17
+ In case your configuration file is not in the standard location (that would be your project directory or
18
+ whatever directory you're running Reek from) you can specify a configuration file with the `-c` option
19
+ like this:
20
+
21
+ ```Bash
22
+ reek -c /somewhere/on/your/filesystem/reek_config.yml lib/
23
+ ```
24
+
15
25
  ## Telling Reek Which Code to Check
16
26
 
17
27
  Probably the most standard use case would be to check all Ruby files in the lib directory:
@@ -91,10 +101,10 @@ mess.rb -- 2 warnings:
91
101
  [2]:x has the name 'x' (UncommunicativeMethodName)
92
102
  ```
93
103
 
94
- ### Enable the ultra-verbose mode
104
+ ### Enable the verbose mode
95
105
 
96
- _reek_ has a ultra-verbose mode which you might find helpful as a beginner. "ultra-verbose" just means that behind each warning a helpful link will be displayed which leads directly to the corresponding _reek_ wiki page.
97
- This mode can be enabled via the "-U" or "--ultra-verbose" flag.
106
+ _reek_ has a verbose mode which you might find helpful as a beginner. "verbose" just means that behind each warning a helpful link will be displayed which leads directly to the corresponding _reek_ documentation page.
107
+ This mode can be enabled via the "-U" or "--documentation" flag.
98
108
 
99
109
  So for instance, if your test file would smell of _ClassVariable_, this is what the _reek_ output would look like:
100
110
 
@@ -103,7 +113,7 @@ reek -U test.rb
103
113
  ```
104
114
  ```
105
115
  test.rb -- 1 warning:
106
- [2]:Dummy declares the class variable @@class_variable (ClassVariable) [https://github.com/troessner/reek/wiki/Class-Variable]
116
+ [2]:Dummy declares the class variable @@class_variable (ClassVariable) [https://github.com/troessner/reek/blob/master/docs/Class-Variable.md]
107
117
  ```
108
118
 
109
119
  Note the link at the end.
@@ -42,7 +42,55 @@ The approach you take will depend on balancing other factors in your code.
42
42
 
43
43
  ## Current support in Reek
44
44
 
45
- Reek's Duplicate Method Call detector checks for repeated identical method calls within any one method definition. This is intended to complement the checks performed by tools such as [Flay](http://ruby.sadi.st/Flay.html) and [Simian](http://www.redhillconsulting.com.au/products/simian/).
45
+ Reek's Duplicate Method Call detector checks for repeated identical method calls within
46
+ any one method definition. This is intended to complement the checks performed by tools
47
+ such as [Flay](http://ruby.sadi.st/Flay.html) and [Simian](http://www.redhillconsulting.com.au/products/simian/).
48
+
49
+ ## Edge cases
50
+
51
+ Be aware that there are some edge cases like this code:
52
+
53
+ ```Ruby
54
+ class Foo
55
+ def bar(switch)
56
+ case switch
57
+ when :a
58
+ ->(arg) { arg.call_me(:maybe); do_something }
59
+ when :b
60
+ ->(arg) { arg.call_me(:maybe); do_something_else }
61
+ when :c
62
+ ->(arg) { arg.call_me(:maybe); do_something_different }
63
+ end
64
+ end
65
+ end
66
+ ```
67
+
68
+ Reek cannot reliably detect that each call's receiver is a different arg and will report:
69
+
70
+ ```
71
+ [5, 7, 9]:DuplicateMethodCall: Foo#bar calls 'arg.call_me(:maybe)' 3 times
72
+ ```
73
+
74
+ If you're running into this problem you can disable this smell detector for this method either via
75
+ configuration:
76
+
77
+ ```Yaml
78
+ ---
79
+ DuplicateMethodCall:
80
+ exclude:
81
+ - 'Foo#bar'
82
+ ```
83
+
84
+ or via source code comment:
85
+
86
+ ```Ruby
87
+ class Foo
88
+ # :reek:DuplicateMethodCall
89
+ def bar(switch)
90
+ # ....
91
+ end
92
+ end
93
+ ```
46
94
 
47
95
  ## Configuration
48
96
 
data/docs/Feature-Envy.md CHANGED
@@ -40,6 +40,50 @@ belongs to the Item class, not the Warehouse.
40
40
 
41
41
  _Feature Envy_ reports any method that refers to self less often than it refers to (ie. send messages to) some other object.
42
42
 
43
+ ## Edge cases
44
+
45
+ Be aware that there are some edge cases like this code:
46
+
47
+ ```Ruby
48
+ class Foo
49
+ def initialize
50
+ @map = {
51
+ a: ->(arg) { arg.css('table') },
52
+ b: ->(arg) { arg.css('div') },
53
+ c: ->(arg) { arg.css('span') }
54
+ }
55
+ end
56
+ end
57
+ ```
58
+
59
+ Reek cannot reliably detect that each call's receiver is a different arg and will report:
60
+
61
+ ```
62
+ [4, 5, 6]:FeatureEnvy: Foo#initialize refers to 'arg' more than self (maybe move it to another class?)
63
+ ```
64
+
65
+ If you're running into this problem you can disable this smell detector for this method either via
66
+ configuration:
67
+
68
+ ```Yaml
69
+ ---
70
+ FeatureEnvy:
71
+ exclude:
72
+ - 'Foo#bar'
73
+ ```
74
+
75
+ or via source code comment:
76
+
77
+ ```Ruby
78
+ class Foo
79
+ # :reek:FeatureEnvy
80
+ def initialize
81
+ @map = {
82
+ # ....
83
+ end
84
+ end
85
+ ```
86
+
43
87
  ## Differences to _Utility Function_
44
88
 
45
89
  _Feature Envy_ is only triggered if there are some references to self and _[Utility Function](Utility-Function.md)_ is triggered if there are no references to self.