reek 6.0.2 → 6.2.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 (271) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +13 -0
  3. data/.github/workflows/ruby.yml +57 -0
  4. data/.rubocop.yml +6 -12
  5. data/.rubocop_todo.yml +6 -4
  6. data/CHANGELOG.md +95 -0
  7. data/CONTRIBUTING.md +10 -10
  8. data/Dockerfile +1 -1
  9. data/Gemfile +8 -7
  10. data/README.md +29 -29
  11. data/bin/code_climate_reek +56 -8
  12. data/lib/reek/ast/ast_node_class_map.rb +1 -1
  13. data/lib/reek/ast/node.rb +1 -1
  14. data/lib/reek/ast/sexp_extensions/arguments.rb +20 -0
  15. data/lib/reek/ast/sexp_extensions/case.rb +1 -1
  16. data/lib/reek/ast/sexp_extensions/if.rb +1 -1
  17. data/lib/reek/ast/sexp_extensions/send.rb +22 -7
  18. data/lib/reek/cli/command/todo_list_command.rb +3 -3
  19. data/lib/reek/cli/options.rb +6 -6
  20. data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.rb +1 -1
  21. data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.yml +41 -41
  22. data/lib/reek/{report/code_climate → code_climate}/code_climate_fingerprint.rb +2 -2
  23. data/lib/reek/{report/code_climate → code_climate}/code_climate_formatter.rb +2 -4
  24. data/lib/reek/{report/code_climate → code_climate}/code_climate_report.rb +3 -3
  25. data/lib/reek/code_comment.rb +25 -20
  26. data/lib/reek/configuration/app_configuration.rb +5 -5
  27. data/lib/reek/configuration/configuration_converter.rb +1 -1
  28. data/lib/reek/configuration/configuration_file_finder.rb +5 -4
  29. data/lib/reek/configuration/default_directive.rb +1 -1
  30. data/lib/reek/configuration/directory_directives.rb +1 -1
  31. data/lib/reek/configuration/excluded_paths.rb +3 -2
  32. data/lib/reek/configuration/schema.rb +177 -0
  33. data/lib/reek/configuration/schema_validator.rb +12 -13
  34. data/lib/reek/context/attribute_context.rb +1 -1
  35. data/lib/reek/context/code_context.rb +1 -1
  36. data/lib/reek/context/method_context.rb +1 -1
  37. data/lib/reek/context/module_context.rb +4 -0
  38. data/lib/reek/context/refinement_context.rb +16 -0
  39. data/lib/reek/context/send_context.rb +7 -1
  40. data/lib/reek/context_builder.rb +17 -3
  41. data/lib/reek/documentation_link.rb +3 -5
  42. data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +2 -2
  43. data/lib/reek/errors/bad_detector_in_comment_error.rb +2 -2
  44. data/lib/reek/errors/encoding_error.rb +1 -1
  45. data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +2 -2
  46. data/lib/reek/errors/incomprehensible_source_error.rb +1 -1
  47. data/lib/reek/errors/legacy_comment_separator_error.rb +2 -2
  48. data/lib/reek/errors/syntax_error.rb +1 -1
  49. data/lib/reek/rake/task.rb +5 -5
  50. data/lib/reek/smell_detectors/base_detector.rb +1 -1
  51. data/lib/reek/smell_detectors/class_variable.rb +2 -2
  52. data/lib/reek/smell_detectors/control_parameter_helpers/candidate.rb +6 -6
  53. data/lib/reek/smell_detectors/control_parameter_helpers/control_parameter_finder.rb +1 -1
  54. data/lib/reek/smell_detectors/duplicate_method_call.rb +5 -5
  55. data/lib/reek/smell_detectors/instance_variable_assumption.rb +8 -8
  56. data/lib/reek/smell_detectors/nested_iterators.rb +4 -3
  57. data/lib/reek/smell_detectors/unused_private_method.rb +3 -2
  58. data/lib/reek/smell_warning.rb +1 -1
  59. data/lib/reek/source/source_locator.rb +1 -3
  60. data/lib/reek/spec/should_reek_of.rb +11 -9
  61. data/lib/reek/spec.rb +1 -1
  62. data/lib/reek/version.rb +2 -2
  63. data/reek.gemspec +29 -25
  64. metadata +37 -250
  65. data/.travis.yml +0 -40
  66. data/docs/API.md +0 -174
  67. data/docs/Attribute.md +0 -39
  68. data/docs/Basic-Smell-Options.md +0 -85
  69. data/docs/Boolean-Parameter.md +0 -54
  70. data/docs/Class-Variable.md +0 -40
  71. data/docs/Code-Smells.md +0 -39
  72. data/docs/Command-Line-Options.md +0 -119
  73. data/docs/Control-Couple.md +0 -26
  74. data/docs/Control-Parameter.md +0 -32
  75. data/docs/Data-Clump.md +0 -46
  76. data/docs/Duplicate-Method-Call.md +0 -264
  77. data/docs/Feature-Envy.md +0 -93
  78. data/docs/How-To-Write-New-Detectors.md +0 -132
  79. data/docs/How-reek-works-internally.md +0 -114
  80. data/docs/Instance-Variable-Assumption.md +0 -163
  81. data/docs/Irresponsible-Module.md +0 -47
  82. data/docs/Large-Class.md +0 -16
  83. data/docs/Long-Parameter-List.md +0 -39
  84. data/docs/Long-Yield-List.md +0 -37
  85. data/docs/Manual-Dispatch.md +0 -30
  86. data/docs/Missing-Safe-Method.md +0 -92
  87. data/docs/Module-Initialize.md +0 -62
  88. data/docs/Nested-Iterators.md +0 -59
  89. data/docs/Nil-Check.md +0 -47
  90. data/docs/RSpec-matchers.md +0 -129
  91. data/docs/Rake-Task.md +0 -66
  92. data/docs/Reek-4-to-Reek-5-migration.md +0 -188
  93. data/docs/Reek-Driven-Development.md +0 -46
  94. data/docs/Repeated-Conditional.md +0 -47
  95. data/docs/Simulated-Polymorphism.md +0 -16
  96. data/docs/Smell-Suppression.md +0 -96
  97. data/docs/Style-Guide.md +0 -19
  98. data/docs/Subclassed-From-Core-Class.md +0 -79
  99. data/docs/Too-Many-Constants.md +0 -37
  100. data/docs/Too-Many-Instance-Variables.md +0 -43
  101. data/docs/Too-Many-Methods.md +0 -56
  102. data/docs/Too-Many-Statements.md +0 -54
  103. data/docs/Uncommunicative-Method-Name.md +0 -94
  104. data/docs/Uncommunicative-Module-Name.md +0 -92
  105. data/docs/Uncommunicative-Name.md +0 -18
  106. data/docs/Uncommunicative-Parameter-Name.md +0 -90
  107. data/docs/Uncommunicative-Variable-Name.md +0 -96
  108. data/docs/Unused-Parameters.md +0 -28
  109. data/docs/Unused-Private-Method.md +0 -101
  110. data/docs/Utility-Function.md +0 -56
  111. data/docs/Versioning-Policy.md +0 -7
  112. data/docs/YAML-Reports.md +0 -93
  113. data/docs/defaults.reek.yml +0 -129
  114. data/docs/templates/default/docstring/html/public_api_marker.erb +0 -3
  115. data/docs/templates/default/docstring/setup.rb +0 -37
  116. data/docs/templates/default/fulldoc/html/css/common.css +0 -1
  117. data/docs/yard_plugin.rb +0 -17
  118. data/features/command_line_interface/basic_usage.feature +0 -15
  119. data/features/command_line_interface/options.feature +0 -123
  120. data/features/command_line_interface/show_progress.feature +0 -33
  121. data/features/command_line_interface/smell_selection.feature +0 -15
  122. data/features/command_line_interface/smells_count.feature +0 -38
  123. data/features/command_line_interface/stdin.feature +0 -65
  124. data/features/configuration_files/accept_setting.feature +0 -87
  125. data/features/configuration_files/directory_specific_directives.feature +0 -274
  126. data/features/configuration_files/exclude_directives.feature +0 -35
  127. data/features/configuration_files/exclude_paths_directives.feature +0 -42
  128. data/features/configuration_files/masking_smells.feature +0 -94
  129. data/features/configuration_files/mix_accept_reject_setting.feature +0 -84
  130. data/features/configuration_files/reject_setting.feature +0 -89
  131. data/features/configuration_files/schema_validation.feature +0 -59
  132. data/features/configuration_files/show_configuration_file.feature +0 -44
  133. data/features/configuration_files/unused_private_method.feature +0 -68
  134. data/features/configuration_loading.feature +0 -91
  135. data/features/configuration_via_source_comments/erroneous_source_comments.feature +0 -68
  136. data/features/configuration_via_source_comments/well_formed_source_comments.feature +0 -116
  137. data/features/locales.feature +0 -32
  138. data/features/programmatic_access.feature +0 -41
  139. data/features/rake_task/rake_task.feature +0 -138
  140. data/features/reports/codeclimate.feature +0 -59
  141. data/features/reports/json.feature +0 -59
  142. data/features/reports/reports.feature +0 -219
  143. data/features/reports/yaml.feature +0 -52
  144. data/features/rspec_matcher.feature +0 -41
  145. data/features/samples.feature +0 -305
  146. data/features/step_definitions/.rubocop.yml +0 -5
  147. data/features/step_definitions/reek_steps.rb +0 -102
  148. data/features/step_definitions/sample_file_steps.rb +0 -63
  149. data/features/support/env.rb +0 -33
  150. data/features/todo_list.feature +0 -108
  151. data/lib/reek/configuration/schema.yml +0 -210
  152. data/samples/checkstyle.xml +0 -7
  153. data/samples/clean_source/clean.rb +0 -6
  154. data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +0 -29
  155. data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +0 -30
  156. data/samples/configuration/corrupt.reek +0 -1
  157. data/samples/configuration/empty.reek +0 -0
  158. data/samples/configuration/full_configuration.reek +0 -13
  159. data/samples/configuration/full_mask.reek +0 -6
  160. data/samples/configuration/home/home.reek.yml +0 -4
  161. data/samples/configuration/partial_mask.reek +0 -4
  162. data/samples/configuration/regular_configuration/.reek.yml +0 -4
  163. data/samples/configuration/regular_configuration/empty_sub_directory/.gitignore +0 -0
  164. data/samples/configuration/with_excluded_paths.reek +0 -5
  165. data/samples/no_config_file/.keep +0 -0
  166. data/samples/paths.rb +0 -5
  167. data/samples/smelly_source/inline.rb +0 -704
  168. data/samples/smelly_source/optparse.rb +0 -1788
  169. data/samples/smelly_source/redcloth.rb +0 -1130
  170. data/samples/smelly_source/ruby.rb +0 -368
  171. data/samples/smelly_source/smelly.rb +0 -7
  172. data/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +0 -5
  173. data/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +0 -2
  174. data/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +0 -6
  175. data/samples/source_with_exclude_paths/nested/uncommunicative_variable_name.rb +0 -6
  176. data/samples/source_with_hidden_directories/.hidden/hidden.rb +0 -1
  177. data/samples/source_with_hidden_directories/not_hidden.rb +0 -1
  178. data/samples/source_with_non_ruby_files/gibberish +0 -1
  179. data/samples/source_with_non_ruby_files/python_source.py +0 -1
  180. data/samples/source_with_non_ruby_files/ruby.rb +0 -6
  181. data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +0 -15
  182. data/spec/quality/documentation_spec.rb +0 -41
  183. data/spec/quality/reek_source_spec.rb +0 -11
  184. data/spec/reek/ast/node_spec.rb +0 -211
  185. data/spec/reek/ast/object_refs_spec.rb +0 -83
  186. data/spec/reek/ast/reference_collector_spec.rb +0 -47
  187. data/spec/reek/ast/sexp_extensions_spec.rb +0 -498
  188. data/spec/reek/cli/application_spec.rb +0 -168
  189. data/spec/reek/cli/command/report_command_spec.rb +0 -44
  190. data/spec/reek/cli/command/todo_list_command_spec.rb +0 -86
  191. data/spec/reek/cli/options_spec.rb +0 -51
  192. data/spec/reek/cli/silencer_spec.rb +0 -28
  193. data/spec/reek/code_comment_spec.rb +0 -184
  194. data/spec/reek/configuration/app_configuration_spec.rb +0 -195
  195. data/spec/reek/configuration/configuration_file_finder_spec.rb +0 -230
  196. data/spec/reek/configuration/default_directive_spec.rb +0 -13
  197. data/spec/reek/configuration/directory_directives_spec.rb +0 -122
  198. data/spec/reek/configuration/excluded_paths_spec.rb +0 -16
  199. data/spec/reek/configuration/rake_task_converter_spec.rb +0 -33
  200. data/spec/reek/configuration/schema_validator_spec.rb +0 -165
  201. data/spec/reek/context/code_context_spec.rb +0 -192
  202. data/spec/reek/context/ghost_context_spec.rb +0 -60
  203. data/spec/reek/context/method_context_spec.rb +0 -72
  204. data/spec/reek/context/module_context_spec.rb +0 -55
  205. data/spec/reek/context/root_context_spec.rb +0 -12
  206. data/spec/reek/context/statement_counter_spec.rb +0 -24
  207. data/spec/reek/context_builder_spec.rb +0 -457
  208. data/spec/reek/detector_repository_spec.rb +0 -22
  209. data/spec/reek/documentation_link_spec.rb +0 -20
  210. data/spec/reek/errors/base_error_spec.rb +0 -13
  211. data/spec/reek/examiner_spec.rb +0 -309
  212. data/spec/reek/logging_error_handler_spec.rb +0 -24
  213. data/spec/reek/rake/task_spec.rb +0 -56
  214. data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +0 -22
  215. data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +0 -126
  216. data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +0 -51
  217. data/spec/reek/report/code_climate/code_climate_report_spec.rb +0 -56
  218. data/spec/reek/report/html_report_spec.rb +0 -19
  219. data/spec/reek/report/json_report_spec.rb +0 -58
  220. data/spec/reek/report/location_formatter_spec.rb +0 -32
  221. data/spec/reek/report/progress_formatter_spec.rb +0 -68
  222. data/spec/reek/report/text_report_spec.rb +0 -89
  223. data/spec/reek/report/xml_report_spec.rb +0 -24
  224. data/spec/reek/report/yaml_report_spec.rb +0 -55
  225. data/spec/reek/report_spec.rb +0 -28
  226. data/spec/reek/smell_configuration_spec.rb +0 -56
  227. data/spec/reek/smell_detectors/attribute_spec.rb +0 -197
  228. data/spec/reek/smell_detectors/base_detector_spec.rb +0 -50
  229. data/spec/reek/smell_detectors/boolean_parameter_spec.rb +0 -93
  230. data/spec/reek/smell_detectors/class_variable_spec.rb +0 -106
  231. data/spec/reek/smell_detectors/control_parameter_spec.rb +0 -300
  232. data/spec/reek/smell_detectors/data_clump_spec.rb +0 -134
  233. data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +0 -211
  234. data/spec/reek/smell_detectors/feature_envy_spec.rb +0 -295
  235. data/spec/reek/smell_detectors/instance_variable_assumption_spec.rb +0 -96
  236. data/spec/reek/smell_detectors/irresponsible_module_spec.rb +0 -226
  237. data/spec/reek/smell_detectors/long_parameter_list_spec.rb +0 -61
  238. data/spec/reek/smell_detectors/long_yield_list_spec.rb +0 -49
  239. data/spec/reek/smell_detectors/manual_dispatch_spec.rb +0 -75
  240. data/spec/reek/smell_detectors/missing_safe_method_spec.rb +0 -68
  241. data/spec/reek/smell_detectors/module_initialize_spec.rb +0 -77
  242. data/spec/reek/smell_detectors/nested_iterators_spec.rb +0 -333
  243. data/spec/reek/smell_detectors/nil_check_spec.rb +0 -100
  244. data/spec/reek/smell_detectors/repeated_conditional_spec.rb +0 -100
  245. data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -77
  246. data/spec/reek/smell_detectors/too_many_constants_spec.rb +0 -144
  247. data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +0 -132
  248. data/spec/reek/smell_detectors/too_many_methods_spec.rb +0 -54
  249. data/spec/reek/smell_detectors/too_many_statements_spec.rb +0 -90
  250. data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +0 -78
  251. data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +0 -78
  252. data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +0 -147
  253. data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +0 -201
  254. data/spec/reek/smell_detectors/unused_parameters_spec.rb +0 -114
  255. data/spec/reek/smell_detectors/unused_private_method_spec.rb +0 -205
  256. data/spec/reek/smell_detectors/utility_function_spec.rb +0 -293
  257. data/spec/reek/smell_warning_spec.rb +0 -137
  258. data/spec/reek/source/source_code_spec.rb +0 -79
  259. data/spec/reek/source/source_locator_spec.rb +0 -166
  260. data/spec/reek/spec/should_reek_of_spec.rb +0 -153
  261. data/spec/reek/spec/should_reek_only_of_spec.rb +0 -91
  262. data/spec/reek/spec/should_reek_spec.rb +0 -52
  263. data/spec/reek/spec/smell_matcher_spec.rb +0 -87
  264. data/spec/reek/tree_dresser_spec.rb +0 -46
  265. data/spec/spec_helper.rb +0 -110
  266. data/tasks/configuration.rake +0 -18
  267. data/tasks/console.rake +0 -5
  268. data/tasks/reek.rake +0 -6
  269. data/tasks/rubocop.rake +0 -11
  270. data/tasks/test.rake +0 -32
  271. /data/lib/reek/{report/code_climate.rb → code_climate.rb} +0 -0
