reek 4.6.0 → 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 (294) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +17 -12
  3. data/.rubocop.yml +79 -26
  4. data/.simplecov +1 -0
  5. data/.travis.yml +3 -9
  6. data/.yardopts +1 -1
  7. data/CHANGELOG.md +76 -0
  8. data/CONTRIBUTING.md +1 -1
  9. data/Gemfile +5 -5
  10. data/README.md +138 -107
  11. data/Rakefile +16 -3
  12. data/bin/code_climate_reek +1 -0
  13. data/bin/reek +2 -3
  14. data/docs/API.md +2 -9
  15. data/docs/Basic-Smell-Options.md +51 -11
  16. data/docs/Code-Smells.md +1 -1
  17. data/docs/Command-Line-Options.md +14 -4
  18. data/docs/Duplicate-Method-Call.md +49 -1
  19. data/docs/Feature-Envy.md +44 -0
  20. data/docs/How-To-Write-New-Detectors.md +7 -7
  21. data/docs/Instance-Variable-Assumption.md +1 -1
  22. data/docs/{Prima-Donna-Method.md → Missing-Safe-Method.md} +11 -9
  23. data/docs/Rake-Task.md +1 -1
  24. data/docs/Reek-4-to-Reek-5-migration.md +193 -0
  25. data/docs/Reek-Driven-Development.md +1 -1
  26. data/docs/Uncommunicative-Method-Name.md +45 -6
  27. data/docs/Uncommunicative-Module-Name.md +49 -7
  28. data/docs/Uncommunicative-Parameter-Name.md +43 -5
  29. data/docs/Uncommunicative-Variable-Name.md +73 -2
  30. data/docs/Unused-Private-Method.md +3 -3
  31. data/docs/defaults.reek.yml +129 -0
  32. data/docs/yard_plugin.rb +1 -0
  33. data/features/command_line_interface/basic_usage.feature +2 -2
  34. data/features/command_line_interface/options.feature +46 -4
  35. data/features/command_line_interface/show_progress.feature +4 -4
  36. data/features/command_line_interface/smell_selection.feature +1 -1
  37. data/features/command_line_interface/smells_count.feature +6 -6
  38. data/features/command_line_interface/stdin.feature +31 -5
  39. data/features/configuration_files/accept_setting.feature +45 -28
  40. data/features/configuration_files/directory_specific_directives.feature +80 -75
  41. data/features/configuration_files/exclude_directives.feature +11 -10
  42. data/features/configuration_files/exclude_paths_directives.feature +4 -4
  43. data/features/configuration_files/masking_smells.feature +38 -9
  44. data/features/configuration_files/mix_accept_reject_setting.feature +31 -28
  45. data/features/configuration_files/reject_setting.feature +52 -41
  46. data/features/configuration_files/schema_validation.feature +59 -0
  47. data/features/configuration_files/unused_private_method.feature +18 -16
  48. data/features/configuration_loading.feature +53 -10
  49. data/features/configuration_via_source_comments/erroneous_source_comments.feature +3 -3
  50. data/features/configuration_via_source_comments/well_formed_source_comments.feature +2 -2
  51. data/features/locales.feature +32 -0
  52. data/features/rake_task/rake_task.feature +58 -18
  53. data/features/reports/codeclimate.feature +59 -0
  54. data/features/reports/json.feature +3 -3
  55. data/features/reports/reports.feature +34 -34
  56. data/features/reports/yaml.feature +3 -3
  57. data/features/rspec_matcher.feature +40 -0
  58. data/features/samples.feature +287 -287
  59. data/features/step_definitions/reek_steps.rb +14 -2
  60. data/features/step_definitions/sample_file_steps.rb +9 -4
  61. data/features/support/env.rb +2 -11
  62. data/features/todo_list.feature +26 -23
  63. data/lib/reek/ast/ast_node_class_map.rb +1 -0
  64. data/lib/reek/ast/builder.rb +16 -0
  65. data/lib/reek/ast/node.rb +50 -58
  66. data/lib/reek/ast/object_refs.rb +2 -1
  67. data/lib/reek/ast/reference_collector.rb +3 -4
  68. data/lib/reek/ast/sexp_extensions/arguments.rb +1 -0
  69. data/lib/reek/ast/sexp_extensions/attribute_assignments.rb +1 -0
  70. data/lib/reek/ast/sexp_extensions/begin.rb +17 -0
  71. data/lib/reek/ast/sexp_extensions/block.rb +1 -0
  72. data/lib/reek/ast/sexp_extensions/case.rb +2 -1
  73. data/lib/reek/ast/sexp_extensions/constant.rb +1 -0
  74. data/lib/reek/ast/sexp_extensions/if.rb +9 -1
  75. data/lib/reek/ast/sexp_extensions/lambda.rb +1 -0
  76. data/lib/reek/ast/sexp_extensions/literal.rb +1 -0
  77. data/lib/reek/ast/sexp_extensions/logical_operators.rb +2 -1
  78. data/lib/reek/ast/sexp_extensions/methods.rb +5 -6
  79. data/lib/reek/ast/sexp_extensions/module.rb +55 -8
  80. data/lib/reek/ast/sexp_extensions/nested_assignables.rb +1 -0
  81. data/lib/reek/ast/sexp_extensions/self.rb +1 -0
  82. data/lib/reek/ast/sexp_extensions/send.rb +1 -4
  83. data/lib/reek/ast/sexp_extensions/super.rb +1 -0
  84. data/lib/reek/ast/sexp_extensions/symbols.rb +1 -0
  85. data/lib/reek/ast/sexp_extensions/variables.rb +1 -0
  86. data/lib/reek/ast/sexp_extensions/when.rb +1 -0
  87. data/lib/reek/ast/sexp_extensions/yield.rb +1 -0
  88. data/lib/reek/ast/sexp_extensions.rb +2 -0
  89. data/lib/reek/cli/application.rb +5 -3
  90. data/lib/reek/cli/command/base_command.rb +1 -0
  91. data/lib/reek/cli/command/report_command.rb +2 -2
  92. data/lib/reek/cli/command/todo_list_command.rb +9 -8
  93. data/lib/reek/cli/options.rb +32 -16
  94. data/lib/reek/cli/silencer.rb +15 -3
  95. data/lib/reek/cli/status.rb +1 -0
  96. data/lib/reek/code_comment.rb +14 -16
  97. data/lib/reek/configuration/app_configuration.rb +34 -28
  98. data/lib/reek/configuration/configuration_converter.rb +110 -0
  99. data/lib/reek/configuration/configuration_file_finder.rb +17 -41
  100. data/lib/reek/configuration/configuration_validator.rb +13 -23
  101. data/lib/reek/configuration/default_directive.rb +18 -3
  102. data/lib/reek/configuration/directory_directives.rb +18 -11
  103. data/lib/reek/configuration/excluded_paths.rb +2 -1
  104. data/lib/reek/configuration/rake_task_converter.rb +29 -0
  105. data/lib/reek/configuration/schema.yml +210 -0
  106. data/lib/reek/configuration/schema_validator.rb +38 -0
  107. data/lib/reek/context/attribute_context.rb +4 -3
  108. data/lib/reek/context/class_context.rb +1 -0
  109. data/lib/reek/context/code_context.rb +49 -44
  110. data/lib/reek/context/ghost_context.rb +1 -2
  111. data/lib/reek/context/method_context.rb +26 -18
  112. data/lib/reek/context/module_context.rb +11 -11
  113. data/lib/reek/context/root_context.rb +1 -4
  114. data/lib/reek/context/send_context.rb +3 -2
  115. data/lib/reek/context/singleton_attribute_context.rb +1 -0
  116. data/lib/reek/context/singleton_method_context.rb +1 -0
  117. data/lib/reek/context/statement_counter.rb +1 -0
  118. data/lib/reek/context/visibility_tracker.rb +1 -0
  119. data/lib/reek/context_builder.rb +44 -44
  120. data/lib/reek/detector_repository.rb +12 -11
  121. data/lib/reek/documentation_link.rb +28 -0
  122. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +15 -13
  123. data/lib/reek/errors/bad_detector_in_comment_error.rb +13 -11
  124. data/lib/reek/errors/base_error.rb +3 -0
  125. data/lib/reek/errors/config_file_error.rb +11 -0
  126. data/lib/reek/errors/encoding_error.rb +43 -0
  127. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +14 -12
  128. data/lib/reek/errors/incomprehensible_source_error.rb +23 -24
  129. data/lib/reek/errors/syntax_error.rb +41 -0
  130. data/lib/reek/examiner.rb +24 -22
  131. data/lib/reek/logging_error_handler.rb +8 -5
  132. data/lib/reek/rake/task.rb +8 -5
  133. data/lib/reek/report/base_report.rb +9 -12
  134. data/lib/reek/report/code_climate/code_climate_configuration.rb +2 -1
  135. data/lib/reek/report/code_climate/code_climate_configuration.yml +6 -6
  136. data/lib/reek/report/code_climate/code_climate_fingerprint.rb +1 -0
  137. data/lib/reek/report/code_climate/code_climate_formatter.rb +1 -0
  138. data/lib/reek/report/code_climate/code_climate_report.rb +1 -0
  139. data/lib/reek/report/code_climate.rb +1 -0
  140. data/lib/reek/report/documentation_link_warning_formatter.rb +17 -0
  141. data/lib/reek/report/heading_formatter.rb +54 -0
  142. data/lib/reek/report/html_report.rb +1 -0
  143. data/lib/reek/report/json_report.rb +2 -1
  144. data/lib/reek/report/location_formatter.rb +40 -0
  145. data/lib/reek/report/progress_formatter.rb +79 -0
  146. data/lib/reek/report/simple_warning_formatter.rb +34 -0
  147. data/lib/reek/report/text_report.rb +2 -2
  148. data/lib/reek/report/xml_report.rb +4 -3
  149. data/lib/reek/report/yaml_report.rb +2 -1
  150. data/lib/reek/report.rb +16 -10
  151. data/lib/reek/smell_configuration.rb +3 -2
  152. data/lib/reek/smell_detectors/attribute.rb +6 -11
  153. data/lib/reek/smell_detectors/base_detector.rb +31 -26
  154. data/lib/reek/smell_detectors/boolean_parameter.rb +4 -5
  155. data/lib/reek/smell_detectors/class_variable.rb +6 -14
  156. data/lib/reek/smell_detectors/control_parameter.rb +19 -33
  157. data/lib/reek/smell_detectors/data_clump.rb +16 -9
  158. data/lib/reek/smell_detectors/duplicate_method_call.rb +24 -17
  159. data/lib/reek/smell_detectors/feature_envy.rb +10 -7
  160. data/lib/reek/smell_detectors/instance_variable_assumption.rb +15 -23
  161. data/lib/reek/smell_detectors/irresponsible_module.rb +6 -12
  162. data/lib/reek/smell_detectors/long_parameter_list.rb +11 -7
  163. data/lib/reek/smell_detectors/long_yield_list.rb +11 -7
  164. data/lib/reek/smell_detectors/manual_dispatch.rb +5 -5
  165. data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +21 -20
  166. data/lib/reek/smell_detectors/module_initialize.rb +4 -5
  167. data/lib/reek/smell_detectors/nested_iterators.rb +17 -24
  168. data/lib/reek/smell_detectors/nil_check.rb +9 -15
  169. data/lib/reek/smell_detectors/repeated_conditional.rb +14 -11
  170. data/lib/reek/smell_detectors/subclassed_from_core_class.rb +8 -8
  171. data/lib/reek/smell_detectors/too_many_constants.rb +11 -9
  172. data/lib/reek/smell_detectors/too_many_instance_variables.rb +11 -6
  173. data/lib/reek/smell_detectors/too_many_methods.rb +12 -7
  174. data/lib/reek/smell_detectors/too_many_statements.rb +11 -6
  175. data/lib/reek/smell_detectors/uncommunicative_method_name.rb +11 -11
  176. data/lib/reek/smell_detectors/uncommunicative_module_name.rb +15 -18
  177. data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +18 -22
  178. data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +27 -27
  179. data/lib/reek/smell_detectors/unused_parameters.rb +5 -6
  180. data/lib/reek/smell_detectors/unused_private_method.rb +14 -20
  181. data/lib/reek/smell_detectors/utility_function.rb +13 -16
  182. data/lib/reek/smell_detectors.rb +2 -1
  183. data/lib/reek/smell_warning.rb +16 -8
  184. data/lib/reek/source/source_code.rb +65 -46
  185. data/lib/reek/source/source_locator.rb +9 -8
  186. data/lib/reek/spec/should_reek.rb +3 -2
  187. data/lib/reek/spec/should_reek_of.rb +13 -26
  188. data/lib/reek/spec/should_reek_only_of.rb +5 -4
  189. data/lib/reek/spec/smell_matcher.rb +2 -1
  190. data/lib/reek/spec.rb +7 -6
  191. data/lib/reek/tree_dresser.rb +9 -8
  192. data/lib/reek/version.rb +2 -1
  193. data/lib/reek.rb +1 -0
  194. data/reek.gemspec +5 -6
  195. data/samples/checkstyle.xml +1 -1
  196. data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +29 -0
  197. data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +30 -0
  198. data/samples/configuration/full_configuration.reek +8 -4
  199. data/samples/configuration/full_mask.reek +5 -4
  200. data/samples/configuration/partial_mask.reek +3 -2
  201. data/samples/configuration/regular_configuration/.reek.yml +4 -0
  202. data/samples/paths.rb +5 -4
  203. data/samples/source_with_hidden_directories/.hidden/hidden.rb +1 -0
  204. data/samples/source_with_hidden_directories/not_hidden.rb +1 -0
  205. data/spec/factories/factories.rb +2 -13
  206. data/spec/reek/ast/node_spec.rb +103 -10
  207. data/spec/reek/ast/reference_collector_spec.rb +1 -1
  208. data/spec/reek/ast/sexp_extensions_spec.rb +15 -34
  209. data/spec/reek/cli/application_spec.rb +52 -42
  210. data/spec/reek/cli/command/todo_list_command_spec.rb +6 -4
  211. data/spec/reek/cli/silencer_spec.rb +28 -0
  212. data/spec/reek/code_comment_spec.rb +31 -38
  213. data/spec/reek/configuration/app_configuration_spec.rb +46 -33
  214. data/spec/reek/configuration/configuration_file_finder_spec.rb +133 -51
  215. data/spec/reek/configuration/default_directive_spec.rb +1 -1
  216. data/spec/reek/configuration/directory_directives_spec.rb +6 -7
  217. data/spec/reek/configuration/excluded_paths_spec.rb +6 -6
  218. data/spec/reek/configuration/rake_task_converter_spec.rb +33 -0
  219. data/spec/reek/configuration/schema_validator_spec.rb +165 -0
  220. data/spec/reek/context/code_context_spec.rb +70 -106
  221. data/spec/reek/context/ghost_context_spec.rb +9 -9
  222. data/spec/reek/context/method_context_spec.rb +2 -2
  223. data/spec/reek/context/module_context_spec.rb +3 -3
  224. data/spec/reek/context/root_context_spec.rb +1 -1
  225. data/spec/reek/context/statement_counter_spec.rb +1 -0
  226. data/spec/reek/context_builder_spec.rb +20 -0
  227. data/spec/reek/documentation_link_spec.rb +20 -0
  228. data/spec/reek/errors/base_error_spec.rb +13 -0
  229. data/spec/reek/examiner_spec.rb +137 -29
  230. data/spec/reek/rake/task_spec.rb +25 -2
  231. data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +82 -78
  232. data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +6 -6
  233. data/spec/reek/report/code_climate/code_climate_report_spec.rb +22 -22
  234. data/spec/reek/report/json_report_spec.rb +13 -46
  235. data/spec/reek/report/{formatter/location_formatter_spec.rb → location_formatter_spec.rb} +5 -5
  236. data/spec/reek/report/{formatter/progress_formatter_spec.rb → progress_formatter_spec.rb} +4 -4
  237. data/spec/reek/report/text_report_spec.rb +4 -4
  238. data/spec/reek/report/xml_report_spec.rb +3 -3
  239. data/spec/reek/report/yaml_report_spec.rb +17 -46
  240. data/spec/reek/report_spec.rb +3 -3
  241. data/spec/reek/smell_detectors/base_detector_spec.rb +4 -5
  242. data/spec/reek/smell_detectors/boolean_parameter_spec.rb +2 -2
  243. data/spec/reek/smell_detectors/class_variable_spec.rb +26 -32
  244. data/spec/reek/smell_detectors/control_parameter_spec.rb +34 -4
  245. data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +3 -3
  246. data/spec/reek/smell_detectors/feature_envy_spec.rb +47 -2
  247. data/spec/reek/smell_detectors/irresponsible_module_spec.rb +59 -21
  248. data/spec/reek/smell_detectors/{prima_donna_method_spec.rb → missing_safe_method_spec.rb} +10 -10
  249. data/spec/reek/smell_detectors/module_initialize_spec.rb +14 -0
  250. data/spec/reek/smell_detectors/nested_iterators_spec.rb +1 -1
  251. data/spec/reek/smell_detectors/too_many_constants_spec.rb +3 -3
  252. data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +1 -1
  253. data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +6 -6
  254. data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +6 -4
  255. data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +36 -15
  256. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +9 -9
  257. data/spec/reek/smell_detectors/unused_parameters_spec.rb +3 -3
  258. data/spec/reek/smell_detectors/unused_private_method_spec.rb +21 -10
  259. data/spec/reek/smell_detectors/utility_function_spec.rb +57 -5
  260. data/spec/reek/smell_warning_spec.rb +12 -8
  261. data/spec/reek/source/source_code_spec.rb +27 -38
  262. data/spec/reek/source/source_locator_spec.rb +42 -12
  263. data/spec/reek/spec/should_reek_of_spec.rb +25 -30
  264. data/spec/reek/spec/should_reek_only_of_spec.rb +2 -2
  265. data/spec/reek/spec/should_reek_spec.rb +8 -8
  266. data/spec/reek/spec/smell_matcher_spec.rb +23 -23
  267. data/spec/reek/tree_dresser_spec.rb +12 -17
  268. data/spec/spec_helper.rb +7 -17
  269. data/tasks/configuration.rake +8 -5
  270. metadata +77 -40
  271. data/defaults.reek +0 -128
  272. data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
  273. data/lib/reek/errors/parse_error.rb +0 -19
  274. data/lib/reek/report/formatter/heading_formatter.rb +0 -51
  275. data/lib/reek/report/formatter/location_formatter.rb +0 -41
  276. data/lib/reek/report/formatter/progress_formatter.rb +0 -80
  277. data/lib/reek/report/formatter/simple_warning_formatter.rb +0 -35
  278. data/lib/reek/report/formatter/wiki_link_warning_formatter.rb +0 -35
  279. data/lib/reek/report/formatter.rb +0 -32
  280. data/samples/configuration/non_public_modifiers_mask.reek +0 -3
  281. data/samples/smelly_with_inline_mask.rb +0 -8
  282. data/samples/smelly_with_modifiers.rb +0 -12
  283. data/samples/source_with_hidden_directories/.hidden/uncommunicative_method_name.rb +0 -5
  284. data/samples/source_with_non_ruby_files/uncommunicative_parameter_name.rb +0 -6
  285. /data/{samples/configuration/more_than_one_configuration_file/regular.reek → .reek.yml} +0 -0
  286. /data/samples/{clean.rb → clean_source/clean.rb} +0 -0
  287. /data/samples/{exceptions.reek → configuration/home/home.reek.yml} +0 -0
  288. /data/samples/configuration/{more_than_one_configuration_file/todo.reek → regular_configuration/empty_sub_directory/.gitignore} +0 -0
  289. /data/samples/{configuration/single_configuration_file/.reek → no_config_file/.keep} +0 -0
  290. /data/samples/{inline.rb → smelly_source/inline.rb} +0 -0
  291. /data/samples/{optparse.rb → smelly_source/optparse.rb} +0 -0
  292. /data/samples/{redcloth.rb → smelly_source/redcloth.rb} +0 -0
  293. /data/samples/{smelly.rb → smelly_source/smelly.rb} +0 -0
  294. /data/samples/{source_with_hidden_directories/uncommunicative_parameter_name.rb → source_with_non_ruby_files/ruby.rb} +0 -0
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.
@@ -27,20 +27,20 @@ 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
44
  lines: [], # lines on which the smell was detected
