reek 4.8.1 → 5.0.2
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 +5 -5
- data/.rubocop.yml +17 -3
- data/.simplecov +1 -0
- data/.travis.yml +0 -5
- data/.yardopts +1 -1
- data/CHANGELOG.md +44 -0
- data/Gemfile +1 -1
- data/README.md +115 -100
- data/Rakefile +16 -3
- data/bin/reek +1 -3
- data/docs/API.md +2 -9
- data/docs/Basic-Smell-Options.md +51 -11
- data/docs/Code-Smells.md +1 -1
- data/docs/Command-Line-Options.md +14 -4
- data/docs/Duplicate-Method-Call.md +49 -1
- data/docs/Feature-Envy.md +44 -0
- data/docs/How-To-Write-New-Detectors.md +2 -3
- data/docs/Instance-Variable-Assumption.md +1 -1
- data/docs/{Prima-Donna-Method.md → Missing-Safe-Method.md} +11 -9
- data/docs/Rake-Task.md +1 -1
- data/docs/Reek-4-to-Reek-5-migration.md +193 -0
- data/docs/Reek-Driven-Development.md +1 -1
- data/docs/Uncommunicative-Method-Name.md +45 -6
- data/docs/Uncommunicative-Module-Name.md +49 -7
- data/docs/Uncommunicative-Parameter-Name.md +43 -5
- data/docs/Uncommunicative-Variable-Name.md +73 -2
- data/docs/Unused-Private-Method.md +1 -1
- data/docs/defaults.reek.yml +129 -0
- data/docs/yard_plugin.rb +1 -0
- data/features/command_line_interface/basic_usage.feature +2 -2
- data/features/command_line_interface/options.feature +46 -4
- data/features/command_line_interface/show_progress.feature +4 -4
- data/features/command_line_interface/smell_selection.feature +1 -1
- data/features/command_line_interface/smells_count.feature +6 -6
- data/features/command_line_interface/stdin.feature +30 -8
- data/features/configuration_files/accept_setting.feature +45 -28
- data/features/configuration_files/directory_specific_directives.feature +78 -73
- data/features/configuration_files/exclude_directives.feature +11 -10
- data/features/configuration_files/exclude_paths_directives.feature +4 -4
- data/features/configuration_files/masking_smells.feature +38 -9
- data/features/configuration_files/mix_accept_reject_setting.feature +31 -28
- data/features/configuration_files/reject_setting.feature +52 -41
- data/features/configuration_files/schema_validation.feature +59 -0
- data/features/configuration_files/unused_private_method.feature +18 -16
- data/features/configuration_loading.feature +53 -10
- data/features/configuration_via_source_comments/erroneous_source_comments.feature +2 -2
- data/features/configuration_via_source_comments/well_formed_source_comments.feature +2 -2
- data/features/locales.feature +2 -2
- data/features/rake_task/rake_task.feature +15 -15
- data/features/reports/json.feature +3 -3
- data/features/reports/reports.feature +34 -34
- data/features/reports/yaml.feature +3 -3
- data/features/rspec_matcher.feature +9 -1
- data/features/samples.feature +287 -287
- data/features/step_definitions/reek_steps.rb +4 -0
- data/features/step_definitions/sample_file_steps.rb +9 -4
- data/features/support/env.rb +2 -2
- data/features/todo_list.feature +26 -23
- data/lib/reek/ast/node.rb +3 -6
- data/lib/reek/ast/object_refs.rb +1 -1
- data/lib/reek/ast/sexp_extensions/case.rb +3 -1
- data/lib/reek/ast/sexp_extensions/if.rb +2 -2
- data/lib/reek/ast/sexp_extensions/logical_operators.rb +1 -1
- data/lib/reek/ast/sexp_extensions/methods.rb +1 -1
- data/lib/reek/cli/application.rb +4 -3
- data/lib/reek/cli/command/report_command.rb +1 -2
- data/lib/reek/cli/command/todo_list_command.rb +4 -2
- data/lib/reek/cli/options.rb +29 -14
- data/lib/reek/cli/silencer.rb +14 -3
- data/lib/reek/code_comment.rb +14 -16
- data/lib/reek/configuration/app_configuration.rb +32 -28
- data/lib/reek/configuration/configuration_converter.rb +110 -0
- data/lib/reek/configuration/configuration_file_finder.rb +15 -40
- data/lib/reek/configuration/configuration_validator.rb +12 -23
- data/lib/reek/configuration/default_directive.rb +17 -3
- data/lib/reek/configuration/directory_directives.rb +17 -11
- data/lib/reek/configuration/excluded_paths.rb +1 -1
- data/lib/reek/configuration/rake_task_converter.rb +29 -0
- data/lib/reek/configuration/schema.yml +210 -0
- data/lib/reek/configuration/schema_validator.rb +38 -0
- data/lib/reek/context/attribute_context.rb +1 -1
- data/lib/reek/context/code_context.rb +4 -4
- data/lib/reek/context/method_context.rb +2 -2
- data/lib/reek/context/module_context.rb +1 -1
- data/lib/reek/context_builder.rb +9 -9
- data/lib/reek/detector_repository.rb +6 -0
- data/lib/reek/documentation_link.rb +28 -0
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +4 -3
- data/lib/reek/errors/bad_detector_in_comment_error.rb +4 -3
- data/lib/reek/errors/config_file_error.rb +11 -0
- data/lib/reek/errors/encoding_error.rb +2 -2
- data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +4 -3
- data/lib/reek/errors/incomprehensible_source_error.rb +2 -2
- data/lib/reek/errors/syntax_error.rb +41 -0
- data/lib/reek/examiner.rb +9 -19
- data/lib/reek/rake/task.rb +3 -3
- data/lib/reek/report/base_report.rb +8 -12
- data/lib/reek/report/code_climate/code_climate_configuration.yml +6 -10
- data/lib/reek/report/documentation_link_warning_formatter.rb +17 -0
- data/lib/reek/report/heading_formatter.rb +54 -0
- data/lib/reek/report/json_report.rb +1 -1
- data/lib/reek/report/location_formatter.rb +40 -0
- data/lib/reek/report/progress_formatter.rb +79 -0
- data/lib/reek/report/simple_warning_formatter.rb +34 -0
- data/lib/reek/report/text_report.rb +1 -2
- data/lib/reek/report/xml_report.rb +3 -3
- data/lib/reek/report/yaml_report.rb +1 -1
- data/lib/reek/report.rb +15 -10
- data/lib/reek/smell_configuration.rb +2 -2
- data/lib/reek/smell_detectors/attribute.rb +0 -1
- data/lib/reek/smell_detectors/base_detector.rb +8 -11
- data/lib/reek/smell_detectors/boolean_parameter.rb +0 -1
- data/lib/reek/smell_detectors/class_variable.rb +0 -1
- data/lib/reek/smell_detectors/control_parameter.rb +17 -32
- data/lib/reek/smell_detectors/data_clump.rb +3 -4
- data/lib/reek/smell_detectors/duplicate_method_call.rb +5 -6
- data/lib/reek/smell_detectors/feature_envy.rb +1 -1
- data/lib/reek/smell_detectors/instance_variable_assumption.rb +0 -1
- data/lib/reek/smell_detectors/irresponsible_module.rb +0 -1
- data/lib/reek/smell_detectors/long_parameter_list.rb +1 -2
- data/lib/reek/smell_detectors/long_yield_list.rb +2 -3
- data/lib/reek/smell_detectors/manual_dispatch.rb +2 -2
- data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +6 -7
- data/lib/reek/smell_detectors/module_initialize.rb +0 -1
- data/lib/reek/smell_detectors/nested_iterators.rb +4 -5
- data/lib/reek/smell_detectors/nil_check.rb +0 -1
- data/lib/reek/smell_detectors/repeated_conditional.rb +3 -4
- data/lib/reek/smell_detectors/subclassed_from_core_class.rb +0 -1
- data/lib/reek/smell_detectors/too_many_constants.rb +1 -2
- data/lib/reek/smell_detectors/too_many_instance_variables.rb +1 -2
- data/lib/reek/smell_detectors/too_many_methods.rb +1 -2
- data/lib/reek/smell_detectors/too_many_statements.rb +1 -2
- data/lib/reek/smell_detectors/uncommunicative_method_name.rb +2 -3
- data/lib/reek/smell_detectors/uncommunicative_module_name.rb +2 -3
- data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +2 -3
- data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +4 -5
- data/lib/reek/smell_detectors/unused_parameters.rb +0 -1
- data/lib/reek/smell_detectors/unused_private_method.rb +0 -1
- data/lib/reek/smell_detectors/utility_function.rb +1 -2
- data/lib/reek/smell_detectors.rb +1 -2
- data/lib/reek/smell_warning.rb +15 -8
- data/lib/reek/source/source_code.rb +40 -55
- data/lib/reek/source/source_locator.rb +7 -7
- data/lib/reek/spec/should_reek.rb +2 -2
- data/lib/reek/spec/should_reek_of.rb +9 -16
- data/lib/reek/spec/should_reek_only_of.rb +4 -4
- data/lib/reek/spec.rb +6 -6
- data/lib/reek/tree_dresser.rb +5 -5
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +4 -4
- data/samples/checkstyle.xml +1 -1
- data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +29 -0
- data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +30 -0
- data/samples/configuration/full_configuration.reek +8 -4
- data/samples/configuration/full_mask.reek +5 -4
- data/samples/configuration/partial_mask.reek +3 -2
- data/samples/configuration/regular_configuration/.reek.yml +4 -0
- data/samples/paths.rb +5 -4
- data/samples/source_with_hidden_directories/.hidden/hidden.rb +1 -0
- data/samples/source_with_hidden_directories/not_hidden.rb +1 -0
- data/spec/reek/ast/node_spec.rb +5 -5
- data/spec/reek/cli/application_spec.rb +18 -4
- data/spec/reek/cli/command/todo_list_command_spec.rb +4 -2
- data/spec/reek/cli/silencer_spec.rb +28 -0
- data/spec/reek/code_comment_spec.rb +0 -7
- data/spec/reek/configuration/app_configuration_spec.rb +44 -31
- data/spec/reek/configuration/configuration_file_finder_spec.rb +141 -49
- data/spec/reek/configuration/default_directive_spec.rb +1 -1
- data/spec/reek/configuration/directory_directives_spec.rb +3 -4
- data/spec/reek/configuration/excluded_paths_spec.rb +5 -5
- data/spec/reek/configuration/rake_task_converter_spec.rb +33 -0
- data/spec/reek/configuration/schema_validator_spec.rb +165 -0
- data/spec/reek/context/code_context_spec.rb +1 -1
- data/spec/reek/documentation_link_spec.rb +20 -0
- data/spec/reek/examiner_spec.rb +28 -1
- data/spec/reek/report/json_report_spec.rb +13 -46
- data/spec/reek/report/{formatter/location_formatter_spec.rb → location_formatter_spec.rb} +5 -5
- data/spec/reek/report/{formatter/progress_formatter_spec.rb → progress_formatter_spec.rb} +4 -4
- data/spec/reek/report/text_report_spec.rb +4 -4
- data/spec/reek/report/xml_report_spec.rb +1 -1
- data/spec/reek/report/yaml_report_spec.rb +9 -38
- data/spec/reek/report_spec.rb +3 -3
- data/spec/reek/smell_detectors/feature_envy_spec.rb +47 -2
- data/spec/reek/smell_detectors/{prima_donna_method_spec.rb → missing_safe_method_spec.rb} +9 -9
- data/spec/reek/smell_detectors/too_many_constants_spec.rb +3 -3
- data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +1 -1
- data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +6 -6
- data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +6 -4
- data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +6 -4
- data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +6 -6
- data/spec/reek/smell_detectors/unused_private_method_spec.rb +1 -1
- data/spec/reek/smell_warning_spec.rb +4 -0
- data/spec/reek/source/source_code_spec.rb +16 -22
- data/spec/reek/source/source_locator_spec.rb +11 -11
- data/spec/reek/spec/should_reek_of_spec.rb +0 -4
- data/spec/reek/spec/should_reek_only_of_spec.rb +2 -2
- data/spec/reek/spec/should_reek_spec.rb +1 -1
- data/spec/reek/tree_dresser_spec.rb +2 -6
- data/spec/spec_helper.rb +3 -5
- data/tasks/configuration.rake +8 -5
- metadata +64 -36
- data/.codeclimate.yml +0 -21
- data/defaults.reek +0 -131
- data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
- data/lib/reek/report/formatter/heading_formatter.rb +0 -52
- data/lib/reek/report/formatter/location_formatter.rb +0 -42
- data/lib/reek/report/formatter/progress_formatter.rb +0 -81
- data/lib/reek/report/formatter/simple_warning_formatter.rb +0 -35
- data/lib/reek/report/formatter/wiki_link_warning_formatter.rb +0 -36
- data/lib/reek/report/formatter.rb +0 -33
- data/lib/reek/smell_detectors/syntax.rb +0 -37
- data/samples/configuration/non_public_modifiers_mask.reek +0 -3
- data/samples/smelly_with_inline_mask.rb +0 -8
- data/samples/smelly_with_modifiers.rb +0 -12
- data/samples/source_with_hidden_directories/.hidden/uncommunicative_method_name.rb +0 -5
- data/samples/source_with_non_ruby_files/uncommunicative_parameter_name.rb +0 -6
- data/spec/reek/smell_detectors/syntax_spec.rb +0 -17
- /data/{samples/configuration/more_than_one_configuration_file/regular.reek → .reek.yml} +0 -0
- /data/samples/{clean.rb → clean_source/clean.rb} +0 -0
- /data/samples/{exceptions.reek → configuration/home/home.reek.yml} +0 -0
- /data/samples/configuration/{more_than_one_configuration_file/todo.reek → regular_configuration/empty_sub_directory/.gitignore} +0 -0
- /data/samples/{configuration/single_configuration_file/.reek → no_config_file/.keep} +0 -0
- /data/samples/{inline.rb → smelly_source/inline.rb} +0 -0
- /data/samples/{optparse.rb → smelly_source/optparse.rb} +0 -0
- /data/samples/{redcloth.rb → smelly_source/redcloth.rb} +0 -0
- /data/samples/{smelly.rb → smelly_source/smelly.rb} +0 -0
- /data/samples/{source_with_hidden_directories/uncommunicative_parameter_name.rb → source_with_non_ruby_files/ruby.rb} +0 -0
|
@@ -12,6 +12,16 @@ reek -h
|
|
|
12
12
|
|
|
13
13
|
for details.
|
|
14
14
|
|
|
15
|
+
## Telling Reek to use a specific configuration file
|
|
16
|
+
|
|
17
|
+
In case your configuration file is not in the standard location (that would be your project directory or
|
|
18
|
+
whatever directory you're running Reek from) you can specify a configuration file with the `-c` option
|
|
19
|
+
like this:
|
|
20
|
+
|
|
21
|
+
```Bash
|
|
22
|
+
reek -c /somewhere/on/your/filesystem/reek_config.yml lib/
|
|
23
|
+
```
|
|
24
|
+
|
|
15
25
|
## Telling Reek Which Code to Check
|
|
16
26
|
|
|
17
27
|
Probably the most standard use case would be to check all Ruby files in the lib directory:
|
|
@@ -91,10 +101,10 @@ mess.rb -- 2 warnings:
|
|
|
91
101
|
[2]:x has the name 'x' (UncommunicativeMethodName)
|
|
92
102
|
```
|
|
93
103
|
|
|
94
|
-
### Enable the
|
|
104
|
+
### Enable the verbose mode
|
|
95
105
|
|
|
96
|
-
_reek_ has a
|
|
97
|
-
This mode can be enabled via the "-U" or "--
|
|
106
|
+
_reek_ has a verbose mode which you might find helpful as a beginner. "verbose" just means that behind each warning a helpful link will be displayed which leads directly to the corresponding _reek_ documentation page.
|
|
107
|
+
This mode can be enabled via the "-U" or "--documentation" flag.
|
|
98
108
|
|
|
99
109
|
So for instance, if your test file would smell of _ClassVariable_, this is what the _reek_ output would look like:
|
|
100
110
|
|
|
@@ -103,7 +113,7 @@ reek -U test.rb
|
|
|
103
113
|
```
|
|
104
114
|
```
|
|
105
115
|
test.rb -- 1 warning:
|
|
106
|
-
[2]:Dummy declares the class variable @@class_variable (ClassVariable) [https://github.com/troessner/reek/
|
|
116
|
+
[2]:Dummy declares the class variable @@class_variable (ClassVariable) [https://github.com/troessner/reek/blob/master/docs/Class-Variable.md]
|
|
107
117
|
```
|
|
108
118
|
|
|
109
119
|
Note the link at the end.
|
|
@@ -42,7 +42,55 @@ The approach you take will depend on balancing other factors in your code.
|
|
|
42
42
|
|
|
43
43
|
## Current support in Reek
|
|
44
44
|
|
|
45
|
-
Reek's Duplicate Method Call detector checks for repeated identical method calls within
|
|
45
|
+
Reek's Duplicate Method Call detector checks for repeated identical method calls within
|
|
46
|
+
any one method definition. This is intended to complement the checks performed by tools
|
|
47
|
+
such as [Flay](http://ruby.sadi.st/Flay.html) and [Simian](http://www.redhillconsulting.com.au/products/simian/).
|
|
48
|
+
|
|
49
|
+
## Edge cases
|
|
50
|
+
|
|
51
|
+
Be aware that there are some edge cases like this code:
|
|
52
|
+
|
|
53
|
+
```Ruby
|
|
54
|
+
class Foo
|
|
55
|
+
def bar(switch)
|
|
56
|
+
case switch
|
|
57
|
+
when :a
|
|
58
|
+
->(arg) { arg.call_me(:maybe); do_something }
|
|
59
|
+
when :b
|
|
60
|
+
->(arg) { arg.call_me(:maybe); do_something_else }
|
|
61
|
+
when :c
|
|
62
|
+
->(arg) { arg.call_me(:maybe); do_something_different }
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Reek cannot reliably detect that each call's receiver is a different arg and will report:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
[5, 7, 9]:DuplicateMethodCall: Foo#bar calls 'arg.call_me(:maybe)' 3 times
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If you're running into this problem you can disable this smell detector for this method either via
|
|
75
|
+
configuration:
|
|
76
|
+
|
|
77
|
+
```Yaml
|
|
78
|
+
---
|
|
79
|
+
DuplicateMethodCall:
|
|
80
|
+
exclude:
|
|
81
|
+
- 'Foo#bar'
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
or via source code comment:
|
|
85
|
+
|
|
86
|
+
```Ruby
|
|
87
|
+
class Foo
|
|
88
|
+
# :reek:DuplicateMethodCall
|
|
89
|
+
def bar(switch)
|
|
90
|
+
# ....
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
```
|
|
46
94
|
|
|
47
95
|
## Configuration
|
|
48
96
|
|
data/docs/Feature-Envy.md
CHANGED
|
@@ -40,6 +40,50 @@ belongs to the Item class, not the Warehouse.
|
|
|
40
40
|
|
|
41
41
|
_Feature Envy_ reports any method that refers to self less often than it refers to (ie. send messages to) some other object.
|
|
42
42
|
|
|
43
|
+
## Edge cases
|
|
44
|
+
|
|
45
|
+
Be aware that there are some edge cases like this code:
|
|
46
|
+
|
|
47
|
+
```Ruby
|
|
48
|
+
class Foo
|
|
49
|
+
def initialize
|
|
50
|
+
@map = {
|
|
51
|
+
a: ->(arg) { arg.css('table') },
|
|
52
|
+
b: ->(arg) { arg.css('div') },
|
|
53
|
+
c: ->(arg) { arg.css('span') }
|
|
54
|
+
}
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Reek cannot reliably detect that each call's receiver is a different arg and will report:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
[4, 5, 6]:FeatureEnvy: Foo#initialize refers to 'arg' more than self (maybe move it to another class?)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
If you're running into this problem you can disable this smell detector for this method either via
|
|
66
|
+
configuration:
|
|
67
|
+
|
|
68
|
+
```Yaml
|
|
69
|
+
---
|
|
70
|
+
FeatureEnvy:
|
|
71
|
+
exclude:
|
|
72
|
+
- 'Foo#bar'
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
or via source code comment:
|
|
76
|
+
|
|
77
|
+
```Ruby
|
|
78
|
+
class Foo
|
|
79
|
+
# :reek:FeatureEnvy
|
|
80
|
+
def initialize
|
|
81
|
+
@map = {
|
|
82
|
+
# ....
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
```
|
|
86
|
+
|
|
43
87
|
## Differences to _Utility Function_
|
|
44
88
|
|
|
45
89
|
_Feature Envy_ is only triggered if there are some references to self and _[Utility Function](Utility-Function.md)_ is triggered if there are no references to self.
|
|
@@ -41,7 +41,6 @@ module Reek
|
|
|
41
41
|
# "smell_warning" is defined in BaseDetector and should be used by you
|
|
42
42
|
# to construct smell warnings
|
|
43
43
|
smell_warning(
|
|
44
|
-
context: context,
|
|
45
44
|
lines: [], # lines on which the smell was detected
|
|
46
45
|
message: "...", # the message that is printed on STDOUT
|
|
47
46
|
# whatever you interpolate into the "message" should go into
|
|
@@ -62,7 +61,7 @@ end
|
|
|
62
61
|
|
|
63
62
|
For your detector to be properly loaded you need to require it in `lib/reek/smell_detectors.rb` as well.
|
|
64
63
|
|
|
65
|
-
### defaults.reek
|
|
64
|
+
### defaults.reek.yml
|
|
66
65
|
|
|
67
66
|
After you ran
|
|
68
67
|
|
|
@@ -70,7 +69,7 @@ After you ran
|
|
|
70
69
|
bundle exec rake
|
|
71
70
|
```
|
|
72
71
|
|
|
73
|
-
for the first time with your shiny new detector in place the `defaults.reek`
|
|
72
|
+
for the first time with your shiny new detector in place the `docs/defaults.reek.yml`
|
|
74
73
|
file should have been updated automatically. Make sure you don't forget to check
|
|
75
74
|
in those changes as well.
|
|
76
75
|
|
|
@@ -61,7 +61,7 @@ end
|
|
|
61
61
|
would report:
|
|
62
62
|
|
|
63
63
|
```Bash
|
|
64
|
-
[1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar
|
|
64
|
+
[1]:InstanceVariableAssumption: Dummy assumes too much for instance variable @ivar
|
|
65
65
|
```
|
|
66
66
|
|
|
67
67
|
Note that this example would trigger this smell warning as well:
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Missing Safe Method
|
|
2
2
|
|
|
3
3
|
## Introduction
|
|
4
4
|
|
|
5
|
-
Candidate methods for the
|
|
5
|
+
Candidate methods for the _Missing Safe Method_ smell are methods whose names
|
|
6
6
|
end with an exclamation mark.
|
|
7
7
|
|
|
8
8
|
An exclamation mark in method names means (the explanation below is taken from
|
|
@@ -13,14 +13,16 @@ An exclamation mark in method names means (the explanation below is taken from
|
|
|
13
13
|
> equivalent method, with the same name minus the !. “Danger” is relative; the
|
|
14
14
|
> ! doesn’t mean anything at all unless the method name it’s in corresponds to
|
|
15
15
|
> a similar but bang-less method name.
|
|
16
|
-
>
|
|
16
|
+
>
|
|
17
17
|
> So, for example, gsub! is the dangerous version of gsub. exit! is the
|
|
18
18
|
> dangerous version of exit. flatten! is the dangerous version of flatten. And
|
|
19
19
|
> so forth.
|
|
20
20
|
|
|
21
|
-
Such a method is called
|
|
21
|
+
Such a method is called _Missing Safe Method_ if and only if the non-bang
|
|
22
22
|
version does not exist and this method is reported as a smell.
|
|
23
23
|
|
|
24
|
+
Missing Safe Method was formerly known as Prima Donna Method.
|
|
25
|
+
|
|
24
26
|
## Example
|
|
25
27
|
|
|
26
28
|
Given
|
|
@@ -33,7 +35,7 @@ class C
|
|
|
33
35
|
end
|
|
34
36
|
```
|
|
35
37
|
|
|
36
|
-
Reek would report the
|
|
38
|
+
Reek would report the _Missing Safe Method_ smell for `bar!`, but not for `foo!`.
|
|
37
39
|
|
|
38
40
|
Reek reports this smell only in a class context, not in a module context in order to allow perfectly legit code like this:
|
|
39
41
|
|
|
@@ -55,12 +57,12 @@ class Daughter < Parent
|
|
|
55
57
|
end
|
|
56
58
|
```
|
|
57
59
|
|
|
58
|
-
In this example, Reek would not report the
|
|
60
|
+
In this example, Reek would not report the _Missing Safe Method_ smell for the
|
|
59
61
|
method `foo` of the `Dangerous` module.
|
|
60
62
|
|
|
61
63
|
## Configuration
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
_Missing Safe Method_ offers the [Basic Smell Options](Basic-Smell-Options.md).
|
|
64
66
|
|
|
65
67
|
## Example configuration via source comment
|
|
66
68
|
|
|
@@ -77,12 +79,12 @@ This would report:
|
|
|
77
79
|
|
|
78
80
|
>>
|
|
79
81
|
ruby.rb -- 1 warning:
|
|
80
|
-
[1]:
|
|
82
|
+
[1]:MissingSafeMethod: Alfa has missing safe method 'bravo!'
|
|
81
83
|
|
|
82
84
|
If you want to suppress this warning you can do this via source comment like this:
|
|
83
85
|
|
|
84
86
|
```Ruby
|
|
85
|
-
# :reek:
|
|
87
|
+
# :reek:MissingSafeMethod { exclude: [ bravo! ] }
|
|
86
88
|
class Alfa
|
|
87
89
|
def bravo!
|
|
88
90
|
end
|
data/docs/Rake-Task.md
CHANGED
|
@@ -33,7 +33,7 @@ An more sophisticated rake task that would make use of all available configurati
|
|
|
33
33
|
```Ruby
|
|
34
34
|
Reek::Rake::Task.new do |t|
|
|
35
35
|
t.name = 'custom_rake' # Whatever name you want. Defaults to "reek".
|
|
36
|
-
t.config_file = 'config
|
|
36
|
+
t.config_file = 'config/.reek.yml' # Defaults to nothing.
|
|
37
37
|
t.source_files = 'vendor/**/*.rb' # Glob pattern to match source files. Defaults to lib/**/*.rb
|
|
38
38
|
t.reek_opts = '-U' # Defaults to ''. You can pass all the options here in that are shown by "reek -h"
|
|
39
39
|
t.fail_on_error = false # Defaults to true
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
## Reek 4 to Reek 5 migration
|
|
2
|
+
|
|
3
|
+
### Schema validation
|
|
4
|
+
|
|
5
|
+
Reek now uses a schema to validate your configuration against on start up and will faily loudly in
|
|
6
|
+
case you misspelled an option or used the wrong data type for a value like this:
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
Error: We found some problems with your configuration file: [/detectors/DetectorWithTypo] key 'DetectorWithTypo:' is undefined.
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Obviously this might affect existing configuration files that until now contained an error nobody noticed.
|
|
13
|
+
|
|
14
|
+
### Scoping detectors under `detectors`
|
|
15
|
+
|
|
16
|
+
In Reek 4 you could just configure your detectors on top level like this:
|
|
17
|
+
|
|
18
|
+
```yaml
|
|
19
|
+
UncommunicativeMethodName:
|
|
20
|
+
accept:
|
|
21
|
+
- foobar
|
|
22
|
+
UnusedPrivateMethod:
|
|
23
|
+
exclude:
|
|
24
|
+
- app/controllers
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
In Reek 5 you have to scope your detector configurations under the `detectors` key:
|
|
28
|
+
|
|
29
|
+
```yaml
|
|
30
|
+
detectors:
|
|
31
|
+
UncommunicativeMethodName:
|
|
32
|
+
accept:
|
|
33
|
+
- foobar
|
|
34
|
+
UnusedPrivateMethod:
|
|
35
|
+
exclude:
|
|
36
|
+
- app/controllers
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### Move directory directives under a special key
|
|
40
|
+
|
|
41
|
+
In Reek 4 you could apply directory specific directives like this:
|
|
42
|
+
|
|
43
|
+
```Yaml
|
|
44
|
+
---
|
|
45
|
+
"web_app/app/controllers":
|
|
46
|
+
NestedIterators:
|
|
47
|
+
enabled: false
|
|
48
|
+
"web_app/app/helpers":
|
|
49
|
+
UtilityFunction:
|
|
50
|
+
enabled: false
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
which was nice and easy but also quite messy. With Reek 5 you'll have to scope this under a `directories`
|
|
54
|
+
key like this:
|
|
55
|
+
|
|
56
|
+
```Yaml
|
|
57
|
+
---
|
|
58
|
+
directories:
|
|
59
|
+
"web_app/app/controllers":
|
|
60
|
+
NestedIterators:
|
|
61
|
+
enabled: false
|
|
62
|
+
"web_app/app/helpers":
|
|
63
|
+
UtilityFunction:
|
|
64
|
+
enabled: false
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### No more regular expressions in Reeks configuration
|
|
68
|
+
|
|
69
|
+
In Reek 4 you could pass regular expressions to the `accept` or `reject` settings of
|
|
70
|
+
|
|
71
|
+
* [Uncommunicative Method Name](Uncommunicative-Method-Name.md)
|
|
72
|
+
* [Uncommunicative Module Name](Uncommunicative-Module-Name.md)
|
|
73
|
+
* [Uncommunicative Parameter Name](Uncommunicative-Parameter-Name.md)
|
|
74
|
+
* [Uncommunicative Variable Name](Uncommunicative-Variable-Name.md)
|
|
75
|
+
|
|
76
|
+
and to the `exclude` settings which are part of our [Basic Smell Options](docs/Basic-Smell-Options.md).
|
|
77
|
+
|
|
78
|
+
This means that this configuration was perfectly valid:
|
|
79
|
+
|
|
80
|
+
```yaml
|
|
81
|
+
detectors:
|
|
82
|
+
UncommunicativeMethodName:
|
|
83
|
+
accept:
|
|
84
|
+
- !ruby/regexp /foobar/
|
|
85
|
+
UnusedPrivateMethod:
|
|
86
|
+
exclude:
|
|
87
|
+
- !ruby/regexp /i am(.*)unused/
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Support for this has been scrapped with Reek 5 to make the Reek configuration more yaml standard compliant.
|
|
91
|
+
You can still pass in regexes, you just have to wrap them into a string using a forward slash at the
|
|
92
|
+
beginning and at the end of the string like this:
|
|
93
|
+
|
|
94
|
+
```Yaml
|
|
95
|
+
---
|
|
96
|
+
UncommunicativeMethodName:
|
|
97
|
+
accept:
|
|
98
|
+
- "/^foobar$/"
|
|
99
|
+
UnusedPrivateMethod:
|
|
100
|
+
exclude:
|
|
101
|
+
- "/i am(.*)unused/"
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Everything within the forward slashes will be loaded as a regex.
|
|
105
|
+
|
|
106
|
+
### No more single item shortcuts for list items
|
|
107
|
+
|
|
108
|
+
You cant use a configuration option that is supposed to be a list with a single element like this anymore:
|
|
109
|
+
|
|
110
|
+
```Yaml
|
|
111
|
+
---
|
|
112
|
+
UncommunicativeMethodName:
|
|
113
|
+
accept: foobar
|
|
114
|
+
UnusedPrivateMethod:
|
|
115
|
+
exclude: omg
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
You'll have to use a proper list here like this:
|
|
119
|
+
|
|
120
|
+
```Yaml
|
|
121
|
+
---
|
|
122
|
+
UncommunicativeMethodName:
|
|
123
|
+
accept:
|
|
124
|
+
- foobar
|
|
125
|
+
UnusedPrivateMethod:
|
|
126
|
+
exclude:
|
|
127
|
+
- omg
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Failing on syntax errors in source files
|
|
131
|
+
|
|
132
|
+
Previously Reek would just continue on syntax errors in source files which might have been convenient but
|
|
133
|
+
not necessarily fitting for a tool that's all about code quality. With Reek 5, Reek will fail hard on
|
|
134
|
+
invalid source files.
|
|
135
|
+
|
|
136
|
+
### API changes
|
|
137
|
+
|
|
138
|
+
This is something that will only affect very advanced users. In case you have no idea what this might be about
|
|
139
|
+
you can just skip it or check out our [Developer API](docs/API.md).
|
|
140
|
+
|
|
141
|
+
#### Allow only detector names in configuration hash
|
|
142
|
+
|
|
143
|
+
In Reek 4 you could build your configuration like this:
|
|
144
|
+
|
|
145
|
+
```ruby
|
|
146
|
+
config_hash = { Reek::SmellDetectors::IrresponsibleModule => { 'enabled' => false } }
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
or like this:
|
|
150
|
+
|
|
151
|
+
```ruby
|
|
152
|
+
config_hash = { 'IrresponsibleModule' => { 'enabled' => false } }
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Starting with Reek 5, the first way is not working anymore and the latter one is what you'll have to use.
|
|
156
|
+
|
|
157
|
+
#### Do not accept a class as parameter for reek_of
|
|
158
|
+
|
|
159
|
+
In the same vein as the change above you also can't use fully qualified detector names like this:
|
|
160
|
+
|
|
161
|
+
```Ruby
|
|
162
|
+
reek_of(Reek::SmellDetectors::DuplicateMethodCall)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
The only supported way now is either as symbol or string:
|
|
166
|
+
|
|
167
|
+
```Ruby
|
|
168
|
+
reek_of(:DuplicateMethodCall)
|
|
169
|
+
reek_of('DuplicateMethodCall')
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Smaller changes
|
|
173
|
+
|
|
174
|
+
* `PrimaDonnaMethod` has been given the better name `MissingSafeMethod`
|
|
175
|
+
* `wiki-links` flag has been renamed to `documentation` flag
|
|
176
|
+
* Reek assumes the default configuration file to be named ".reek.yml" and will ignore all other files. You can
|
|
177
|
+
still use any name you want though by passing in a name via the `-c` flag
|
|
178
|
+
* We have dropped the legacy code comment separator ":" at the end of a detector name. If you wanted to configure
|
|
179
|
+
a smell detector via comment before this release you had to use g like this:
|
|
180
|
+
|
|
181
|
+
```
|
|
182
|
+
# :reek:UnusedPrivateMethod: { exclude: [ bravo ] }
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Mind the ":" at the end of "UnusedPrivateMethod". This syntax is disallowed with Reek 5 - you have to drop the ":"
|
|
186
|
+
at the end now like this:
|
|
187
|
+
|
|
188
|
+
```
|
|
189
|
+
# :reek:UnusedPrivateMethod { exclude: [ bravo ] }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
* We have dropped support for Ruby 2.1 and 2.2 since they are officially not supported by the Ruby core team anymore
|
|
193
|
+
|
|
@@ -14,7 +14,7 @@ Reek::Rake::Task.new do |t|
|
|
|
14
14
|
end
|
|
15
15
|
```
|
|
16
16
|
|
|
17
|
-
Now the command `reek` will run Reek on your source code (and in this case, it fails if it finds any smells). For more detailed information about Reek's integration with Rake, see [Rake Task](Rake-Task.md)
|
|
17
|
+
Now the command `reek` will run Reek on your source code (and in this case, it fails if it finds any smells). For more detailed information about Reek's integration with Rake, see [Rake Task](Rake-Task.md).
|
|
18
18
|
|
|
19
19
|
## reek/spec
|
|
20
20
|
|
|
@@ -21,8 +21,8 @@ Reek's _Uncommunicative Method Name_ detector supports the
|
|
|
21
21
|
|
|
22
22
|
| Option | Value | Effect |
|
|
23
23
|
| ---------------|-------------|---------|
|
|
24
|
-
| `reject` | array of
|
|
25
|
-
| `accept` | array of
|
|
24
|
+
| `reject` | array of strings | The set of names that Reek uses to check for bad names. Defaults to single-letter names, names ending with a number or names containing upper case letters. |
|
|
25
|
+
| `accept` | array of strings | The set of names that Reek will accept (and not report) even if they match one of the `reject` expressions. |
|
|
26
26
|
|
|
27
27
|
An example configuration could look like this:
|
|
28
28
|
|
|
@@ -30,13 +30,15 @@ An example configuration could look like this:
|
|
|
30
30
|
---
|
|
31
31
|
UncommunicativeMethodName:
|
|
32
32
|
accept:
|
|
33
|
-
-
|
|
33
|
+
- x
|
|
34
34
|
- meth1
|
|
35
35
|
reject:
|
|
36
|
-
-
|
|
36
|
+
- helper
|
|
37
37
|
- foobar
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
+
Reek will convert whatever you give it as a string to the corresponding regex, so "foobar" from above will be converted to /foobar/ internally.
|
|
41
|
+
|
|
40
42
|
Applying a configuration to a source file like this:
|
|
41
43
|
|
|
42
44
|
```Ruby
|
|
@@ -50,6 +52,43 @@ Reek would report:
|
|
|
50
52
|
|
|
51
53
|
```
|
|
52
54
|
smelly.rb -- 2 warnings:
|
|
53
|
-
[4]:UncommunicativeMethodName: awesome_helper has the name 'awesome_helper'
|
|
54
|
-
[3]:UncommunicativeMethodName: foobar has the name 'foobar'
|
|
55
|
+
[4]:UncommunicativeMethodName: awesome_helper has the name 'awesome_helper'
|
|
56
|
+
[3]:UncommunicativeMethodName: foobar has the name 'foobar'
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Advanced configuration
|
|
60
|
+
|
|
61
|
+
Sometimes just strings are not enough for configuration. E.g. consider this code sample:
|
|
62
|
+
|
|
63
|
+
```Ruby
|
|
64
|
+
class Klass
|
|
65
|
+
def foo; end
|
|
66
|
+
def foobar; end;
|
|
67
|
+
end
|
|
55
68
|
```
|
|
69
|
+
|
|
70
|
+
and now imagine that you want to reject the name "foo" but not "foobar". This wouldn't be possible with just using strings.
|
|
71
|
+
For this reason Reek has a special syntax that allows you to use regexes by using a forward slash at the beginning and the end of the string.
|
|
72
|
+
Everything within the forward slashes will be loaded as a regex.
|
|
73
|
+
|
|
74
|
+
A possible configuration that allows "foobar" but rejects "foo" could look like this:
|
|
75
|
+
|
|
76
|
+
```Yaml
|
|
77
|
+
---
|
|
78
|
+
UncommunicativeMethodName:
|
|
79
|
+
reject:
|
|
80
|
+
- "/^foo$/"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Reek 4
|
|
84
|
+
|
|
85
|
+
In Reek 4 you could also pass regexes to `accept` or `reject`, meaning this was perfectly valid as well:
|
|
86
|
+
|
|
87
|
+
```yaml
|
|
88
|
+
UncommunicativeMethodName:
|
|
89
|
+
accept:
|
|
90
|
+
- !ruby/regexp /foobar/
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Support for this has been scrapped with Reek 5 to make the Reek configuration more yaml standard compliant.
|
|
94
|
+
You can still pass in regexes, you just have to wrap them into a string. Please see "Advanced configuration" above.
|
|
@@ -19,8 +19,8 @@ Reek's _Uncommunicative Module Name_ detector supports the [Basic Smell Options]
|
|
|
19
19
|
|
|
20
20
|
| Option | Value | Effect |
|
|
21
21
|
| ---------------|-------------|---------|
|
|
22
|
-
| `reject` | array of
|
|
23
|
-
| `accept` | array
|
|
22
|
+
| `reject` | array of strings | The set of names that Reek uses to check for bad names. Defaults to single-letter names and names ending with a number. |
|
|
23
|
+
| `accept` | array or strings | The set of names that Reek will accept (and not report) even if they match one of the `reject` expressions. Empty by default.|
|
|
24
24
|
|
|
25
25
|
An example configuration could look like this:
|
|
26
26
|
|
|
@@ -28,17 +28,19 @@ An example configuration could look like this:
|
|
|
28
28
|
---
|
|
29
29
|
UncommunicativeModuleName:
|
|
30
30
|
accept:
|
|
31
|
-
-
|
|
32
|
-
-
|
|
31
|
+
- lassy
|
|
32
|
+
- Util
|
|
33
33
|
reject:
|
|
34
|
-
-
|
|
34
|
+
- Helper
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
+
Reek will convert whatever you give it as a string to the corresponding regex, so "Helper" from above will be converted to /Helper/ internally.
|
|
38
|
+
|
|
37
39
|
Applying a configuration to a source file like this:
|
|
38
40
|
|
|
39
41
|
```Ruby
|
|
40
42
|
class Classy1; end # Should not be reported
|
|
41
|
-
class
|
|
43
|
+
class Util; end # Should not be reported
|
|
42
44
|
class BaseHelper; end # Should be reported
|
|
43
45
|
```
|
|
44
46
|
|
|
@@ -46,5 +48,45 @@ Reek would report:
|
|
|
46
48
|
|
|
47
49
|
```
|
|
48
50
|
smelly.rb -- 1 warning:
|
|
49
|
-
[3]:UncommunicativeModuleName: BaseHelper has the name 'BaseHelper'
|
|
51
|
+
[3]:UncommunicativeModuleName: BaseHelper has the name 'BaseHelper'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Advanced configuration
|
|
55
|
+
|
|
56
|
+
Sometimes just strings are not enough for configuration. E.g. consider this code sample:
|
|
57
|
+
|
|
58
|
+
```Ruby
|
|
59
|
+
class Klassy
|
|
60
|
+
# ...
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
class KlassyModule
|
|
64
|
+
# ...
|
|
65
|
+
end
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
and now imagine that you want to reject the name "Klassy" but not "KlassyModule". This wouldn't be possible with just using strings.
|
|
69
|
+
For this reason Reek has a special syntax that allows you to use regexes by using a forward slash at the beginning and the end of the string.
|
|
70
|
+
Everything within the forward slashes will be loaded as a regex.
|
|
71
|
+
|
|
72
|
+
A possible configuration that allows "KlassyModule" but rejects "Klassy" could look like this:
|
|
73
|
+
|
|
74
|
+
```Yaml
|
|
75
|
+
---
|
|
76
|
+
UncommunicativeModuleName:
|
|
77
|
+
reject:
|
|
78
|
+
- "/^Klassy$/"
|
|
50
79
|
```
|
|
80
|
+
|
|
81
|
+
## Reek 4
|
|
82
|
+
|
|
83
|
+
In Reek 4 you could also pass regexes to `accept` or `reject`, meaning this was perfectly valid as well:
|
|
84
|
+
|
|
85
|
+
```yaml
|
|
86
|
+
UncommunicativeModuleName:
|
|
87
|
+
accept:
|
|
88
|
+
- !ruby/regexp /foobar/
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Support for this has been scrapped with Reek 5 to make the Reek configuration more yaml standard compliant.
|
|
92
|
+
You can still pass in regexes, you just have to wrap them into a string. Please see "Advanced configuration" above.
|