@@ -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
 
@@ -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
@@ -60,7 +60,7 @@ module Reek
60
60
  #
61
61
  # Returns an array with all matching nodes.
62
62
  def each_node(target_types, ignoring = [], &blk)
63
- return enum_for(:each_node, target_types, ignoring) unless block_given?
63
+ return enum_for(:each_node, target_types, ignoring) unless blk
64
64
 
65
65
  look_for(Array(target_types), ignoring, &blk)
66
66
  end
@@ -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
@@ -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
@@ -10,7 +10,7 @@ Attribute:
10
10
 
11
11
  Given:
12
12
 
13
- ```Ruby
13
+ ```ruby
14
14
  class Klass
15
15
  attr_accessor :dummy
16
16
  end
@@ -33,7 +33,7 @@ BooleanParameter:
33
33
 
34
34
  Given
35
35
 
36
- ```Ruby
36
+ ```ruby
37
37
  class Dummy
38
38
  def hit_the_switch(switch = true)
39
39
  if switch
@@ -63,7 +63,7 @@ BooleanParameter:
63
63
 
64
64
  * Move everything in the `if` branch into a separate method
65
65
  * Move everything in the `else` branch into a separate method
66
- * Get rid of the `hit_the_switch` method alltogether
66
+ * Get rid of the `hit_the_switch` method altogether
67
67
  * Make the decision what method to call in the initial caller of `hit_the_switch`