45
45
  message: "...", # the message that is printed on STDOUT
46
46
  # whatever you interpolate into the "message" should go into
@@ -61,7 +61,7 @@ end
61
61
 
62
62
  For your detector to be properly loaded you need to require it in `lib/reek/smell_detectors.rb` as well.
63
63
 
64
- ### defaults.reek
64
+ ### defaults.reek.yml
65
65
 
66
66
  After you ran
67
67
 
@@ -69,7 +69,7 @@ After you ran
69
69
  bundle exec rake
70
70
  ```
71
71
 
72
- for the first time with your shiny new detector in place the `defaults.reek`
72
+ for the first time with your shiny new detector in place the `docs/defaults.reek.yml`
73
73
  file should have been updated automatically. Make sure you don't forget to check
74
74
  in those changes as well.
75
75
 
@@ -61,7 +61,7 @@ end
61
61
  would report:
62
62
 
63
63
  ```Bash
64
- [1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar [https://github.com/troessner/reek/blob/master/docs/Instance-Variable-Assumption.md]
64
+ [1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar
65
65
  ```
66
66
 
67
67
  Note that this example would trigger this smell warning as well:
@@ -1,8 +1,8 @@
1
- # Prima Donna Method
1
+ # Missing Safe Method
2
2
 
3
3
  ## Introduction
4
4
 
5
- Candidate methods for the _Prima Donna Method_ smell are methods whose names
5
+ Candidate methods for the _Missing Safe Method_ smell are methods whose names
6
6
  end with an exclamation mark.
7
7
 
8
8
  An exclamation mark in method names means (the explanation below is taken from
@@ -13,14 +13,16 @@ An exclamation mark in method names means (the explanation below is taken from
13
13
  > equivalent method, with the same name minus the !. “Danger” is relative; the
14
14
  > ! doesn’t mean anything at all unless the method name it’s in corresponds to
15
15
  > a similar but bang-less method name.
16
- >
16
+ >
17
17
  > So, for example, gsub! is the dangerous version of gsub. exit! is the
18
18
  > dangerous version of exit. flatten! is the dangerous version of flatten. And
19
19
  > so forth.
20
20
 
21
- Such a method is called _Prima Donna Method_ if and only if her non-bang
21
+ Such a method is called _Missing Safe Method_ if and only if the non-bang
22
22
  version does not exist and this method is reported as a smell.
23
23
 
24
+ Missing Safe Method was formerly known as Prima Donna Method.
25
+
24
26
  ## Example
25
27
 
26
28
  Given
@@ -33,7 +35,7 @@ class C
33
35
  end
34
36
  ```
35
37
 
36
- Reek would report the _Prima Donna Method_ smell for `bar!`, but not for `foo!`.
38
+ Reek would report the _Missing Safe Method_ smell for `bar!`, but not for `foo!`.
37
39
 
38
40
  Reek reports this smell only in a class context, not in a module context in order to allow perfectly legit code like this:
39
41
 
@@ -55,12 +57,12 @@ class Daughter < Parent
55
57
  end
56
58
  ```
57
59
 
58
- In this example, Reek would not report the _Prima Donna Method_ smell for the
60
+ In this example, Reek would not report the _Missing Safe Method_ smell for the
59
61
  method `foo` of the `Dangerous` module.
60
62
 
61
63
  ## Configuration
62
64
 
63
- _Prima Donna Method_ offers the [Basic Smell Options](Basic-Smell-Options.md).
65
+ _Missing Safe Method_ offers the [Basic Smell Options](Basic-Smell-Options.md).
64
66
 
65
67
  ## Example configuration via source comment
66
68
 
@@ -77,12 +79,12 @@ This would report:
77
79
 
78
80
  >>
79
81
  ruby.rb -- 1 warning:
80
- [1]:PrimaDonnaMethod: Alfa has prima donna method 'bravo!'
82
+ [1]:MissingSafeMethod: Alfa has missing safe method 'bravo!'
81
83
 
82
84
  If you want to suppress this warning you can do this via source comment like this:
83
85
 
84
86
  ```Ruby
85
- # :reek:PrimaDonnaMethod: { exclude: [ bravo! ] }
87
+ # :reek:MissingSafeMethod { exclude: [ bravo! ] }
86
88
  class Alfa
87
89
  def bravo!
88
90
  end
data/docs/Rake-Task.md CHANGED
@@ -33,7 +33,7 @@ An more sophisticated rake task that would make use of all available configurati
33
33
  ```Ruby
34
34
  Reek::Rake::Task.new do |t|
35
35
  t.name = 'custom_rake' # Whatever name you want. Defaults to "reek".
36
- t.config_file = 'config/config.reek' # Defaults to nothing.
36
+ t.config_file = 'config/.reek.yml' # Defaults to nothing.
37
37
  t.source_files = 'vendor/**/*.rb' # Glob pattern to match source files. Defaults to lib/**/*.rb
38
38
  t.reek_opts = '-U' # Defaults to ''. You can pass all the options here in that are shown by "reek -h"
39
39
  t.fail_on_error = false # Defaults to true
@@ -0,0 +1,193 @@
1
+ ## Reek 4 to Reek 5 migration
2
+
3
+ ### Schema validation
4
+
5
+ Reek now uses a schema to validate your configuration against on start up and will faily loudly in
6
+ case you misspelled an option or used the wrong data type for a value like this:
7
+
8
+ ```
9
+ Error: We found some problems with your configuration file: [/detectors/DetectorWithTypo] key 'DetectorWithTypo:' is undefined.
10
+ ```
11
+
12
+ Obviously this might affect existing configuration files that until now contained an error nobody noticed.
13
+
14
+ ### Scoping detectors under `detectors`
15
+
16
+ In Reek 4 you could just configure your detectors on top level like this:
17
+
18
+ ```yaml
19
+ UncommunicativeMethodName:
20
+ accept:
21
+ - foobar
22
+ UnusedPrivateMethod:
23
+ exclude:
24
+ - app/controllers
25
+ ```
26
+
27
+ In Reek 5 you have to scope your detector configurations under the `detectors` key:
28
+
29
+ ```yaml
30
+ detectors:
31
+ UncommunicativeMethodName:
32
+ accept:
33
+ - foobar
34
+ UnusedPrivateMethod:
35
+ exclude:
36
+ - app/controllers
37
+ ```
38
+
39
+ ### Move directory directives under a special key
40
+
41
+ In Reek 4 you could apply directory specific directives like this:
42
+
43
+ ```Yaml
44
+ ---
45
+ "web_app/app/controllers":
46
+ NestedIterators:
47
+ enabled: false
48
+ "web_app/app/helpers":
49
+ UtilityFunction:
50
+ enabled: false
51
+ ```
52
+
53
+ which was nice and easy but also quite messy. With Reek 5 you'll have to scope this under a `directories`
54
+ key like this:
55
+
56
+ ```Yaml
57
+ ---
58
+ directories:
59
+ "web_app/app/controllers":
60
+ NestedIterators:
61
+ enabled: false
62
+ "web_app/app/helpers":
63
+ UtilityFunction:
64
+ enabled: false
65
+ ```
66
+
67
+ ### No more regular expressions in Reeks configuration
68
+
69
+ In Reek 4 you could pass regular expressions to the `accept` or `reject` settings of
70
+
71
+ * [Uncommunicative Method Name](Uncommunicative-Method-Name.md)
72
+ * [Uncommunicative Module Name](Uncommunicative-Module-Name.md)
73
+ * [Uncommunicative Parameter Name](Uncommunicative-Parameter-Name.md)
74
+ * [Uncommunicative Variable Name](Uncommunicative-Variable-Name.md)
75
+
76
+ and to the `exclude` settings which are part of our [Basic Smell Options](docs/Basic-Smell-Options.md).
77
+
78
+ This means that this configuration was perfectly valid:
79
+
80
+ ```yaml
81
+ detectors:
82
+ UncommunicativeMethodName:
83
+ accept:
84
+ - !ruby/regexp /foobar/
85
+ UnusedPrivateMethod:
86
+ exclude:
87
+ - !ruby/regexp /i am(.*)unused/
88
+ ```
89
+
90
+ Support for this has been scrapped with Reek 5 to make the Reek configuration more yaml standard compliant.
91
+ You can still pass in regexes, you just have to wrap them into a string using a forward slash at the
92
+ beginning and at the end of the string like this:
93
+
94
+ ```Yaml
95
+ ---
96
+ UncommunicativeMethodName:
97
+ accept:
98
+ - "/^foobar$/"
99
+ UnusedPrivateMethod:
100
+ exclude:
101
+ - "/i am(.*)unused/"
102
+ ```
103
+
104
+ Everything within the forward slashes will be loaded as a regex.
105
+
106
+ ### No more single item shortcuts for list items
107
+
108
+ You cant use a configuration option that is supposed to be a list with a single element like this anymore:
109
+
110
+ ```Yaml
111
+ ---
112
+ UncommunicativeMethodName:
113
+ accept: foobar
114
+ UnusedPrivateMethod:
115
+ exclude: omg
116
+ ```
117
+
118
+ You'll have to use a proper list here like this:
119
+
120
+ ```Yaml
121
+ ---
122
+ UncommunicativeMethodName:
123
+ accept:
124
+ - foobar
125
+ UnusedPrivateMethod:
126
+ exclude:
127
+ - omg
128
+ ```
129
+
130
+ ## Failing on syntax errors in source files
131
+
132
+ Previously Reek would just continue on syntax errors in source files which might have been convenient but
133
+ not necessarily fitting for a tool that's all about code quality. With Reek 5, Reek will fail hard on
134
+ invalid source files.
135
+
136
+ ### API changes
137
+
138
+ This is something that will only affect very advanced users. In case you have no idea what this might be about
139
+ you can just skip it or check out our [Developer API](docs/API.md).
140
+
141
+ #### Allow only detector names in configuration hash
142
+
143
+ In Reek 4 you could build your configuration like this:
144
+
145
+ ```ruby
146
+ config_hash = { Reek::SmellDetectors::IrresponsibleModule => { 'enabled' => false } }
147
+ ```
148
+
149
+ or like this:
150
+
151
+ ```ruby
152
+ config_hash = { 'IrresponsibleModule' => { 'enabled' => false } }
153
+ ```
154
+
155
+ Starting with Reek 5, the first way is not working anymore and the latter one is what you'll have to use.
156
+
157
+ #### Do not accept a class as parameter for reek_of
158
+
159
+ In the same vein as the change above you also can't use fully qualified detector names like this:
160
+
161
+ ```Ruby
162
+ reek_of(Reek::SmellDetectors::DuplicateMethodCall)
163
+ ```
164
+
165
+ The only supported way now is either as symbol or string:
166
+
167
+ ```Ruby
168
+ reek_of(:DuplicateMethodCall)
169
+ reek_of('DuplicateMethodCall')
170
+ ```
171
+
172
+ ## Smaller changes
173
+
174
+ * `PrimaDonnaMethod` has been given the better name `MissingSafeMethod`
175
+ * `wiki-links` flag has been renamed to `documentation` flag
176
+ * Reek assumes the default configuration file to be named ".reek.yml" and will ignore all other files. You can
177
+ still use any name you want though by passing in a name via the `-c` flag
178
+ * We have dropped the legacy code comment separator ":" at the end of a detector name. If you wanted to configure
179
+ a smell detector via comment before this release you had to use g like this:
180
+
181
+ ```
182
+ # :reek:UnusedPrivateMethod: { exclude: [ bravo ] }
183
+ ```
184
+
185
+ Mind the ":" at the end of "UnusedPrivateMethod". This syntax is disallowed with Reek 5 - you have to drop the ":"
186
+ at the end now like this:
187
+
188
+ ```
189
+ # :reek:UnusedPrivateMethod { exclude: [ bravo ] }
190
+ ```
191
+
192
+ * We have dropped support for Ruby 2.1 and 2.2 since they are officially not supported by the Ruby core team anymore
193
+
@@ -14,7 +14,7 @@ Reek::Rake::Task.new do |t|
14
14
  end
15
15
  ```
16
16
 
17
- Now the command `reek` will run Reek on your source code (and in this case, it fails if it finds any smells). For more detailed information about Reek's integration with Rake, see [Rake Task](Rake-Task.md) in this wiki.
17
+ Now the command `reek` will run Reek on your source code (and in this case, it fails if it finds any smells). For more detailed information about Reek's integration with Rake, see [Rake Task](Rake-Task.md).
18
18
 
19
19
  ## reek/spec
20
20
 
@@ -21,8 +21,8 @@ Reek's _Uncommunicative Method Name_ detector supports the
21
21
 
22
22
  | Option | Value | Effect |
23
23
  | ---------------|-------------|---------|
24
- | `reject` | array of regular expressions or strings | The set of patterns / names that Reek uses to check for bad names. Defaults to `[/^[a-z]$/, /[0-9]$/, /[A-Z]/]`. |
25
- | `accept` | array of regular expressions or strings | The set of patterns / names that Reek will accept (and not report) even if they match one of the `reject` expressions. |
24
+ | `reject` | array of strings | The set of names that Reek uses to check for bad names. Defaults to single-letter names, names ending with a number or names containing upper case letters. |
25
+ | `accept` | array of strings | The set of names that Reek will accept (and not report) even if they match one of the `reject` expressions. |
26
26
 
27
27
  An example configuration could look like this:
28
28
 
@@ -30,13 +30,15 @@ An example configuration could look like this:
30
30
  ---
31
31
  UncommunicativeMethodName:
32
32
  accept:
33
- - !ruby/regexp /x/
33
+ - x
34
34
  - meth1
35
35
  reject:
36
- - !ruby/regexp /helper/
36
+ - helper
37
37
  - foobar
38
38
  ```
39
39
 
40
+ Reek will convert whatever you give it as a string to the corresponding regex, so "foobar" from above will be converted to /foobar/ internally.
41
+
40
42
  Applying a configuration to a source file like this:
41
43
 
42
44
  ```Ruby
@@ -50,6 +52,43 @@ Reek would report:
50
52
 
51
53
  ```
52
54
  smelly.rb -- 2 warnings:
53
- [4]:UncommunicativeMethodName: awesome_helper has the name 'awesome_helper' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Method-Name.md]
54
- [3]:UncommunicativeMethodName: foobar has the name 'foobar' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Method-Name.md]
55
+ [4]:UncommunicativeMethodName: awesome_helper has the name 'awesome_helper'
56
+ [3]:UncommunicativeMethodName: foobar has the name 'foobar'
57
+ ```
58
+
59
+ ## Advanced configuration
60
+
61
+ Sometimes just strings are not enough for configuration. E.g. consider this code sample:
62
+
63
+ ```Ruby
64
+ class Klass
65
+ def foo; end
66
+ def foobar; end;
67
+ end
55
68
  ```
69
+
70
+ and now imagine that you want to reject the name "foo" but not "foobar". This wouldn't be possible with just using strings.
71
+ 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.
72
+ Everything within the forward slashes will be loaded as a regex.
73
+
74
+ A possible configuration that allows "foobar" but rejects "foo" could look like this:
75
+
76
+ ```Yaml
77
+ ---
78
+ UncommunicativeMethodName:
79
+ reject:
80
+ - "/^foo$/"
81
+ ```
82
+
83
+ ## Reek 4
84
+
85
+ In Reek 4 you could also pass regexes to `accept` or `reject`, meaning this was perfectly valid as well:
86
+
87
+ ```yaml
88
+ UncommunicativeMethodName:
89
+ accept:
90
+ - !ruby/regexp /foobar/
91
+ ```
92
+
93
+ Support for this has been scrapped with Reek 5 to make the Reek configuration more yaml standard compliant.
94
+ You can still pass in regexes, you just have to wrap them into a string. Please see "Advanced configuration" above.
@@ -19,8 +19,8 @@ Reek's _Uncommunicative Module Name_ detector supports the [Basic Smell Options]
19
19
 
20
20
  | Option | Value | Effect |
21
21
  | ---------------|-------------|---------|
22
- | `reject` | array of regular expressions or strings | The set of patterns or names that Reek uses to check for bad names. Defaults to `[/^.$/, /[0-9]$/]`. |
23
- | `accept` | array of regular expressions or strings | The set of patterns or names that Reek will accept (and not report) even if they match one of the `reject` expressions. Empty by default.|
22
+ | `reject` | array of strings | The set of names that Reek uses to check for bad names. Defaults to single-letter names and names ending with a number. |
23
+ | `accept` | array or strings | The set of names that Reek will accept (and not report) even if they match one of the `reject` expressions. Empty by default.|
24
24
 
25
25
  An example configuration could look like this:
26
26
 
@@ -28,17 +28,19 @@ An example configuration could look like this:
28
28
  ---
29
29
  UncommunicativeModuleName:
30
30
  accept:
31
- - !ruby/regexp /lassy/
32
- - M
31
+ - lassy
32
+ - Util
33
33
  reject:
34
- - !ruby/regexp /Helper/
34
+ - Helper
35
35
  ```
36
36
 
37
+ Reek will convert whatever you give it as a string to the corresponding regex, so "Helper" from above will be converted to /Helper/ internally.
38
+
37
39
  Applying a configuration to a source file like this:
38
40
 
39
41
  ```Ruby
40
42
  class Classy1; end # Should not be reported
41
- class M; end # Should not be reported
43
+ class Util; end # Should not be reported
42
44
  class BaseHelper; end # Should be reported
43
45
  ```
44
46
 
@@ -46,5 +48,45 @@ Reek would report:
46
48
 
47
49
  ```
48
50
  smelly.rb -- 1 warning:
49
- [3]:UncommunicativeModuleName: BaseHelper has the name 'BaseHelper' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Module-Name.md]
51
+ [3]:UncommunicativeModuleName: BaseHelper has the name 'BaseHelper'
52
+ ```
53
+
54
+ ## Advanced configuration
55
+
56
+ Sometimes just strings are not enough for configuration. E.g. consider this code sample:
57
+
58
+ ```Ruby
59
+ class Klassy
60
+ # ...
61
+ end
62
+
63
+ class KlassyModule
64
+ # ...
65
+ end
66
+ ```
67
+
68
+ and now imagine that you want to reject the name "Klassy" but not "KlassyModule". This wouldn't be possible with just using strings.
69
+ 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.
70
+ Everything within the forward slashes will be loaded as a regex.
71
+
72
+ A possible configuration that allows "KlassyModule" but rejects "Klassy" could look like this:
73
+
74
+ ```Yaml
75
+ ---
76
+ UncommunicativeModuleName:
77
+ reject:
78
+ - "/^Klassy$/"
50
79
  ```
80
+
81
+ ## Reek 4
82
+
83
+ In Reek 4 you could also pass regexes to `accept` or `reject`, meaning this was perfectly valid as well:
84
+
85
+ ```yaml
86
+ UncommunicativeModuleName:
87
+ accept:
88
+ - !ruby/regexp /foobar/
89
+ ```
90
+
91
+ Support for this has been scrapped with Reek 5 to make the Reek configuration more yaml standard compliant.
92
+ You can still pass in regexes, you just have to wrap them into a string. Please see "Advanced configuration" above.
@@ -20,8 +20,8 @@ Reek's _Uncommunicative Parameter Name_ detector supports the [Basic Smell Optio
20
20
 
21
21
  | Option | Value | Effect |
22
22
  | ---------|-------------|---------|
23
- | `reject` | array of regular expressions or strings | The set of patterns / names that Reek uses to check for bad names. Defaults to `[/^.$/, /[0-9]$/, /[A-Z]/, /^_/]. |
24
- | `accept` | array of regular expressions or strings | The set of patterns / names that Reek will accept (and not report) even if they match one of the `reject` expressions. |
23
+ | `reject` | array of strings | The set of names that Reek uses to check for bad names. Defaults to single-letter names, names containing an uppercase letter, names with a number at the end and '_'. |
24
+ | `accept` | array of strings | The set of names that Reek will accept (and not report) even if they match one of the `reject` expressions. |
25
25
 
26
26
 
27
27
  An example configuration could look like this:
@@ -30,12 +30,14 @@ An example configuration could look like this:
30
30
  ---
31
31
  UncommunicativeParameterName:
32
32
  accept:
33
- - !ruby/regexp /x/
33
+ - x
34
34
  - arg1
35
35
  reject:
36
- - !ruby/regexp /foobar/
36
+ - foobar
37
37
  ```
38
38
 
39
+ Reek will convert whatever you give it as a string to the corresponding regex, so "foobar" from above will be converted to /foobar/ internally.
40
+
39
41
  Applying a configuration to a source file like this:
40
42
 
41
43
  ```Ruby
@@ -48,5 +50,41 @@ Reek would report:
48
50
 
49
51
  ```
50
52
  smelly.rb -- 1 warning:
51
- [3]:UncommunicativeParameterName: omg has the parameter name 'foobar' [https://github.com/troessner/reek/blob/master/docs/Uncommunicative-Parameter-Name.md]
53
+ [3]:UncommunicativeParameterName: omg has the parameter name 'foobar'
54
+ ```
55
+
56
+ ## Advanced configuration
57
+
58
+ Sometimes just strings are not enough for configuration. E.g. consider this code sample:
59
+
60
+ ```Ruby
61
+ class Klass
62
+ def my_method(foo, foobar); end
63
+ end
52
64
  ```
65
+
66
+ and now imagine that you want to reject the name "foo" but not "foobar". This wouldn't be possible with just using strings.
67
+ 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.
68
+ Everything within the forward slashes will be loaded as a regex.
69
+
70
+ A possible configuration that allows "foobar" but rejects "foo" could look like this:
71
+
72
+ ```Yaml
73
+ ---
74
+ UncommunicativeParameterName:
75
+ reject:
76
+ - "/^foo$/"
77
+ ```
78
+
79
+ ## Reek 4
80
+
81
+ In Reek 4 you could also pass regexes to `accept` or `reject`, meaning this was perfectly valid as well:
82
+
83
+ ```yaml
84
+ UncommunicativeParameterName:
85
+ accept:
86
+ - !ruby/regexp /foobar/
87
+ ```
88
+
89
+ Support for this has been scrapped with Reek 5 to make the Reek configuration more yaml standard compliant.
90
+ You can still pass in regexes, you just have to wrap them into a string. Please see "Advanced configuration" above.