reek 6.0.2 → 6.5.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 (280) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +13 -0
  3. data/.github/workflows/ruby.yml +58 -0
  4. data/.gitignore +0 -1
  5. data/.rubocop.yml +7 -20
  6. data/.rubocop_todo.yml +6 -4
  7. data/.simplecov +2 -0
  8. data/CHANGELOG.md +114 -0
  9. data/CONTRIBUTING.md +10 -10
  10. data/Dockerfile +1 -1
  11. data/Gemfile +17 -24
  12. data/README.md +38 -40
  13. data/Rakefile +2 -0
  14. data/bin/code_climate_reek +56 -8
  15. data/docs/yard_plugin.rb +3 -1
  16. data/lib/reek/ast/ast_node_class_map.rb +1 -1
  17. data/lib/reek/ast/node.rb +16 -10
  18. data/lib/reek/ast/sexp_extensions/arguments.rb +20 -0
  19. data/lib/reek/ast/sexp_extensions/case.rb +1 -1
  20. data/lib/reek/ast/sexp_extensions/if.rb +1 -1
  21. data/lib/reek/ast/sexp_extensions/send.rb +22 -7
  22. data/lib/reek/cli/command/todo_list_command.rb +3 -3
  23. data/lib/reek/cli/options.rb +8 -8
  24. data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.rb +1 -1
  25. data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.yml +41 -41
  26. data/lib/reek/{report/code_climate → code_climate}/code_climate_fingerprint.rb +2 -2
  27. data/lib/reek/{report/code_climate → code_climate}/code_climate_formatter.rb +2 -4
  28. data/lib/reek/{report/code_climate → code_climate}/code_climate_report.rb +3 -3
  29. data/lib/reek/code_comment.rb +25 -20
  30. data/lib/reek/configuration/app_configuration.rb +5 -5
  31. data/lib/reek/configuration/configuration_converter.rb +1 -1
  32. data/lib/reek/configuration/configuration_file_finder.rb +5 -4
  33. data/lib/reek/configuration/default_directive.rb +1 -1
  34. data/lib/reek/configuration/directory_directives.rb +1 -1
  35. data/lib/reek/configuration/excluded_paths.rb +3 -2
  36. data/lib/reek/configuration/schema.rb +177 -0
  37. data/lib/reek/configuration/schema_validator.rb +12 -13
  38. data/lib/reek/context/attribute_context.rb +1 -1
  39. data/lib/reek/context/code_context.rb +3 -3
  40. data/lib/reek/context/method_context.rb +1 -1
  41. data/lib/reek/context/module_context.rb +4 -0
  42. data/lib/reek/context/refinement_context.rb +16 -0
  43. data/lib/reek/context/send_context.rb +7 -1
  44. data/lib/reek/context_builder.rb +17 -3
  45. data/lib/reek/documentation_link.rb +3 -5
  46. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +2 -2
  47. data/lib/reek/errors/bad_detector_in_comment_error.rb +2 -2
  48. data/lib/reek/errors/encoding_error.rb +1 -1
  49. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +2 -2
  50. data/lib/reek/errors/incomprehensible_source_error.rb +1 -1
  51. data/lib/reek/errors/legacy_comment_separator_error.rb +2 -2
  52. data/lib/reek/errors/syntax_error.rb +1 -1
  53. data/lib/reek/rake/task.rb +5 -5
  54. data/lib/reek/report/github_report.rb +55 -0
  55. data/lib/reek/report/text_report.rb +1 -1
  56. data/lib/reek/report.rb +7 -5
  57. data/lib/reek/smell_detectors/base_detector.rb +1 -1
  58. data/lib/reek/smell_detectors/class_variable.rb +2 -2
  59. data/lib/reek/smell_detectors/control_parameter_helpers/candidate.rb +6 -6
  60. data/lib/reek/smell_detectors/control_parameter_helpers/control_parameter_finder.rb +1 -1
  61. data/lib/reek/smell_detectors/data_clump.rb +1 -1
  62. data/lib/reek/smell_detectors/duplicate_method_call.rb +5 -5
  63. data/lib/reek/smell_detectors/instance_variable_assumption.rb +8 -8
  64. data/lib/reek/smell_detectors/nested_iterators.rb +4 -3
  65. data/lib/reek/smell_detectors/uncommunicative_module_name.rb +1 -1
  66. data/lib/reek/smell_detectors/unused_private_method.rb +3 -2
  67. data/lib/reek/smell_warning.rb +1 -1
  68. data/lib/reek/source/source_code.rb +11 -5
  69. data/lib/reek/source/source_locator.rb +1 -3
  70. data/lib/reek/spec/should_reek_of.rb +11 -9
  71. data/lib/reek/spec.rb +1 -1
  72. data/lib/reek/version.rb +2 -2
  73. data/reek.gemspec +33 -25
  74. metadata +41 -238
  75. data/.travis.yml +0 -40
  76. data/docs/API.md +0 -174
  77. data/docs/Attribute.md +0 -39
  78. data/docs/Basic-Smell-Options.md +0 -85
  79. data/docs/Boolean-Parameter.md +0 -54
  80. data/docs/Class-Variable.md +0 -40
  81. data/docs/Code-Smells.md +0 -39
  82. data/docs/Command-Line-Options.md +0 -119
  83. data/docs/Control-Couple.md +0 -26
  84. data/docs/Control-Parameter.md +0 -32
  85. data/docs/Data-Clump.md +0 -46
  86. data/docs/Duplicate-Method-Call.md +0 -264
  87. data/docs/Feature-Envy.md +0 -93
  88. data/docs/How-To-Write-New-Detectors.md +0 -132
  89. data/docs/How-reek-works-internally.md +0 -114
  90. data/docs/Instance-Variable-Assumption.md +0 -163
  91. data/docs/Irresponsible-Module.md +0 -47
  92. data/docs/Large-Class.md +0 -16
  93. data/docs/Long-Parameter-List.md +0 -39
  94. data/docs/Long-Yield-List.md +0 -37
  95. data/docs/Manual-Dispatch.md +0 -30
  96. data/docs/Missing-Safe-Method.md +0 -92
  97. data/docs/Module-Initialize.md +0 -62
  98. data/docs/Nested-Iterators.md +0 -59
  99. data/docs/Nil-Check.md +0 -47
  100. data/docs/RSpec-matchers.md +0 -129
  101. data/docs/Rake-Task.md +0 -66
  102. data/docs/Reek-4-to-Reek-5-migration.md +0 -188
  103. data/docs/Reek-Driven-Development.md +0 -46
  104. data/docs/Repeated-Conditional.md +0 -47
  105. data/docs/Simulated-Polymorphism.md +0 -16
  106. data/docs/Smell-Suppression.md +0 -96
  107. data/docs/Style-Guide.md +0 -19
  108. data/docs/Subclassed-From-Core-Class.md +0 -79
  109. data/docs/Too-Many-Constants.md +0 -37
  110. data/docs/Too-Many-Instance-Variables.md +0 -43
  111. data/docs/Too-Many-Methods.md +0 -56
  112. data/docs/Too-Many-Statements.md +0 -54
  113. data/docs/Uncommunicative-Method-Name.md +0 -94
  114. data/docs/Uncommunicative-Module-Name.md +0 -92
  115. data/docs/Uncommunicative-Name.md +0 -18
  116. data/docs/Uncommunicative-Parameter-Name.md +0 -90
  117. data/docs/Uncommunicative-Variable-Name.md +0 -96
  118. data/docs/Unused-Parameters.md +0 -28
  119. data/docs/Unused-Private-Method.md +0 -101
  120. data/docs/Utility-Function.md +0 -56
  121. data/docs/Versioning-Policy.md +0 -7
  122. data/docs/YAML-Reports.md +0 -93
  123. data/docs/defaults.reek.yml +0 -129
  124. data/docs/templates/default/docstring/html/public_api_marker.erb +0 -3
  125. data/docs/templates/default/docstring/setup.rb +0 -37
  126. data/docs/templates/default/fulldoc/html/css/common.css +0 -1
  127. data/features/command_line_interface/basic_usage.feature +0 -15
  128. data/features/command_line_interface/options.feature +0 -123
  129. data/features/command_line_interface/show_progress.feature +0 -33
  130. data/features/command_line_interface/smell_selection.feature +0 -15
  131. data/features/command_line_interface/smells_count.feature +0 -38
  132. data/features/command_line_interface/stdin.feature +0 -65
  133. data/features/configuration_files/accept_setting.feature +0 -87
  134. data/features/configuration_files/directory_specific_directives.feature +0 -274
  135. data/features/configuration_files/exclude_directives.feature +0 -35
  136. data/features/configuration_files/exclude_paths_directives.feature +0 -42
  137. data/features/configuration_files/masking_smells.feature +0 -94
  138. data/features/configuration_files/mix_accept_reject_setting.feature +0 -84
  139. data/features/configuration_files/reject_setting.feature +0 -89
  140. data/features/configuration_files/schema_validation.feature +0 -59
  141. data/features/configuration_files/show_configuration_file.feature +0 -44
  142. data/features/configuration_files/unused_private_method.feature +0 -68
  143. data/features/configuration_loading.feature +0 -91
  144. data/features/configuration_via_source_comments/erroneous_source_comments.feature +0 -68
  145. data/features/configuration_via_source_comments/well_formed_source_comments.feature +0 -116
  146. data/features/locales.feature +0 -32
  147. data/features/programmatic_access.feature +0 -41
  148. data/features/rake_task/rake_task.feature +0 -138
  149. data/features/reports/codeclimate.feature +0 -59
  150. data/features/reports/json.feature +0 -59
  151. data/features/reports/reports.feature +0 -219
  152. data/features/reports/yaml.feature +0 -52
  153. data/features/rspec_matcher.feature +0 -41
  154. data/features/samples.feature +0 -305
  155. data/features/step_definitions/.rubocop.yml +0 -5
  156. data/features/step_definitions/reek_steps.rb +0 -102
  157. data/features/step_definitions/sample_file_steps.rb +0 -63
  158. data/features/support/env.rb +0 -33
  159. data/features/todo_list.feature +0 -108
  160. data/lib/reek/configuration/schema.yml +0 -210
  161. data/samples/checkstyle.xml +0 -7
  162. data/samples/clean_source/clean.rb +0 -6
  163. data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +0 -29
  164. data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +0 -30
  165. data/samples/configuration/corrupt.reek +0 -1
  166. data/samples/configuration/empty.reek +0 -0
  167. data/samples/configuration/full_configuration.reek +0 -13
  168. data/samples/configuration/full_mask.reek +0 -6
  169. data/samples/configuration/home/home.reek.yml +0 -4
  170. data/samples/configuration/partial_mask.reek +0 -4
  171. data/samples/configuration/regular_configuration/.reek.yml +0 -4
  172. data/samples/configuration/regular_configuration/empty_sub_directory/.gitignore +0 -0
  173. data/samples/configuration/with_excluded_paths.reek +0 -5
  174. data/samples/no_config_file/.keep +0 -0
  175. data/samples/paths.rb +0 -5
  176. data/samples/smelly_source/inline.rb +0 -704
  177. data/samples/smelly_source/optparse.rb +0 -1788
  178. data/samples/smelly_source/redcloth.rb +0 -1130
  179. data/samples/smelly_source/ruby.rb +0 -368
  180. data/samples/smelly_source/smelly.rb +0 -7
  181. data/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +0 -5
  182. data/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +0 -2
  183. data/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +0 -6
  184. data/samples/source_with_exclude_paths/nested/uncommunicative_variable_name.rb +0 -6
  185. data/samples/source_with_hidden_directories/.hidden/hidden.rb +0 -1
  186. data/samples/source_with_hidden_directories/not_hidden.rb +0 -1
  187. data/samples/source_with_non_ruby_files/gibberish +0 -1
  188. data/samples/source_with_non_ruby_files/python_source.py +0 -1
  189. data/samples/source_with_non_ruby_files/ruby.rb +0 -6
  190. data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +0 -15
  191. data/spec/quality/documentation_spec.rb +0 -41
  192. data/spec/quality/reek_source_spec.rb +0 -11
  193. data/spec/reek/ast/node_spec.rb +0 -211
  194. data/spec/reek/ast/object_refs_spec.rb +0 -83
  195. data/spec/reek/ast/reference_collector_spec.rb +0 -47
  196. data/spec/reek/ast/sexp_extensions_spec.rb +0 -498
  197. data/spec/reek/cli/application_spec.rb +0 -168
  198. data/spec/reek/cli/command/report_command_spec.rb +0 -44
  199. data/spec/reek/cli/command/todo_list_command_spec.rb +0 -86
  200. data/spec/reek/cli/options_spec.rb +0 -51
  201. data/spec/reek/cli/silencer_spec.rb +0 -28
  202. data/spec/reek/code_comment_spec.rb +0 -184
  203. data/spec/reek/configuration/app_configuration_spec.rb +0 -195
  204. data/spec/reek/configuration/configuration_file_finder_spec.rb +0 -230
  205. data/spec/reek/configuration/default_directive_spec.rb +0 -13
  206. data/spec/reek/configuration/directory_directives_spec.rb +0 -122
  207. data/spec/reek/configuration/excluded_paths_spec.rb +0 -16
  208. data/spec/reek/configuration/rake_task_converter_spec.rb +0 -33
  209. data/spec/reek/configuration/schema_validator_spec.rb +0 -165
  210. data/spec/reek/context/code_context_spec.rb +0 -192
  211. data/spec/reek/context/ghost_context_spec.rb +0 -60
  212. data/spec/reek/context/method_context_spec.rb +0 -72
  213. data/spec/reek/context/module_context_spec.rb +0 -55
  214. data/spec/reek/context/root_context_spec.rb +0 -12
  215. data/spec/reek/context/statement_counter_spec.rb +0 -24
  216. data/spec/reek/context_builder_spec.rb +0 -457
  217. data/spec/reek/detector_repository_spec.rb +0 -22
  218. data/spec/reek/documentation_link_spec.rb +0 -20
  219. data/spec/reek/errors/base_error_spec.rb +0 -13
  220. data/spec/reek/examiner_spec.rb +0 -309
  221. data/spec/reek/logging_error_handler_spec.rb +0 -24
  222. data/spec/reek/rake/task_spec.rb +0 -56
  223. data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +0 -22
  224. data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +0 -126
  225. data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +0 -51
  226. data/spec/reek/report/code_climate/code_climate_report_spec.rb +0 -56
  227. data/spec/reek/report/html_report_spec.rb +0 -19
  228. data/spec/reek/report/json_report_spec.rb +0 -58
  229. data/spec/reek/report/location_formatter_spec.rb +0 -32
  230. data/spec/reek/report/progress_formatter_spec.rb +0 -68
  231. data/spec/reek/report/text_report_spec.rb +0 -89
  232. data/spec/reek/report/xml_report_spec.rb +0 -24
  233. data/spec/reek/report/yaml_report_spec.rb +0 -55
  234. data/spec/reek/report_spec.rb +0 -28
  235. data/spec/reek/smell_configuration_spec.rb +0 -56
  236. data/spec/reek/smell_detectors/attribute_spec.rb +0 -197
  237. data/spec/reek/smell_detectors/base_detector_spec.rb +0 -50
  238. data/spec/reek/smell_detectors/boolean_parameter_spec.rb +0 -93
  239. data/spec/reek/smell_detectors/class_variable_spec.rb +0 -106
  240. data/spec/reek/smell_detectors/control_parameter_spec.rb +0 -300
  241. data/spec/reek/smell_detectors/data_clump_spec.rb +0 -134
  242. data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +0 -211
  243. data/spec/reek/smell_detectors/feature_envy_spec.rb +0 -295
  244. data/spec/reek/smell_detectors/instance_variable_assumption_spec.rb +0 -96
  245. data/spec/reek/smell_detectors/irresponsible_module_spec.rb +0 -226
  246. data/spec/reek/smell_detectors/long_parameter_list_spec.rb +0 -61
  247. data/spec/reek/smell_detectors/long_yield_list_spec.rb +0 -49
  248. data/spec/reek/smell_detectors/manual_dispatch_spec.rb +0 -75
  249. data/spec/reek/smell_detectors/missing_safe_method_spec.rb +0 -68
  250. data/spec/reek/smell_detectors/module_initialize_spec.rb +0 -77
  251. data/spec/reek/smell_detectors/nested_iterators_spec.rb +0 -333
  252. data/spec/reek/smell_detectors/nil_check_spec.rb +0 -100
  253. data/spec/reek/smell_detectors/repeated_conditional_spec.rb +0 -100
  254. data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -77
  255. data/spec/reek/smell_detectors/too_many_constants_spec.rb +0 -144
  256. data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +0 -132
  257. data/spec/reek/smell_detectors/too_many_methods_spec.rb +0 -54
  258. data/spec/reek/smell_detectors/too_many_statements_spec.rb +0 -90
  259. data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +0 -78
  260. data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +0 -78
  261. data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +0 -147
  262. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +0 -201
  263. data/spec/reek/smell_detectors/unused_parameters_spec.rb +0 -114
  264. data/spec/reek/smell_detectors/unused_private_method_spec.rb +0 -205
  265. data/spec/reek/smell_detectors/utility_function_spec.rb +0 -293
  266. data/spec/reek/smell_warning_spec.rb +0 -137
  267. data/spec/reek/source/source_code_spec.rb +0 -79
  268. data/spec/reek/source/source_locator_spec.rb +0 -166
  269. data/spec/reek/spec/should_reek_of_spec.rb +0 -153
  270. data/spec/reek/spec/should_reek_only_of_spec.rb +0 -91
  271. data/spec/reek/spec/should_reek_spec.rb +0 -52
  272. data/spec/reek/spec/smell_matcher_spec.rb +0 -87
  273. data/spec/reek/tree_dresser_spec.rb +0 -46
  274. data/spec/spec_helper.rb +0 -110
  275. data/tasks/configuration.rake +0 -18
  276. data/tasks/console.rake +0 -5
  277. data/tasks/reek.rake +0 -6
  278. data/tasks/rubocop.rake +0 -11
  279. data/tasks/test.rake +0 -32
  280. /data/lib/reek/{report/code_climate.rb → code_climate.rb} +0 -0