68
68
  ClassVariable:
69
69
  remediation_points: 350_000
@@ -76,7 +76,7 @@ ClassVariable:
76
76
 
77
77
  Given
78
78
 
79
- ```Ruby
79
+ ```ruby
80
80
  class Dummy
81
81
  @@class_variable = :whatever
82
82
  end
@@ -95,7 +95,7 @@ ClassVariable:
95
95
 
96
96
  You can use class-instance variable to mitigate the problem (as also suggested in the linked article above):
97
97
 
98
- ```Ruby
98
+ ```ruby
99
99
  class Dummy
100
100
  @class_variable = :whatever
101
101
  end
@@ -109,7 +109,7 @@ ControlParameter:
109
109
 
110
110
  A simple example would be the "quoted" parameter in the following method:
111
111
 
112
- ```Ruby
112
+ ```ruby
113
113
  def write(quoted)
114
114
  if quoted
115
115
  write_quoted @value
@@ -119,7 +119,7 @@ ControlParameter:
119
119
  end
120
120
  ```
121
121
 
122
- Fixing those problems is out of the scope of this document but an easy solution could be to remove the "write" method alltogether and to move the calls to "write_quoted" / "write_unquoted" in the initial caller of "write".
122
+ Fixing those problems is out of the scope of this document but an easy solution could be to remove the "write" method altogether and to move the calls to "write_quoted" / "write_unquoted" in the initial caller of "write".
123
123
  DataClump:
124
124
  remediation_points: 250_000
125
125
  content: |
@@ -131,7 +131,7 @@ DataClump:
131
131
 
132
132
  Given
133
133
 
134
- ```Ruby
134
+ ```ruby
135
135
  class Dummy
136
136
  def x(y1,y2); end
137
137
  def y(y1,y2); end
@@ -160,7 +160,7 @@ DuplicateMethodCall:
160
160
 
161
161
  Here's a very much simplified and contrived example. The following method will report a warning:
162
162
 
163
- ```Ruby
163
+ ```ruby
164
164
  def double_thing()
165
165
  @other.thing + @other.thing
166
166
  end
@@ -168,7 +168,7 @@ DuplicateMethodCall:
168
168
 
169
169
  One quick approach to silence Reek would be to refactor the code thus:
170
170
 
171
- ```Ruby
171
+ ```ruby
172
172
  def double_thing()
173
173
  thing = @other.thing
174
174
  thing + thing
@@ -177,7 +177,7 @@ DuplicateMethodCall:
177
177
 
178
178
  A slightly different approach would be to replace all calls of `double_thing` by calls to `@other.double_thing`:
179
179
 
180
- ```Ruby
180
+ ```ruby
181
181
  class Other
182
182
  def double_thing()
183
183
  thing + thing
@@ -201,7 +201,7 @@ FeatureEnvy:
201
201
 
202
202
  Running Reek on:
203
203
 
204
- ```Ruby
204
+ ```ruby
205
205
  class Warehouse
206
206
  def sale_price(item)
207
207
  (item.price - item.rebate) * @vat
@@ -211,13 +211,13 @@ FeatureEnvy:
211
211
 
212
212
  would report:
213
213
 
214
- ```Bash
214
+ ```bash
215
215
  Warehouse#total_price refers to item more than self (FeatureEnvy)
216
216
  ```
