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.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +13 -0
- data/.github/workflows/ruby.yml +58 -0
- data/.gitignore +0 -1
- data/.rubocop.yml +7 -20
- data/.rubocop_todo.yml +6 -4
- data/.simplecov +2 -0
- data/CHANGELOG.md +114 -0
- data/CONTRIBUTING.md +10 -10
- data/Dockerfile +1 -1
- data/Gemfile +17 -24
- data/README.md +38 -40
- data/Rakefile +2 -0
- data/bin/code_climate_reek +56 -8
- data/docs/yard_plugin.rb +3 -1
- data/lib/reek/ast/ast_node_class_map.rb +1 -1
- data/lib/reek/ast/node.rb +16 -10
- data/lib/reek/ast/sexp_extensions/arguments.rb +20 -0
- data/lib/reek/ast/sexp_extensions/case.rb +1 -1
- data/lib/reek/ast/sexp_extensions/if.rb +1 -1
- data/lib/reek/ast/sexp_extensions/send.rb +22 -7
- data/lib/reek/cli/command/todo_list_command.rb +3 -3
- data/lib/reek/cli/options.rb +8 -8
- data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.rb +1 -1
- data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.yml +41 -41
- data/lib/reek/{report/code_climate → code_climate}/code_climate_fingerprint.rb +2 -2
- data/lib/reek/{report/code_climate → code_climate}/code_climate_formatter.rb +2 -4
- data/lib/reek/{report/code_climate → code_climate}/code_climate_report.rb +3 -3
- data/lib/reek/code_comment.rb +25 -20
- data/lib/reek/configuration/app_configuration.rb +5 -5
- data/lib/reek/configuration/configuration_converter.rb +1 -1
- data/lib/reek/configuration/configuration_file_finder.rb +5 -4
- data/lib/reek/configuration/default_directive.rb +1 -1
- data/lib/reek/configuration/directory_directives.rb +1 -1
- data/lib/reek/configuration/excluded_paths.rb +3 -2
- data/lib/reek/configuration/schema.rb +177 -0
- data/lib/reek/configuration/schema_validator.rb +12 -13
- data/lib/reek/context/attribute_context.rb +1 -1
- data/lib/reek/context/code_context.rb +3 -3
- data/lib/reek/context/method_context.rb +1 -1
- data/lib/reek/context/module_context.rb +4 -0
- data/lib/reek/context/refinement_context.rb +16 -0
- data/lib/reek/context/send_context.rb +7 -1
- data/lib/reek/context_builder.rb +17 -3
- data/lib/reek/documentation_link.rb +3 -5
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +2 -2
- data/lib/reek/errors/bad_detector_in_comment_error.rb +2 -2
- data/lib/reek/errors/encoding_error.rb +1 -1
- data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +2 -2
- data/lib/reek/errors/incomprehensible_source_error.rb +1 -1
- data/lib/reek/errors/legacy_comment_separator_error.rb +2 -2
- data/lib/reek/errors/syntax_error.rb +1 -1
- data/lib/reek/rake/task.rb +5 -5
- data/lib/reek/report/github_report.rb +55 -0
- data/lib/reek/report/text_report.rb +1 -1
- data/lib/reek/report.rb +7 -5
- data/lib/reek/smell_detectors/base_detector.rb +1 -1
- data/lib/reek/smell_detectors/class_variable.rb +2 -2
- data/lib/reek/smell_detectors/control_parameter_helpers/candidate.rb +6 -6
- data/lib/reek/smell_detectors/control_parameter_helpers/control_parameter_finder.rb +1 -1
- data/lib/reek/smell_detectors/data_clump.rb +1 -1
- data/lib/reek/smell_detectors/duplicate_method_call.rb +5 -5
- data/lib/reek/smell_detectors/instance_variable_assumption.rb +8 -8
- data/lib/reek/smell_detectors/nested_iterators.rb +4 -3
- data/lib/reek/smell_detectors/uncommunicative_module_name.rb +1 -1
- data/lib/reek/smell_detectors/unused_private_method.rb +3 -2
- data/lib/reek/smell_warning.rb +1 -1
- data/lib/reek/source/source_code.rb +11 -5
- data/lib/reek/source/source_locator.rb +1 -3
- data/lib/reek/spec/should_reek_of.rb +11 -9
- data/lib/reek/spec.rb +1 -1
- data/lib/reek/version.rb +2 -2
- data/reek.gemspec +33 -25
- metadata +41 -238
- data/.travis.yml +0 -40
- data/docs/API.md +0 -174
- data/docs/Attribute.md +0 -39
- data/docs/Basic-Smell-Options.md +0 -85
- data/docs/Boolean-Parameter.md +0 -54
- data/docs/Class-Variable.md +0 -40
- data/docs/Code-Smells.md +0 -39
- data/docs/Command-Line-Options.md +0 -119
- data/docs/Control-Couple.md +0 -26
- data/docs/Control-Parameter.md +0 -32
- data/docs/Data-Clump.md +0 -46
- data/docs/Duplicate-Method-Call.md +0 -264
- data/docs/Feature-Envy.md +0 -93
- data/docs/How-To-Write-New-Detectors.md +0 -132
- data/docs/How-reek-works-internally.md +0 -114
- data/docs/Instance-Variable-Assumption.md +0 -163
- data/docs/Irresponsible-Module.md +0 -47
- data/docs/Large-Class.md +0 -16
- data/docs/Long-Parameter-List.md +0 -39
- data/docs/Long-Yield-List.md +0 -37
- data/docs/Manual-Dispatch.md +0 -30
- data/docs/Missing-Safe-Method.md +0 -92
- data/docs/Module-Initialize.md +0 -62
- data/docs/Nested-Iterators.md +0 -59
- data/docs/Nil-Check.md +0 -47
- data/docs/RSpec-matchers.md +0 -129
- data/docs/Rake-Task.md +0 -66
- data/docs/Reek-4-to-Reek-5-migration.md +0 -188
- data/docs/Reek-Driven-Development.md +0 -46
- data/docs/Repeated-Conditional.md +0 -47
- data/docs/Simulated-Polymorphism.md +0 -16
- data/docs/Smell-Suppression.md +0 -96
- data/docs/Style-Guide.md +0 -19
- data/docs/Subclassed-From-Core-Class.md +0 -79
- data/docs/Too-Many-Constants.md +0 -37
- data/docs/Too-Many-Instance-Variables.md +0 -43
- data/docs/Too-Many-Methods.md +0 -56
- data/docs/Too-Many-Statements.md +0 -54
- data/docs/Uncommunicative-Method-Name.md +0 -94
- data/docs/Uncommunicative-Module-Name.md +0 -92
- data/docs/Uncommunicative-Name.md +0 -18
- data/docs/Uncommunicative-Parameter-Name.md +0 -90
- data/docs/Uncommunicative-Variable-Name.md +0 -96
- data/docs/Unused-Parameters.md +0 -28
- data/docs/Unused-Private-Method.md +0 -101
- data/docs/Utility-Function.md +0 -56
- data/docs/Versioning-Policy.md +0 -7
- data/docs/YAML-Reports.md +0 -93
- data/docs/defaults.reek.yml +0 -129
- data/docs/templates/default/docstring/html/public_api_marker.erb +0 -3
- data/docs/templates/default/docstring/setup.rb +0 -37
- data/docs/templates/default/fulldoc/html/css/common.css +0 -1
- data/features/command_line_interface/basic_usage.feature +0 -15
- data/features/command_line_interface/options.feature +0 -123
- data/features/command_line_interface/show_progress.feature +0 -33
- data/features/command_line_interface/smell_selection.feature +0 -15
- data/features/command_line_interface/smells_count.feature +0 -38
- data/features/command_line_interface/stdin.feature +0 -65
- data/features/configuration_files/accept_setting.feature +0 -87
- data/features/configuration_files/directory_specific_directives.feature +0 -274
- data/features/configuration_files/exclude_directives.feature +0 -35
- data/features/configuration_files/exclude_paths_directives.feature +0 -42
- data/features/configuration_files/masking_smells.feature +0 -94
- data/features/configuration_files/mix_accept_reject_setting.feature +0 -84
- data/features/configuration_files/reject_setting.feature +0 -89
- data/features/configuration_files/schema_validation.feature +0 -59
- data/features/configuration_files/show_configuration_file.feature +0 -44
- data/features/configuration_files/unused_private_method.feature +0 -68
- data/features/configuration_loading.feature +0 -91
- data/features/configuration_via_source_comments/erroneous_source_comments.feature +0 -68
- data/features/configuration_via_source_comments/well_formed_source_comments.feature +0 -116
- data/features/locales.feature +0 -32
- data/features/programmatic_access.feature +0 -41
- data/features/rake_task/rake_task.feature +0 -138
- data/features/reports/codeclimate.feature +0 -59
- data/features/reports/json.feature +0 -59
- data/features/reports/reports.feature +0 -219
- data/features/reports/yaml.feature +0 -52
- data/features/rspec_matcher.feature +0 -41
- data/features/samples.feature +0 -305
- data/features/step_definitions/.rubocop.yml +0 -5
- data/features/step_definitions/reek_steps.rb +0 -102
- data/features/step_definitions/sample_file_steps.rb +0 -63
- data/features/support/env.rb +0 -33
- data/features/todo_list.feature +0 -108
- data/lib/reek/configuration/schema.yml +0 -210
- data/samples/checkstyle.xml +0 -7
- data/samples/clean_source/clean.rb +0 -6
- data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +0 -29
- data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +0 -30
- data/samples/configuration/corrupt.reek +0 -1
- data/samples/configuration/empty.reek +0 -0
- data/samples/configuration/full_configuration.reek +0 -13
- data/samples/configuration/full_mask.reek +0 -6
- data/samples/configuration/home/home.reek.yml +0 -4
- data/samples/configuration/partial_mask.reek +0 -4
- data/samples/configuration/regular_configuration/.reek.yml +0 -4
- data/samples/configuration/regular_configuration/empty_sub_directory/.gitignore +0 -0
- data/samples/configuration/with_excluded_paths.reek +0 -5
- data/samples/no_config_file/.keep +0 -0
- data/samples/paths.rb +0 -5
- data/samples/smelly_source/inline.rb +0 -704
- data/samples/smelly_source/optparse.rb +0 -1788
- data/samples/smelly_source/redcloth.rb +0 -1130
- data/samples/smelly_source/ruby.rb +0 -368
- data/samples/smelly_source/smelly.rb +0 -7
- data/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +0 -5
- data/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +0 -2
- data/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +0 -6
- data/samples/source_with_exclude_paths/nested/uncommunicative_variable_name.rb +0 -6
- data/samples/source_with_hidden_directories/.hidden/hidden.rb +0 -1
- data/samples/source_with_hidden_directories/not_hidden.rb +0 -1
- data/samples/source_with_non_ruby_files/gibberish +0 -1
- data/samples/source_with_non_ruby_files/python_source.py +0 -1
- data/samples/source_with_non_ruby_files/ruby.rb +0 -6
- data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +0 -15
- data/spec/quality/documentation_spec.rb +0 -41
- data/spec/quality/reek_source_spec.rb +0 -11
- data/spec/reek/ast/node_spec.rb +0 -211
- data/spec/reek/ast/object_refs_spec.rb +0 -83
- data/spec/reek/ast/reference_collector_spec.rb +0 -47
- data/spec/reek/ast/sexp_extensions_spec.rb +0 -498
- data/spec/reek/cli/application_spec.rb +0 -168
- data/spec/reek/cli/command/report_command_spec.rb +0 -44
- data/spec/reek/cli/command/todo_list_command_spec.rb +0 -86
- data/spec/reek/cli/options_spec.rb +0 -51
- data/spec/reek/cli/silencer_spec.rb +0 -28
- data/spec/reek/code_comment_spec.rb +0 -184
- data/spec/reek/configuration/app_configuration_spec.rb +0 -195
- data/spec/reek/configuration/configuration_file_finder_spec.rb +0 -230
- data/spec/reek/configuration/default_directive_spec.rb +0 -13
- data/spec/reek/configuration/directory_directives_spec.rb +0 -122
- data/spec/reek/configuration/excluded_paths_spec.rb +0 -16
- data/spec/reek/configuration/rake_task_converter_spec.rb +0 -33
- data/spec/reek/configuration/schema_validator_spec.rb +0 -165
- data/spec/reek/context/code_context_spec.rb +0 -192
- data/spec/reek/context/ghost_context_spec.rb +0 -60
- data/spec/reek/context/method_context_spec.rb +0 -72
- data/spec/reek/context/module_context_spec.rb +0 -55
- data/spec/reek/context/root_context_spec.rb +0 -12
- data/spec/reek/context/statement_counter_spec.rb +0 -24
- data/spec/reek/context_builder_spec.rb +0 -457
- data/spec/reek/detector_repository_spec.rb +0 -22
- data/spec/reek/documentation_link_spec.rb +0 -20
- data/spec/reek/errors/base_error_spec.rb +0 -13
- data/spec/reek/examiner_spec.rb +0 -309
- data/spec/reek/logging_error_handler_spec.rb +0 -24
- data/spec/reek/rake/task_spec.rb +0 -56
- data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +0 -22
- data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +0 -126
- data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +0 -51
- data/spec/reek/report/code_climate/code_climate_report_spec.rb +0 -56
- data/spec/reek/report/html_report_spec.rb +0 -19
- data/spec/reek/report/json_report_spec.rb +0 -58
- data/spec/reek/report/location_formatter_spec.rb +0 -32
- data/spec/reek/report/progress_formatter_spec.rb +0 -68
- data/spec/reek/report/text_report_spec.rb +0 -89
- data/spec/reek/report/xml_report_spec.rb +0 -24
- data/spec/reek/report/yaml_report_spec.rb +0 -55
- data/spec/reek/report_spec.rb +0 -28
- data/spec/reek/smell_configuration_spec.rb +0 -56
- data/spec/reek/smell_detectors/attribute_spec.rb +0 -197
- data/spec/reek/smell_detectors/base_detector_spec.rb +0 -50
- data/spec/reek/smell_detectors/boolean_parameter_spec.rb +0 -93
- data/spec/reek/smell_detectors/class_variable_spec.rb +0 -106
- data/spec/reek/smell_detectors/control_parameter_spec.rb +0 -300
- data/spec/reek/smell_detectors/data_clump_spec.rb +0 -134
- data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +0 -211
- data/spec/reek/smell_detectors/feature_envy_spec.rb +0 -295
- data/spec/reek/smell_detectors/instance_variable_assumption_spec.rb +0 -96
- data/spec/reek/smell_detectors/irresponsible_module_spec.rb +0 -226
- data/spec/reek/smell_detectors/long_parameter_list_spec.rb +0 -61
- data/spec/reek/smell_detectors/long_yield_list_spec.rb +0 -49
- data/spec/reek/smell_detectors/manual_dispatch_spec.rb +0 -75
- data/spec/reek/smell_detectors/missing_safe_method_spec.rb +0 -68
- data/spec/reek/smell_detectors/module_initialize_spec.rb +0 -77
- data/spec/reek/smell_detectors/nested_iterators_spec.rb +0 -333
- data/spec/reek/smell_detectors/nil_check_spec.rb +0 -100
- data/spec/reek/smell_detectors/repeated_conditional_spec.rb +0 -100
- data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -77
- data/spec/reek/smell_detectors/too_many_constants_spec.rb +0 -144
- data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +0 -132
- data/spec/reek/smell_detectors/too_many_methods_spec.rb +0 -54
- data/spec/reek/smell_detectors/too_many_statements_spec.rb +0 -90
- data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +0 -78
- data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +0 -78
- data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +0 -147
- data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +0 -201
- data/spec/reek/smell_detectors/unused_parameters_spec.rb +0 -114
- data/spec/reek/smell_detectors/unused_private_method_spec.rb +0 -205
- data/spec/reek/smell_detectors/utility_function_spec.rb +0 -293
- data/spec/reek/smell_warning_spec.rb +0 -137
- data/spec/reek/source/source_code_spec.rb +0 -79
- data/spec/reek/source/source_locator_spec.rb +0 -166
- data/spec/reek/spec/should_reek_of_spec.rb +0 -153
- data/spec/reek/spec/should_reek_only_of_spec.rb +0 -91
- data/spec/reek/spec/should_reek_spec.rb +0 -52
- data/spec/reek/spec/smell_matcher_spec.rb +0 -87
- data/spec/reek/tree_dresser_spec.rb +0 -46
- data/spec/spec_helper.rb +0 -110
- data/tasks/configuration.rake +0 -18
- data/tasks/console.rake +0 -5
- data/tasks/reek.rake +0 -6
- data/tasks/rubocop.rake +0 -11
- data/tasks/test.rake +0 -32
- /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
|
-
*
|
|
38
|
+
* 
|
|
39
|
+
* 
|
|
39
40
|
* [](https://badge.fury.io/rb/reek)
|
|
40
|
-
* 
|
|
41
|
-
* 
|
|
41
|
+
* 
|
|
42
|
+
* 
|
|
42
43
|
* [](https://inch-ci.org/github/troessner/reek)
|
|
43
44
|
* [](https://codeclimate.com/github/troessner/reek)
|
|
44
45
|
* [](https://codebeat.co/projects/github-com-troessner-reek)
|
|
45
|
-
|
|
46
|
-
* 
|
|
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
|
-
```
|
|
59
|
+
```bash
|
|
60
60
|
gem install reek
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
and run it like this:
|
|
64
64
|
|
|
65
|
-
```
|
|
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
|
-
```
|
|
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
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
```
|
|
176
|
+
```bash
|
|
177
177
|
reek
|
|
178
178
|
```
|
|
179
179
|
|
|
180
180
|
is the exact same thing as being explicit:
|
|
181
181
|
|
|
182
|
-
```
|
|
182
|
+
```bash
|
|
183
183
|
reek .
|
|
184
184
|
```
|
|
185
185
|
|
|
186
186
|
Additionally you can pipe code to Reek like this:
|
|
187
187
|
|
|
188
|
-
```
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
```
|
|
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
|
-
|
|
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
|
|
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
|
-
```
|
|
527
|
-
|
|
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
|
|
556
|
+
Reek supports 6 output formats:
|
|
560
557
|
|
|
561
558
|
* plain text (default)
|
|
562
|
-
* HTML
|
|
563
|
-
* YAML
|
|
564
|
-
* JSON
|
|
565
|
-
* 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
|
-
```
|
|
570
|
+
```yaml
|
|
573
571
|
directories:
|
|
574
572
|
"app/controllers":
|
|
575
573
|
IrresponsibleModule:
|
data/Rakefile
CHANGED
data/bin/code_climate_reek
CHANGED
|
@@ -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/
|
|
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
|
-
|
|
51
|
-
config.fetch include_paths_key, include_paths_default
|
|
60
|
+
JSON.parse File.read(configuration_file_path)
|
|
52
61
|
else
|
|
53
|
-
|
|
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::
|
|
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
|
|
12
|
+
super
|
|
11
13
|
end
|
|
12
14
|
end
|
|
13
15
|
|
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
|
|
68
|
+
return enum_for(:each_node, target_types, ignoring) unless blk
|
|
64
69
|
|
|
65
|
-
|
|
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(
|
|
112
|
-
if target_types.include?
|
|
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(
|
|
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(
|
|
123
|
-
yield self if target_types.include?
|
|
124
|
-
return if ignoring.include?
|
|
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(
|
|
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
|
|
@@ -16,7 +16,7 @@ module Reek
|
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def args
|
|
19
|
-
children[2
|
|
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
|
-
|
|
27
|
+
return true if object_creation_call? && module_creation_receiver?
|
|
28
|
+
return true if data_definition_call? && data_definition_receiver?
|
|
29
29
|
|
|
30
|
-
|
|
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
|
-
|
|
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
|
data/lib/reek/cli/options.rb
CHANGED
|
@@ -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
|
-
|
|
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
|