data/README.md CHANGED
@@ -35,15 +35,15 @@
35
35
 
36
36
  ## Overview
37
37
 
38
- * [![Build Status](https://secure.travis-ci.org/troessner/reek.svg?branch=master)](https://travis-ci.org/troessner/reek?branch=master)
38
+ * ![Downloads](https://img.shields.io/badge/Downloads-%3E24_million-blue)
39
+ * ![Build Status](https://github.com/troessner/reek/actions/workflows/ruby.yml/badge.svg?branch=master)
39
40
  * [![Gem Version](https://badge.fury.io/rb/reek.svg)](https://badge.fury.io/rb/reek)
40
- * ![](http://img.shields.io/github/tag/troessner/reek.svg)
41
- * ![](http://img.shields.io/badge/license-MIT-brightgreen.svg)
41
+ * ![Git Tag](http://img.shields.io/github/tag/troessner/reek.svg)
42
+ * ![Licence](http://img.shields.io/badge/license-MIT-brightgreen.svg)
42
43
  * [![Inline docs](https://inch-ci.org/github/troessner/reek.png)](https://inch-ci.org/github/troessner/reek)
43
44
  * [![Code Climate](https://codeclimate.com/github/troessner/reek/badges/gpa.svg)](https://codeclimate.com/github/troessner/reek)
44
45
  * [![codebeat](https://codebeat.co/badges/42fed4ff-3e55-4aed-8ecc-409b4aa539b3)](https://codebeat.co/projects/github-com-troessner-reek)
45
- * ![](http://ruby-gem-downloads-badge.herokuapp.com/reek?type=total)
46
- * ![](http://ruby-gem-downloads-badge.herokuapp.com/reek?label=downloads-current-version)
46
+
47
47
 
48
48
  ## Quickstart
49
49
 
@@ -56,13 +56,13 @@ or [that one](https://troessner.svbtle.com/the-latest-and-greatest-additions-to-
56
56
 
57
57
  Install it via rubygems:
58
58
 
59
- ```Bash
59
+ ```bash
60
60
  gem install reek
61
61
  ```
62
62
 
63
63
  and run it like this:
64
64
 
65
- ```Bash
65
+ ```bash
66
66
  reek [options] [dir_or_source_file]*
67
67
  ```
68
68
 
@@ -70,7 +70,7 @@ reek [options] [dir_or_source_file]*
70
70
 
71
71
  Imagine a source file `demo.rb` containing:
72
72
 
73
- ```Ruby
73
+ ```ruby
74
74
  # Smelly class
75
75
  class Smelly
76
76
  # This will reek of UncommunicativeMethodName
@@ -94,7 +94,7 @@ demo.rb -- 2 warnings:
94
94
 
95
95
  ## Supported Ruby versions
96
96
 
97
- Reek is officially supported for CRuby 2.4 to 2.7 and for JRuby 9.2.
97
+ Reek is officially supported for CRuby 3.0 through 3.3 and for JRuby 9.4.
98
98
  Other Ruby implementations (like Rubinius) are not officially supported but
99
99
  should work as well.
100
100
 
@@ -111,7 +111,7 @@ language and business logic.
111
111
  That said, an example might help you get going. Have a look at this sample of a
112
112
  Ruby on Rails model (be aware that this is truncated, not working code):
113
113
 
114
- ```Ruby
114
+ ```ruby
115
115
  class ShoppingCart < ActiveRecord::Base
116
116
  has_many :items
117
117
 
@@ -140,7 +140,7 @@ would report:
140
140
  Fixing this is pretty straightforward. Put the gross price calculation for a single item
141
141
  where it belongs, which would be the `Item` class:
142
142
 
143
- ```Ruby
143
+ ```ruby
144
144
  class ShoppingCart < ActiveRecord::Base
145
145
  has_many :items
146
146
 
@@ -165,7 +165,7 @@ those first when you have a warning that you don't know how to deal with.
165
165
 
166
166
  There are multiple ways you can have Reek work on sources, the most common one just being
167
167
 
168
- ```Bash
168
+ ```bash
169
169
  reek lib/
170
170
  ```
171
171
 
@@ -173,25 +173,25 @@ If you don't pass any source arguments to Reek it just takes the current working
173
173
 
174
174
  So
175
175
 
176
- ```Bash
176
+ ```bash
177
177
  reek
178
178
  ```
179
179
 
180
180
  is the exact same thing as being explicit:
181
181
 
182
- ```Bash
182
+ ```bash
183
183
  reek .
184
184
  ```
185
185
 
186
186
  Additionally you can pipe code to Reek like this:
187
187
 
188
- ```Bash
188
+ ```bash
189
189
  echo "class C; def m; end; end" | reek
190
190
  ```
191
191
 
192
192
  This would print out:
193
193
 
194
- ```Bash
194
+ ```bash
195
195
  $stdin -- 3 warnings:
196
196
  [1]:C has no descriptive comment (IrresponsibleModule)
197
197
  [1]:C has the name 'C' (UncommunicativeModuleName)
@@ -219,7 +219,7 @@ for up to date details of exactly what Reek will check in your code.
219
219
  because it is [kind of controversial](https://github.com/troessner/reek/issues/844) which means
220
220
  you have to explicitly activate it in your configuration via
221
221
 
222
- ```Yaml
222
+ ```yaml
223
223
  UnusedPrivateMethod:
224
224
  enabled: true
225
225
  ```
@@ -228,7 +228,7 @@ UnusedPrivateMethod:
228
228
  as well that can turn out to be really unforgiving.
229
229
  As a consequence, we made it possible to disable it for non-public methods like this:
230
230
 
231
- ```Yaml
231
+ ```yaml
232
232
  ---
233
233
  UtilityFunction:
234
234
  public_methods_only: true
@@ -240,7 +240,7 @@ UtilityFunction:
240
240
 
241
241
  For a basic overview, run
242
242
 
243
- ```Ruby
243
+ ```ruby
244
244
  reek --help
245
245
  ```
246
246
 
@@ -328,7 +328,7 @@ directories:
328
328
  exclude_paths:
329
329
  - lib/legacy
330
330
  - lib/rake/legacy_tasks
331
- - lib/smelly.rb
331
+ - lib/smelly.rb
332
332
  ```
333
333
 
334
334
  As you see above, Reek's configuration consists of 3 different sections denoted by 3 different keys:
@@ -395,7 +395,7 @@ In case you need to suppress a smell warning and you can't or don't want to
395
395
  use configuration files for whatever reasons you can also use special
396
396
  source code comments like this:
397
397
 
398
- ```Ruby
398
+ ```ruby
399
399
  # This method smells of :reek:NestedIterators
400
400
  def smelly_method foo
401
401
  foo.each {|bar| bar.each {|baz| baz.qux}}
@@ -404,14 +404,14 @@ end
404
404
 
405
405
  You can even pass in smell specific configuration settings:
406
406
 
407
- ```Ruby
407
+ ```ruby
408
408
  # :reek:NestedIterators { max_allowed_nesting: 2 }
409
409
  def smelly_method foo
410
410
  foo.each {|bar| bar.each {|baz| baz.qux}}
411
411
  end
412
412
  ```
413
413
 
414
- This is an incredibly powerful feature and further explained under [Smell Suppresion](docs/Smell-Suppression.md).
414
+ This is an incredibly powerful feature and further explained under [Smell Suppression](docs/Smell-Suppression.md).
415
415
 
416
416
  #### Debugging trouble with the configuration
417
417
 
@@ -432,7 +432,7 @@ codebase this might not be an option.
432
432
  Fortunately Reek provides a 'todo' flag which you can use to generate a configuration that will
433
433
  suppress all smell warnings for the current codebase:
434
434
 
435
- ```Bash
435
+ ```bash
436
436
  reek --todo lib/
437
437
  ```
438
438
 
@@ -447,7 +447,7 @@ If for whatever reasons you decide to put '.reek.yml' somewhere else where
447
447
  Reek won't pick it up automatically you need to tell Reek explicitly to do so
448
448
  via:
449
449
 
450
- ```Bash
450
+ ```bash
451
451
  reek -c whatever/.reek.yml lib/
452
452
  ```
453
453
 
@@ -461,7 +461,7 @@ and instead abort execution. It also will not take **any** other configuration f
461
461
 
462
462
  This means that when you run
463
463
 
464
- ```Bash
464
+ ```bash
465
465
  reek -c other_configuration.reek --todo lib/
466
466
  ```
467
467
 
@@ -474,7 +474,7 @@ but keep in mind that this is not the intended use case of this feature.
474
474
 
475
475
  Besides the obvious
476
476
 
477
- ```Bash
477
+ ```bash
478
478
  reek [options] [dir_or_source_file]*
479
479
  ```
480
480
 
@@ -514,18 +514,15 @@ Another useful Rake task is the `console` task. This will throw you right into a
514
514
  ```
515
515
  bundle exec rake console
516
516
 
517
- [3] pry(main)> require_relative 'lib/reek/examiner'
518
- => true
519
- [4] pry(main)> Reek::Examiner
517
+ irb(main):001> Reek::Examiner
520
518
  => Reek::Examiner
521
519
  ```
522
520
 
523
- You can also use Pry while running the tests by adding the following at the
521
+ You can also use IRB while running the tests by adding the following at the
524
522
  point where you want to start debugging:
525
523
 
526
- ```Ruby
527
- require 'pry'
528
- binding.pry
524
+ ```ruby
525
+ binding.irb
529
526
  ```
530
527
 
531
528
  Have a look at our [Developer API](docs/API.md) for more inspiration.
@@ -556,20 +553,21 @@ e.g., `codeclimate analyze -e duplication`
556
553
 
557
554
  ## Output formats
558
555
 
559
- Reek supports 5 output formats:
556
+ Reek supports 6 output formats:
560
557
 
561
558
  * plain text (default)
562
- * HTML (`--format html`)
563
- * YAML (`--format yaml`, see also [YAML Reports](docs/YAML-Reports.md))
564
- * JSON (`--format json`)
565
- * XML (`--format xml`)
559
+ * HTML (`--format html`)
560
+ * YAML (`--format yaml`, see also [YAML Reports](docs/YAML-Reports.md))
561
+ * JSON (`--format json`)
562
+ * XML (`--format xml`)
563
+ * GitHub (`--format github`)
566
564
 
567
565
  ## Working with Rails
568
566
 
569
567
  Making Reek "Rails"-friendly is fairly simple since we support directory specific configurations (`directory directives` in Reek talk).
570
568
  Just add this to your configuration file:
571
569
 
572
- ```Yaml
570
+ ```yaml
573
571
  directories:
574
572
  "app/controllers":
575
573
  IrresponsibleModule:
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler/gem_tasks'
2
4
  require 'rake/clean'
3
5
 
@@ -6,7 +6,8 @@
6
6
 
7
7
  require_relative '../lib/reek'
8
8
  require_relative '../lib/reek/cli/application'
9
- require_relative '../lib/reek/report/code_climate'
9
+ require_relative '../lib/reek/code_climate'
10
+ Reek::CLI::Silencer.silently { require 'parser/current' }
10
11
 
11
12
  # Map input coming from CodeClimate to Reek.
12
13
  class CodeClimateToReek
@@ -14,15 +15,16 @@ class CodeClimateToReek
14
15
  # we have to exit with a zero for both failure and success.
15
16
  ENGINE_CONFIGURATION = [
16
17
  '--failure-exit-code', '0',
17
- '--success-exit-code', '0',
18
- '.'
18
+ '--success-exit-code', '0'
19
19
  ].freeze
20
+ CUSTOM_CONFIG_KEY = 'config'
21
+ CUSTOM_CONFIG_TARGET_RUBY_VERSION_KEY = 'target_ruby_version'
20
22
 
21
23
  attr_reader :configuration_file_path, :include_paths_key, :include_paths_default
22
24
 
23
25
  def initialize(configuration_file_path: '/config.json',
24
26
  include_paths_key: 'include_paths',
25
- include_paths_default: [])
27
+ include_paths_default: ['.'])
26
28
  @configuration_file_path = configuration_file_path
27
29
  @include_paths_key = include_paths_key
28
30
  @include_paths_default = include_paths_default
@@ -32,6 +34,10 @@ class CodeClimateToReek
32
34
  include_paths + ENGINE_CONFIGURATION
33
35
  end
34
36
 
37
+ def target_ruby_version
38
+ config.dig(CUSTOM_CONFIG_KEY, CUSTOM_CONFIG_TARGET_RUBY_VERSION_KEY)
39
+ end
40
+
35
41
  private
36
42
 
37
43
  def configuration_file_exists?
@@ -46,11 +52,14 @@ class CodeClimateToReek
46
52
  # ]
47
53
  # }
48
54
  def include_paths
55
+ config.fetch include_paths_key, include_paths_default
56
+ end
57
+
58
+ def config
49
59
  if configuration_file_exists?
50
- config = JSON.parse File.read(configuration_file_path)
51
- config.fetch include_paths_key, include_paths_default
60
+ JSON.parse File.read(configuration_file_path)
52
61
  else
53
- include_paths_default
62
+ {}
54
63
  end
55
64
  end
56
65
  end
@@ -58,11 +67,50 @@ end
58
67
  # Override for ReportCommand to force the use of CodeClimateReport.
59
68
  module ReportClassOverride
60
69
  def report_class
61
- Reek::Report::CodeClimateReport
70
+ Reek::CodeClimate::CodeClimateReport
71
+ end
72
+ end
73
+
74
+ # Override Reek::Source::SourceCode to use a parser version specified by the user
75
+ module SourceCodeOverride
76
+ # override self.default_parser method
77
+ def default_parser
78
+ parser_class.new(Reek::AST::Builder.new).tap do |parser|
79
+ diagnostics = parser.diagnostics
80
+ diagnostics.all_errors_are_fatal = true
81
+ diagnostics.ignore_warnings = true
82
+ end
83
+ end
84
+
85
+ # config.json file will look like this:
86
+ # {
87
+ # "include_paths":[
88
+ # "lib",
89
+ # "spec"
90
+ # ],
91
+ # "config": {
92
+ # "target_ruby_version": "3.1.0"
93
+ # }
94
+ # }
95
+ def parser_class
96
+ # convert an X.Y.Z version number to an XY two digit number
97
+ requested_version = CodeClimateToReek.new.target_ruby_version
98
+ return Parser::CurrentRuby if requested_version.nil?
99
+
100
+ version_number = Gem::Version.new(requested_version).segments[0..1].join
101
+
102
+ begin
103
+ Reek::CLI::Silencer.silently { require "parser/ruby#{version_number}" }
104
+ Module.const_get("Parser::Ruby#{version_number}")
105
+ rescue LoadError, NameError
106
+ # use Parser::CurrentRuby when an invalid version number is provided
107
+ Parser::CurrentRuby
108
+ end
62
109
  end
63
110
  end
64
111
 
65
112
  Reek::CLI::Command::ReportCommand.prepend ReportClassOverride
113
+ Reek::Source::SourceCode.singleton_class.prepend SourceCodeOverride
66
114
 
67
115
  application = Reek::CLI::Application.new(CodeClimateToReek.new.cli_arguments)
68
116
 
data/docs/yard_plugin.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'yard'
2
4
 
3
5
  # Template helper to modify processing of links in HTML generated from our
@@ -7,7 +9,7 @@ module LocalLinkHelper
7
9
  # {file: } directives.
8
10
  def resolve_links(text)
9
11
  text = text.gsub(%r{<a href="([^"]*.md)">([^<]*)</a>}, '{file:\1 \2}')
10
- super text
12
+ super
11
13
  end
12
14
  end
13
15
 
@@ -30,7 +30,7 @@ module Reek
30
30
  SexpExtensions.const_get(const)
31
31
  ]
32
32
  end
33
- Hash[assoc]
33
+ assoc.to_h
34
34
  end
35
35
  end
36
36
 
data/lib/reek/ast/node.rb CHANGED
@@ -9,6 +9,11 @@ module Reek
9
9
  # methods to ease the transition from Sexp to AST::Node.
10
10
  #
11
11
  class Node < ::Parser::AST::Node
12
+ # Struct representing the rules for the search performed by each_node method.
13
+ NodeLookupRule = Struct.new(:target_types, :ignoring)
14
+
15
+ private_constant :NodeLookupRule
16
+
12
17
  def initialize(type, children = [], options = {})
13
18
  @comments = options.fetch(:comments, [])
14
19
  super
@@ -60,9 +65,10 @@ module Reek
60
65
  #
61
66
  # Returns an array with all matching nodes.
62
67
  def each_node(target_types, ignoring = [], &blk)
63
- return enum_for(:each_node, target_types, ignoring) unless block_given?
68
+ return enum_for(:each_node, target_types, ignoring) unless blk
64
69
 
65
- look_for(Array(target_types), ignoring, &blk)
70
+ lookup_rule = NodeLookupRule.new(Array(target_types), ignoring)
71
+ look_for(lookup_rule, &blk)
66
72
  end
67
73
 
68
74
  def contains_nested_node?(target_type)
@@ -108,23 +114,23 @@ module Reek
108
114
  protected
109
115
 
110
116
  # See ".each_node" for documentation.
111
- def look_for(target_types, ignoring, &blk)
112
- if target_types.include? type
117
+ def look_for(lookup_rule, &blk)
118
+ if lookup_rule.target_types.include?(type)
113
119
  yield self
114
- return if ignoring.include?(type)
120
+ return if lookup_rule.ignoring.include?(type)
115
121
  end
116
122
  each_sexp do |elem|
117
- elem.look_for_recurse(target_types, ignoring, &blk)
123
+ elem.look_for_recurse(lookup_rule, &blk)
118
124
  end
119
125
  end
120
126
 
121
127
  # See ".each_node" for documentation.
122
- def look_for_recurse(target_types, ignoring, &blk)
123
- yield self if target_types.include? type
124
- return if ignoring.include? type
128
+ def look_for_recurse(lookup_rule, &blk)
129
+ yield self if lookup_rule.target_types.include?(type)
130
+ return if lookup_rule.ignoring.include?(type)
125
131
 
126
132
  each_sexp do |elem|
127
- elem.look_for_recurse(target_types, ignoring, &blk)
133
+ elem.look_for_recurse(lookup_rule, &blk)
128
134
  end
129
135
  end
130
136
 
@@ -104,6 +104,26 @@ module Reek
104
104
  end
105
105
  end
106
106
  # rubocop:enable Naming/ClassAndModuleCamelCase
107
+
108
+ # Utility methods for :forward_arg nodes.
109
+ # rubocop:disable Naming/ClassAndModuleCamelCase
110
+ module Forward_ArgNode
111
+ include ArgNodeBase
112
+
113
+ def anonymous_splat?
114
+ true
115
+ end
116
+ end
117
+ # rubocop:enable Naming/ClassAndModuleCamelCase
118
+
119
+ # Utility methods for :kwnilarg nodes.
120
+ module KwnilargNode
121
+ include ArgNodeBase
122
+
123
+ def anonymous_splat?
124
+ true
125
+ end
126
+ end
107
127
  end
108
128
  end
109
129
  end
@@ -10,7 +10,7 @@ module Reek
10
10
  end
11
11
 
12
12
  def body_nodes(type, ignoring = [])
13
- children[1..-1].compact.flat_map do |child|
13
+ children[1..].compact.flat_map do |child|
14
14
  child.each_node(type, ignoring | type).to_a
15
15
  end
16
16
  end
@@ -31,7 +31,7 @@ module Reek
31
31
 
32
32
  # @quality :reek:FeatureEnvy
33
33
  def body_nodes(type, ignoring = [])
34
- children[1..-1].compact.flat_map do |child|
34
+ children[1..].compact.flat_map do |child|
35
35
  if ignoring.include? child.type
36
36
  []
37
37
  else
@@ -16,7 +16,7 @@ module Reek
16
16
  end
17
17
 
18
18
  def args
19
- children[2..-1]
19
+ children[2..]
20
20
  end
21
21
 
22
22
  def participants
@@ -24,13 +24,10 @@ module Reek
24
24
  end
25
25
 
26
26
  def module_creation_call?
27
- object_creation_call? && module_creation_receiver?
28
- end
27
+ return true if object_creation_call? && module_creation_receiver?
28
+ return true if data_definition_call? && data_definition_receiver?
29
29
 
30
- def module_creation_receiver?
31
- receiver &&
32
- receiver.type == :const &&
33
- [:Class, :Struct].include?(receiver.simple_name)
30
+ false
34
31
  end
35
32
 
36
33
  def object_creation_call?
@@ -47,6 +44,24 @@ module Reek
47
44
  def attr_with_writable_flag?
48
45
  name == :attr && args.any? && args.last.type == :true
49
46
  end
47
+
48
+ private
49
+
50
+ def module_creation_receiver?
51
+ const_receiver? && [:Class, :Struct].include?(receiver.simple_name)
52
+ end
53
+
54
+ def data_definition_call?
55
+ name == :define
56
+ end
57
+
58
+ def data_definition_receiver?
59
+ const_receiver? && receiver.simple_name == :Data
60
+ end
61
+
62
+ def const_receiver?
63
+ receiver && receiver.type == :const
64
+ end
50
65
  end
51
66
 
52
67
  Op_AsgnNode = SendNode
@@ -13,7 +13,7 @@ module Reek
13
13
  #
14
14
  class TodoListCommand < BaseCommand
15
15
  HEADER = "# Auto generated by Reeks --todo flag\n"
16
- EXISTING_FILE_MESSAGE = "\nExisting '#{DEFAULT_CONFIGURATION_FILE_NAME}' detected - aborting.\n"
16
+ EXISTING_FILE_MESSAGE = "\nExisting '#{DEFAULT_CONFIGURATION_FILE_NAME}' detected - aborting.\n".freeze
17
17
  NO_SMELLS_FOUND_MESSAGE = "\nNo smells found - nothing to do, exiting.\n"
18
18
 
19
19
  def execute
@@ -23,8 +23,8 @@ module Reek
23
23
  puts EXISTING_FILE_MESSAGE
24
24
  else
25
25
  write_to_file
26
- puts "\n'#{DEFAULT_CONFIGURATION_FILE_NAME}' generated! "\
27
- 'You can now use this as a starting point.'
26
+ puts "\n'#{DEFAULT_CONFIGURATION_FILE_NAME}' generated! " \
27
+ 'You can now use this as a starting point.'
28
28
  end
29
29
  options.success_exit_code
30
30
  end
@@ -110,12 +110,12 @@ module Reek
110
110
  parser.on('--smell SMELL',
111
111
  'Only look for a specific smell.',
112
112
  'Call it like this: reek --smell MissingSafeMethod source.rb',
113
- "Check out #{DocumentationLink.build('Code Smells')} "\
113
+ "Check out #{DocumentationLink.build('Code Smells')} " \
114
114
  'for a list of smells') do |smell|
115
115
  smells_to_detect << smell
116
116
  end
117
117
  parser.on('--stdin-filename FILE',
118
- 'When passing code in via pipe, assume this filename when '\
118
+ 'When passing code in via pipe, assume this filename when ' \
119
119
  'checking file or directory rules in the config.') do |file|
120
120
  self.stdin_filename = file
121
121
  end
@@ -131,9 +131,9 @@ module Reek
131
131
  def set_alternative_formatter_options
132
132
  parser.separator "\nReport format:"
133
133
  parser.on(
134
- '-f', '--format FORMAT', [:html, :text, :yaml, :json, :xml],
134
+ '-f', '--format FORMAT', [:html, :text, :yaml, :json, :xml, :github],
135
135
  'Report smells in the given format:',
136
- ' html', ' text (default)', ' yaml', ' json', ' xml') do |opt|
136
+ ' html', ' text (default)', ' yaml', ' json', ' xml', ' github') do |opt|
137
137
  self.report_format = opt
138
138
  end
139
139
  end
@@ -210,12 +210,12 @@ module Reek
210
210
  def set_exit_codes
211
211
  parser.separator "\nExit codes:"
212
212
  parser.on('--success-exit-code CODE',
213
- 'The exit code when no smells are found '\
213
+ 'The exit code when no smells are found ' \
214
214
  "(default: #{Status::DEFAULT_SUCCESS_EXIT_CODE})") do |option|
215
215
  self.success_exit_code = Integer(option)
216
216
  end
217
217
  parser.on('--failure-exit-code CODE',
218
- 'The exit code when smells are found '\
218
+ 'The exit code when smells are found ' \
219
219
  "(default: #{Status::DEFAULT_FAILURE_EXIT_CODE})") do |option|
220
220
  self.failure_exit_code = Integer(option)
221
221
  end
@@ -231,8 +231,8 @@ module Reek
231
231
  parser.on_tail('-l', '--list', 'List all available smell detectors') do
232
232
  puts "All available smell detectors:\n\n"
233
233
  puts DetectorRepository.available_detector_names
234
- puts "\nCheck out #{DocumentationLink.build('Code Smells')} "\
235
- 'for a details on each detector'
234
+ puts "\nCheck out #{DocumentationLink.build('Code Smells')} " \
235
+ 'for a details on each detector'
236
236
  exit
237
237
  end
238
238
  parser.on_tail('-v', '--version', 'Show version') do
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Reek
4
- module Report
4
+ module CodeClimate
5
5
  # loads the smell type metadata to present in Code Climate
6
6
  module CodeClimateConfiguration
7
7
  def self.load