217
217
 
218
218
  since this:
219
219
 
220
- ```Ruby
220
+ ```ruby
221
221
  (item.price - item.rebate)
222
222
  ```
223
223
 
@@ -229,7 +229,7 @@ InstanceVariableAssumption:
229
229
 
230
230
  Good:
231
231
 
232
- ```Ruby
232
+ ```ruby
233
233
  class Foo
234
234
  def initialize
235
235
  @bar = :foo
@@ -243,7 +243,7 @@ InstanceVariableAssumption:
243
243
 
244
244
  Good as well:
245
245
 
246
- ```Ruby
246
+ ```ruby
247
247
  class Foo
248
248
  def foo?
249
249
  bar == :foo
@@ -257,7 +257,7 @@ InstanceVariableAssumption:
257
257
 
258
258
  Bad:
259
259
 
260
- ```Ruby
260
+ ```ruby
261
261
  class Foo
262
262
  def go_foo!
263
263
  @bar = :foo
@@ -273,7 +273,7 @@ InstanceVariableAssumption:
273
273
 
274
274
  Running Reek on:
275
275
 
276
- ```Ruby
276
+ ```ruby
277
277
  class Dummy
278
278
  def test
279
279
  @ivar
@@ -283,13 +283,13 @@ InstanceVariableAssumption:
283
283
 
284
284
  would report:
285
285
 
286
- ```Bash
286
+ ```bash
287
287
  [1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar
288
288
  ```
289
289
 
290
290
  Note that this example would trigger this smell warning as well:
291
291
 
292
- ```Ruby
292
+ ```ruby
293
293
  class Parent
294
294
  def initialize(omg)
295
295
  @omg = omg
@@ -305,7 +305,7 @@ InstanceVariableAssumption:
305
305
 
306
306
  The way to address the smell warning is that you should create an `attr_reader` to use `@omg` in the subclass and not access `@omg` directly like this:
307
307
 
308
- ```Ruby
308
+ ```ruby
309
309
  class Parent
310
310
  attr_reader :omg
311
311
 
@@ -325,7 +325,7 @@ InstanceVariableAssumption:
325
325
 
326
326
  If you don't want to expose those methods as public API just make them private like this:
327
327
 
328
- ```Ruby
328
+ ```ruby
329
329
  class Parent
330
330
  def initialize(omg)
331
331
  @omg = omg
@@ -360,7 +360,7 @@ IrresponsibleModule:
360
360
 
361
361
  Given
362
362
 
363
- ```Ruby
363
+ ```ruby
364
364
  class Dummy
365
365
  # Do things...
366
366
  end
@@ -375,7 +375,7 @@ IrresponsibleModule:
375
375
 
376
376
  Fixing this is simple - just an explaining comment:
377
377
 
378
- ```Ruby
378
+ ```ruby
379
379
  # The Dummy class is responsible for ...
380
380
  class Dummy
381
381
  # Do things...
@@ -390,7 +390,7 @@ LongParameterList:
390
390
 
391
391
  Given
392
392
 
393
- ```Ruby
393
+ ```ruby
394
394
  class Dummy
395
395
  def long_list(foo,bar,baz,fling,flung)
396
396
  puts foo,bar,baz,fling,flung
@@ -413,7 +413,7 @@ LongYieldList:
413
413
 
414
414
  ## Example
415
415
 
416
- ```Ruby
416
+ ```ruby
417
417
  class Dummy
418
418
  def yields_a_lot(foo,bar,baz,fling,flung)
419
419
  yield foo,bar,baz,fling,flung
@@ -436,7 +436,7 @@ ManualDispatch:
436
436
 
437
437
  ## Example
438
438
 
439
- ```Ruby
439
+ ```ruby
440
440
  class MyManualDispatcher
441
441
  attr_reader :foo
442
442
 
@@ -467,7 +467,7 @@ ModuleInitialize:
467
467
 
468
468
  The `Foo` module below contains a method `initialize`. Although class `B` inherits from `A`, the inclusion of `Foo` stops `A#initialize` from being called.
469
469
 
470
- ```Ruby
470
+ ```ruby
471
471
  class A
472
472
  def initialize(a)
473
473
  @a = a
@@ -492,7 +492,7 @@ ModuleInitialize:
492
492
 
493
493
  A simple solution is to rename `Foo#initialize` and call that method by name:
494
494
 
495
- ```Ruby
495
+ ```ruby
496
496
  module Foo
497
497
  def setup_foo_module(foo)
498
498
  @foo = foo
@@ -518,7 +518,7 @@ NestedIterators:
518
518
 
519
519
  Given
520
520
 
521
- ```Ruby
521
+ ```ruby
522
522
  class Duck
523
523
  class << self
524
524
  def duck_names
@@ -549,7 +549,7 @@ NilCheck:
549
549
 
550
550
  Given
551
551
 
552
- ```Ruby
552
+ ```ruby
553
553
  class Klass
554
554
  def nil_checker(argument)
555
555
  if argument.nil?
@@ -582,7 +582,7 @@ MissingSafeMethod:
582
582
 
583
583
  Given
584
584
 
585
- ```Ruby
585
+ ```ruby
586
586
  class C
587
587
  def foo; end
588
588
  def foo!; end
@@ -595,7 +595,7 @@ MissingSafeMethod:
595
595
  Reek reports this smell only in a class context, not in a module context in order to allow perfectly legit code like this:
596
596
 
597
597
 
598
- ```Ruby
598
+ ```ruby
599
599
  class Parent
600
600
  def foo; end
601
601
  end
@@ -622,7 +622,7 @@ RepeatedConditional:
622
622
 
623
623
  Given
624
624
 
625
- ```Ruby
625
+ ```ruby
626
626
  class RepeatedConditionals
627
627
  attr_accessor :switch
628
628
 
@@ -664,7 +664,7 @@ TooManyInstanceVariables:
664
664
 
665
665
  and this code:
666
666
 
667
- ```Ruby
667
+ ```ruby
668
668
  class TooManyInstanceVariables
669
669
  def initialize
670
670
  @arg_1 = :dummy
@@ -697,7 +697,7 @@ TooManyConstants:
697
697
 
698
698
  and this code:
699
699
 
700
- ```Ruby
700
+ ```ruby
701
701
  class TooManyConstants
702
702
  CONST_1 = :dummy
703
703
  CONST_2 = :dummy
@@ -728,7 +728,7 @@ TooManyMethods:
728
728
 
729
729
  and this code:
730
730
 
731
- ```Ruby
731
+ ```ruby
732
732
  class TooManyMethods
733
733
  def one; end
734
734
  def two; end
@@ -752,7 +752,7 @@ TooManyStatements:
752
752
 
753
753
  So the following method would score +6 in Reek's statement-counting algorithm:
754
754
 
755
- ```Ruby
755
+ ```ruby
756
756
  def parse(arg, argv, &error)
757
757
  if !(val = arg) and (argv.empty? or /\A-/ =~ (val = argv[0]))
758
758
  return nil, block, nil # +1
@@ -768,7 +768,7 @@ TooManyStatements:
768
768
  end
769
769
  ```
770
770
 
771
- (You might argue that the two assigments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)
771
+ (You might argue that the two assignments within the first @if@ should count as statements, and that perhaps the nested assignment should count as +2.)
772
772
  UncommunicativeMethodName:
773
773
  remediation_points: 150_000
774
774
  content: |
@@ -804,7 +804,7 @@ UnusedParameters:
804
804
 
805
805
  Given:
806
806
 
807
- ```Ruby
807
+ ```ruby
808
808
  class Klass
809
809
  def unused_parameters(x,y,z)
810
810
  puts x,y # but not z
@@ -830,7 +830,7 @@ UnusedPrivateMethod:
830
830
 
831
831
  Given:
832
832
 
833
- ```Ruby
833
+ ```ruby
834
834
  class Car
835
835
  private
836
836
  def drive; end
@@ -3,7 +3,7 @@
3
3
  require 'digest'
4
4
 
5
5
  module Reek
6
- module Report
6
+ module CodeClimate
7
7
  # Generates a string to uniquely identify a smell
8
8
  class CodeClimateFingerprint
9
9
  NON_IDENTIFYING_PARAMETERS = [:count, :depth].freeze
@@ -36,7 +36,7 @@ module Reek
36
36
  end
37
37
 
38
38
  def parameters
39
- warning.parameters.reject { |key, _| NON_IDENTIFYING_PARAMETERS.include?(key) }.sort.to_s
39
+ warning.parameters.except(*NON_IDENTIFYING_PARAMETERS).sort.to_s
40
40
  end
41
41
 
42
42
  def warning_uniquely_identifiable?
@@ -4,7 +4,7 @@ require 'codeclimate_engine'
4
4
  require_relative 'code_climate_configuration'
5
5
 
6
6
  module Reek
7
- module Report
7
+ module CodeClimate
8
8
  # Generates a hash in the structure specified by the Code Climate engine spec
9
9
  class CodeClimateFormatter
10
10
  def initialize(warning)
@@ -57,9 +57,7 @@ module Reek
57
57
  end
58
58
 
59
59
  def configuration
60
- @configuration ||= begin
61
- CodeClimateConfiguration.load
62
- end
60
+ @configuration ||= CodeClimateConfiguration.load
63
61
  end
64
62
  end
65
63
  end