reek 4.8.2 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{samples/configuration/more_than_one_configuration_file/regular.reek → .reek.yml} +0 -0
- data/.rubocop.yml +17 -3
- data/.simplecov +1 -0
- data/.travis.yml +0 -5
- data/.yardopts +1 -1
- data/CHANGELOG.md +28 -0
- data/Gemfile +1 -1
- data/README.md +113 -98
- 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/{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 +43 -4
- data/docs/Uncommunicative-Module-Name.md +48 -6
- data/docs/Uncommunicative-Parameter-Name.md +42 -4
- 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/options.feature +46 -4
- data/features/command_line_interface/stdin.feature +27 -5
- data/features/configuration_files/accept_setting.feature +39 -22
- data/features/configuration_files/directory_specific_directives.feature +58 -53
- data/features/configuration_files/exclude_directives.feature +8 -7
- data/features/configuration_files/masking_smells.feature +35 -6
- data/features/configuration_files/mix_accept_reject_setting.feature +24 -21
- data/features/configuration_files/reject_setting.feature +45 -34
- data/features/configuration_files/schema_validation.feature +59 -0
- data/features/configuration_files/unused_private_method.feature +14 -12
- data/features/configuration_loading.feature +50 -7
- data/features/rake_task/rake_task.feature +5 -5
- data/features/reports/json.feature +4 -1
- data/features/reports/reports.feature +12 -12
- data/features/reports/yaml.feature +3 -0
- data/features/rspec_matcher.feature +9 -1
- 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 +16 -13
- data/lib/reek/ast/node.rb +3 -6
- data/lib/reek/ast/object_refs.rb +1 -1
- data/lib/reek/ast/sexp_extensions/if.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 +27 -13
- 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 +2 -2
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +1 -1
- data/lib/reek/errors/bad_detector_in_comment_error.rb +1 -1
- 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 +1 -1
- 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.rb +15 -10
- data/lib/reek/report/base_report.rb +8 -12
- data/lib/reek/report/code_climate/code_climate_configuration.yml +5 -9
- 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/smell_configuration.rb +2 -2
- data/lib/reek/smell_detectors.rb +1 -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 +0 -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_warning.rb +10 -8
- data/lib/reek/source/source_code.rb +40 -55
- data/lib/reek/source/source_locator.rb +7 -7
- data/lib/reek/spec.rb +6 -6
- 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/tree_dresser.rb +5 -5
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +3 -3
- data/samples/checkstyle.xml +1 -1
- data/samples/{clean.rb → clean_source/clean.rb} +0 -0
- 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/{exceptions.reek → configuration/home/home.reek.yml} +0 -0
- data/samples/configuration/partial_mask.reek +3 -2
- data/samples/configuration/regular_configuration/.reek.yml +4 -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/paths.rb +5 -4
- 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/.hidden/hidden.rb +1 -0
- data/samples/source_with_hidden_directories/not_hidden.rb +1 -0
- data/samples/{source_with_hidden_directories/uncommunicative_parameter_name.rb → source_with_non_ruby_files/ruby.rb} +0 -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 +133 -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/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 +2 -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 +56 -35
- data/defaults.reek +0 -131
- data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
- data/lib/reek/report/formatter.rb +0 -33
- 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 -23
- 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
@@ -25,6 +25,7 @@ Feature: Report smells using simple YAML layout
|
|
25
25
|
smell_type: UncommunicativeMethodName
|
26
26
|
source: smelly.rb
|
27
27
|
name: x
|
28
|
+
documentation_link: https://github.com/troessner/reek/blob/v5.0.0/docs/Uncommunicative-Method-Name.md
|
28
29
|
- context: Smelly#x
|
29
30
|
lines:
|
30
31
|
- 5
|
@@ -32,6 +33,7 @@ Feature: Report smells using simple YAML layout
|
|
32
33
|
smell_type: UncommunicativeVariableName
|
33
34
|
source: smelly.rb
|
34
35
|
name: y
|
36
|
+
documentation_link: https://github.com/troessner/reek/blob/v5.0.0/docs/Uncommunicative-Variable-Name.md
|
35
37
|
"""
|
36
38
|
|
37
39
|
Scenario: Indicate smells and print them as yaml when using STDIN
|
@@ -46,4 +48,5 @@ Feature: Report smells using simple YAML layout
|
|
46
48
|
lines:
|
47
49
|
- 1
|
48
50
|
message: has no descriptive comment
|
51
|
+
documentation_link: https://github.com/troessner/reek/blob/v5.0.0/docs/Irresponsible-Module.md
|
49
52
|
"""
|
@@ -24,7 +24,15 @@ Feature: Use reek_of matcher
|
|
24
24
|
"""
|
25
25
|
|
26
26
|
Scenario: Masking smells with a configuration file
|
27
|
-
Given a
|
27
|
+
Given a file named ".reek.yml" with:
|
28
|
+
"""
|
29
|
+
---
|
30
|
+
detectors:
|
31
|
+
UncommunicativeMethodName:
|
32
|
+
enabled: false
|
33
|
+
UncommunicativeVariableName:
|
34
|
+
enabled: false
|
35
|
+
"""
|
28
36
|
When I run `rspec reek_spec.rb`
|
29
37
|
Then stdout should contain:
|
30
38
|
"""
|
@@ -6,6 +6,10 @@ When /^I pass "([^\"]*)" to reek *(.*)$/ do |stdin, args|
|
|
6
6
|
reek_with_pipe(stdin, args)
|
7
7
|
end
|
8
8
|
|
9
|
+
When /^I pass a stdin to reek *(.*) with:$/ do |args, stdin|
|
10
|
+
reek_with_pipe(stdin, args)
|
11
|
+
end
|
12
|
+
|
9
13
|
Then /^it reports nothing$/ do
|
10
14
|
expect(last_command_started).to have_output_on_stdout('')
|
11
15
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require_relative '../../samples/paths'
|
2
2
|
|
3
3
|
Given(/^the smelly file '(.+)'$/) do |filename|
|
4
|
-
write_file(filename,
|
4
|
+
write_file(filename, SAMPLES_DIR.join('smelly_source').join(filename).read)
|
5
5
|
end
|
6
6
|
|
7
7
|
Given(/^the clean file 'clean.rb'$/) do
|
@@ -28,13 +28,18 @@ Given(/^a directory called 'smelly' containing two smelly files$/) do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
Given(/^the smelly file '(.+)' in a subdirectory$/) do |filename|
|
31
|
-
contents =
|
31
|
+
contents = SAMPLES_DIR.join('smelly_source').join(filename).read
|
32
32
|
|
33
33
|
write_file("subdir/#{filename}", contents)
|
34
34
|
end
|
35
35
|
|
36
36
|
Given(/^a configuration file '(.+)'$/) do |filename|
|
37
|
-
write_file(filename,
|
37
|
+
write_file(filename, CONFIGURATION_DIR.join(filename).read)
|
38
|
+
end
|
39
|
+
|
40
|
+
Given(/^our default configuration file$/) do
|
41
|
+
default_configuration = File.read SAMPLES_DIR.join('..').join('docs').join('defaults.reek.yml')
|
42
|
+
write_file('defaults.reek', default_configuration)
|
38
43
|
end
|
39
44
|
|
40
45
|
When(/^I run "reek (.*?)" in a subdirectory$/) do |args|
|
@@ -44,7 +49,7 @@ When(/^I run "reek (.*?)" in a subdirectory$/) do |args|
|
|
44
49
|
end
|
45
50
|
|
46
51
|
Given(/^a configuration file '(.+)' in a subdirectory$/) do |filename|
|
47
|
-
contents =
|
52
|
+
contents = CONFIGURATION_DIR.join(filename).read
|
48
53
|
|
49
54
|
write_file("subdir/#{filename}", contents)
|
50
55
|
end
|
data/features/support/env.rb
CHANGED
@@ -13,11 +13,11 @@ end
|
|
13
13
|
#
|
14
14
|
class ReekWorld
|
15
15
|
def reek(args)
|
16
|
-
run_simple("reek --no-color --no-
|
16
|
+
run_simple("reek --no-color --no-documentation #{args}", false)
|
17
17
|
end
|
18
18
|
|
19
19
|
def reek_with_pipe(stdin, args)
|
20
|
-
run "reek --no-color --no-
|
20
|
+
run "reek --no-color --no-documentation #{args}"
|
21
21
|
type(stdin)
|
22
22
|
close_input
|
23
23
|
end
|
data/features/todo_list.feature
CHANGED
@@ -29,13 +29,14 @@ Feature: Auto-generate a todo file
|
|
29
29
|
And the file ".todo.reek" should contain:
|
30
30
|
"""
|
31
31
|
---
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
detectors:
|
33
|
+
UncommunicativeMethodName:
|
34
|
+
exclude:
|
35
|
+
- Smelly#x
|
36
|
+
UncommunicativeVariableName:
|
37
|
+
exclude:
|
38
|
+
- Smelly#x
|
39
|
+
"""
|
39
40
|
When I run reek -c .todo.reek smelly.rb
|
40
41
|
Then it succeeds
|
41
42
|
|
@@ -54,10 +55,11 @@ Feature: Auto-generate a todo file
|
|
54
55
|
And a file named ".todo.reek" with:
|
55
56
|
"""
|
56
57
|
---
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
58
|
+
detectors:
|
59
|
+
# smelly.rb reeks of UncommunicativeMethodName and UncommunicativeVariableName
|
60
|
+
# so the configuration below will partially mask this
|
61
|
+
UncommunicativeMethodName:
|
62
|
+
enabled: false
|
61
63
|
"""
|
62
64
|
When I run reek -c .todo.reek smelly.rb
|
63
65
|
Then it reports:
|
@@ -77,8 +79,9 @@ Feature: Auto-generate a todo file
|
|
77
79
|
---
|
78
80
|
# smelly.rb reeks of UncommunicativeMethodName and UncommunicativeVariableName
|
79
81
|
# so the configuration below will partially mask this
|
80
|
-
|
81
|
-
|
82
|
+
detectors:
|
83
|
+
UncommunicativeMethodName:
|
84
|
+
enabled: false
|
82
85
|
"""
|
83
86
|
When I run reek -c config.reek smelly.rb
|
84
87
|
Then it reports:
|
data/lib/reek/ast/node.rb
CHANGED
@@ -1,10 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../cli/silencer'
|
4
|
-
|
5
|
-
Reek::CLI::Silencer.silently do
|
6
|
-
require 'parser'
|
7
|
-
end
|
4
|
+
Reek::CLI::Silencer.without_warnings { require 'parser' }
|
8
5
|
|
9
6
|
module Reek
|
10
7
|
module AST
|
@@ -72,8 +69,8 @@ module Reek
|
|
72
69
|
each_node(target_type).any?
|
73
70
|
end
|
74
71
|
|
75
|
-
# :reek:DuplicateMethodCall { max_calls: 2 } is ok for lines.first
|
76
|
-
# :reek:FeatureEnvy
|
72
|
+
# @quality :reek:DuplicateMethodCall { max_calls: 2 } is ok for lines.first
|
73
|
+
# @quality :reek:FeatureEnvy
|
77
74
|
def format_to_ruby
|
78
75
|
if location
|
79
76
|
lines = location.expression.source.split("\n").map(&:strip)
|
data/lib/reek/ast/object_refs.rb
CHANGED
data/lib/reek/cli/application.rb
CHANGED
@@ -6,6 +6,7 @@ require_relative '../configuration/app_configuration'
|
|
6
6
|
require_relative '../source/source_locator'
|
7
7
|
require_relative 'command/report_command'
|
8
8
|
require_relative 'command/todo_list_command'
|
9
|
+
require_relative '../errors/config_file_error'
|
9
10
|
|
10
11
|
module Reek
|
11
12
|
module CLI
|
@@ -42,7 +43,7 @@ module Reek
|
|
42
43
|
|
43
44
|
def configure_app_configuration(config_file)
|
44
45
|
Configuration::AppConfiguration.from_path(config_file)
|
45
|
-
rescue
|
46
|
+
rescue Errors::ConfigFileError => error
|
46
47
|
warn "Error: #{error}"
|
47
48
|
exit Status::DEFAULT_ERROR_EXIT_CODE
|
48
49
|
end
|
@@ -68,7 +69,7 @@ module Reek
|
|
68
69
|
options.argv
|
69
70
|
end
|
70
71
|
|
71
|
-
# :reek:UtilityFunction
|
72
|
+
# @quality :reek:UtilityFunction
|
72
73
|
def input_was_piped?
|
73
74
|
!$stdin.tty?
|
74
75
|
end
|
@@ -88,7 +89,7 @@ module Reek
|
|
88
89
|
end
|
89
90
|
|
90
91
|
def source_from_pipe
|
91
|
-
[$stdin]
|
92
|
+
[Source::SourceCode.from($stdin, origin: options.stdin_filename)]
|
92
93
|
end
|
93
94
|
|
94
95
|
def disable_progress_output_unless_verbose
|
@@ -38,7 +38,6 @@ module Reek
|
|
38
38
|
@reporter ||=
|
39
39
|
report_class.new(
|
40
40
|
warning_formatter: warning_formatter,
|
41
|
-
report_formatter: Report::Formatter,
|
42
41
|
sort_by_issue_count: sort_by_issue_count,
|
43
42
|
heading_formatter: heading_formatter,
|
44
43
|
progress_formatter: progress_formatter.new(sources.length))
|
@@ -53,7 +52,7 @@ module Reek
|
|
53
52
|
end
|
54
53
|
|
55
54
|
def warning_formatter_class
|
56
|
-
Report.warning_formatter_class(options.show_links ? :
|
55
|
+
Report.warning_formatter_class(options.show_links ? :documentation_links : :simple)
|
57
56
|
end
|
58
57
|
|
59
58
|
def location_formatter
|
@@ -2,6 +2,7 @@
|
|
2
2
|
|
3
3
|
require_relative 'base_command'
|
4
4
|
require_relative '../../examiner'
|
5
|
+
require_relative '../../configuration/app_configuration'
|
5
6
|
|
6
7
|
module Reek
|
7
8
|
module CLI
|
@@ -11,14 +12,15 @@ module Reek
|
|
11
12
|
# file that can serve as a todo list.
|
12
13
|
#
|
13
14
|
class TodoListCommand < BaseCommand
|
14
|
-
FILE_NAME = '.todo.reek'
|
15
|
+
FILE_NAME = '.todo.reek'
|
15
16
|
|
16
17
|
def execute
|
17
18
|
if smells.empty?
|
18
19
|
puts "\n'.todo.reek' not generated because "\
|
19
20
|
'there were no smells found!'
|
20
21
|
else
|
21
|
-
File.write FILE_NAME,
|
22
|
+
File.write FILE_NAME,
|
23
|
+
{ Configuration::AppConfiguration::DETECTORS_KEY => groups }.to_yaml
|
22
24
|
puts "\n'.todo.reek' generated! You can now use "\
|
23
25
|
'this as a starting point for your configuration.'
|
24
26
|
end
|
data/lib/reek/cli/options.rb
CHANGED
@@ -4,6 +4,7 @@ require 'optparse'
|
|
4
4
|
require 'rainbow'
|
5
5
|
require_relative '../version'
|
6
6
|
require_relative 'status'
|
7
|
+
require_relative '../detector_repository'
|
7
8
|
require_relative '../documentation_link'
|
8
9
|
|
9
10
|
module Reek
|
@@ -13,9 +14,9 @@ module Reek
|
|
13
14
|
#
|
14
15
|
# See {file:docs/Command-Line-Options.md} for details.
|
15
16
|
#
|
16
|
-
# :reek:TooManyInstanceVariables
|
17
|
-
# :reek:TooManyMethods
|
18
|
-
# :reek:Attribute
|
17
|
+
# @quality :reek:TooManyInstanceVariables { max_instance_variables: 12 }
|
18
|
+
# @quality :reek:TooManyMethods { max_methods: 18 }
|
19
|
+
# @quality :reek:Attribute { enabled: false }
|
19
20
|
#
|
20
21
|
class Options
|
21
22
|
attr_reader :argv, :parser, :smells_to_detect
|
@@ -27,6 +28,7 @@ module Reek
|
|
27
28
|
:show_empty,
|
28
29
|
:show_links,
|
29
30
|
:sorting,
|
31
|
+
:stdin_filename,
|
30
32
|
:success_exit_code,
|
31
33
|
:failure_exit_code,
|
32
34
|
:generate_todo_list,
|
@@ -65,12 +67,12 @@ module Reek
|
|
65
67
|
# processing by a machine, but will be viewed by a human. This means
|
66
68
|
# features like coloring can be safely enabled by default.
|
67
69
|
#
|
68
|
-
# :reek:UtilityFunction
|
70
|
+
# @quality :reek:UtilityFunction
|
69
71
|
def tty_output?
|
70
72
|
$stdout.tty?
|
71
73
|
end
|
72
74
|
|
73
|
-
# :reek:TooManyStatements
|
75
|
+
# @quality :reek:TooManyStatements { max_statements: 7 }
|
74
76
|
def set_up_parser
|
75
77
|
set_banner
|
76
78
|
set_configuration_options
|
@@ -92,12 +94,12 @@ module Reek
|
|
92
94
|
#{program_name} -s lib
|
93
95
|
cat my_class.rb | #{program_name}
|
94
96
|
|
95
|
-
See https://
|
97
|
+
See https://github.com/troessner/reek for detailed help.
|
96
98
|
|
97
99
|
BANNER
|
98
100
|
end
|
99
101
|
|
100
|
-
# :reek:TooManyStatements
|
102
|
+
# @quality :reek:TooManyStatements { max_statements: 7 }
|
101
103
|
def set_configuration_options
|
102
104
|
parser.separator 'Configuration:'
|
103
105
|
parser.on('-c', '--config FILE', 'Read configuration options from FILE') do |file|
|
@@ -105,11 +107,16 @@ module Reek
|
|
105
107
|
end
|
106
108
|
parser.on('--smell SMELL',
|
107
109
|
'Only look for a specific smell.',
|
108
|
-
'Call it like this: reek --smell
|
110
|
+
'Call it like this: reek --smell MissingSafeMethod source.rb',
|
109
111
|
"Check out #{DocumentationLink.build('Code Smells')} "\
|
110
112
|
'for a list of smells') do |smell|
|
111
113
|
smells_to_detect << smell
|
112
114
|
end
|
115
|
+
parser.on('--stdin-filename FILE',
|
116
|
+
'When passing code in via pipe, assume this filename when '\
|
117
|
+
'checking file or directory rules in the config.') do |file|
|
118
|
+
self.stdin_filename = file
|
119
|
+
end
|
113
120
|
end
|
114
121
|
|
115
122
|
def set_generate_todo_list_options
|
@@ -129,7 +136,7 @@ module Reek
|
|
129
136
|
end
|
130
137
|
end
|
131
138
|
|
132
|
-
# :reek:TooManyStatements
|
139
|
+
# @quality :reek:TooManyStatements { max_statements: 7 }
|
133
140
|
def set_report_formatting_options
|
134
141
|
parser.separator "\nText format options:"
|
135
142
|
set_up_color_option
|
@@ -151,8 +158,8 @@ module Reek
|
|
151
158
|
'Show headings for smell-free source files (default: false)') do |show_empty|
|
152
159
|
self.show_empty = show_empty
|
153
160
|
end
|
154
|
-
parser.on('-U', '--[no-]
|
155
|
-
'Show link to related
|
161
|
+
parser.on('-U', '--[no-]documentation',
|
162
|
+
'Show link to related documentation page for each smell (default: true)') do |show_links|
|
156
163
|
self.show_links = show_links
|
157
164
|
end
|
158
165
|
end
|
@@ -192,7 +199,7 @@ module Reek
|
|
192
199
|
end
|
193
200
|
end
|
194
201
|
|
195
|
-
# :reek:DuplicateMethodCall
|
202
|
+
# @quality :reek:DuplicateMethodCall { max_calls: 2 }
|
196
203
|
def set_exit_codes
|
197
204
|
parser.separator "\nExit codes:"
|
198
205
|
parser.on('--success-exit-code CODE',
|
@@ -207,13 +214,20 @@ module Reek
|
|
207
214
|
end
|
208
215
|
end
|
209
216
|
|
210
|
-
# :reek:TooManyStatements
|
217
|
+
# @quality :reek:TooManyStatements { max_statements: 12 }
|
211
218
|
def set_utility_options
|
212
219
|
parser.separator "\nUtility options:"
|
213
220
|
parser.on_tail('-h', '--help', 'Show this message') do
|
214
221
|
puts parser
|
215
222
|
exit
|
216
223
|
end
|
224
|
+
parser.on_tail('-l', '--list', 'List all available smell detectors') do
|
225
|
+
puts "All available smell detectors:\n\n"
|
226
|
+
puts DetectorRepository.available_detector_names
|
227
|
+
puts "\nCheck out #{DocumentationLink.build('Code Smells')} "\
|
228
|
+
'for a details on each detector'
|
229
|
+
exit
|
230
|
+
end
|
217
231
|
parser.on_tail('-v', '--version', 'Show version') do
|
218
232
|
puts "#{parser.program_name} #{Reek::Version::STRING}\n"
|
219
233
|
exit
|
data/lib/reek/cli/silencer.rb
CHANGED
@@ -8,17 +8,28 @@ module Reek
|
|
8
8
|
module Silencer
|
9
9
|
module_function
|
10
10
|
|
11
|
-
# :reek:TooManyStatements
|
11
|
+
# @quality :reek:TooManyStatements { max_statements: 9 }
|
12
12
|
def silently
|
13
13
|
old_verbose = $VERBOSE
|
14
|
+
old_stderr = $stderr
|
15
|
+
old_stdout = $stdout
|
16
|
+
|
14
17
|
$VERBOSE = false
|
15
18
|
$stderr = StringIO.new
|
16
19
|
$stdout = StringIO.new
|
17
20
|
yield
|
18
21
|
ensure
|
19
22
|
$VERBOSE = old_verbose
|
20
|
-
$stderr =
|
21
|
-
$stdout =
|
23
|
+
$stderr = old_stderr
|
24
|
+
$stdout = old_stdout
|
25
|
+
end
|
26
|
+
|
27
|
+
def without_warnings
|
28
|
+
old_verbose = $VERBOSE
|
29
|
+
$VERBOSE = false
|
30
|
+
yield
|
31
|
+
ensure
|
32
|
+
$VERBOSE = old_verbose
|
22
33
|
end
|
23
34
|
end
|
24
35
|
end
|
data/lib/reek/code_comment.rb
CHANGED
@@ -17,22 +17,20 @@ module Reek
|
|
17
17
|
:reek: # prefix
|
18
18
|
(\w+) # smell detector e.g.: UncommunicativeVariableName
|
19
19
|
(
|
20
|
-
:? # legacy separator
|
21
20
|
\s*
|
22
21
|
(\{.*?\}) # optional details in hash style e.g.: { max_methods: 30 }
|
23
22
|
)?
|
24
23
|
/x
|
25
24
|
SANITIZE_REGEX = /(#|\n|\s)+/ # Matches '#', newlines and > 1 whitespaces.
|
26
|
-
DISABLE_DETECTOR_CONFIGURATION = '{ enabled: false }'
|
25
|
+
DISABLE_DETECTOR_CONFIGURATION = '{ enabled: false }'
|
27
26
|
MINIMUM_CONTENT_LENGTH = 2
|
28
|
-
LEGACY_SEPARATOR = ':'.freeze
|
29
27
|
|
30
28
|
attr_reader :config
|
31
29
|
|
32
30
|
#
|
33
|
-
# @param comment [String]
|
34
|
-
# @param line [Integer]
|
35
|
-
# @param source [String]
|
31
|
+
# @param comment [String] the original comment as found in the source code
|
32
|
+
# @param line [Integer] start of the expression the comment belongs to
|
33
|
+
# @param source [String] Path to source file or "string"
|
36
34
|
#
|
37
35
|
def initialize(comment:, line: nil, source: nil)
|
38
36
|
@original_comment = comment
|
@@ -80,15 +78,15 @@ module Reek
|
|
80
78
|
# This class validates [1], [2] and [3] at the moment but will also validate
|
81
79
|
# [4] in the future.
|
82
80
|
#
|
83
|
-
# :reek:TooManyInstanceVariables
|
81
|
+
# @quality :reek:TooManyInstanceVariables { max_instance_variables: 7 }
|
84
82
|
class CodeCommentValidator
|
85
83
|
#
|
86
|
-
# @param detector_name [String]
|
84
|
+
# @param detector_name [String] the detector class that was parsed out of the original
|
87
85
|
# comment, e.g. "DuplicateMethodCall" or "UnknownSmellDetector"
|
88
|
-
# @param original_comment [String]
|
89
|
-
# @param line [Integer]
|
90
|
-
# @param source [String]
|
91
|
-
# @param options [String]
|
86
|
+
# @param original_comment [String] the original comment as found in the source code
|
87
|
+
# @param line [Integer] start of the expression the comment belongs to
|
88
|
+
# @param source [String] path to source file or "string"
|
89
|
+
# @param options [String] the configuration options as String for the detector that were
|
92
90
|
# extracted from the original comment
|
93
91
|
def initialize(detector_name:, original_comment:, line:, source:, options: {})
|
94
92
|
@detector_name = detector_name
|
@@ -151,24 +149,24 @@ module Reek
|
|
151
149
|
line: line
|
152
150
|
end
|
153
151
|
|
154
|
-
# @return [Boolean]
|
152
|
+
# @return [Boolean] all keys in code comment are applicable to the detector in question
|
155
153
|
def given_keys_legit?
|
156
154
|
given_configuration_keys.subset? valid_detector_keys
|
157
155
|
end
|
158
156
|
|
159
|
-
# @return [Set]
|
157
|
+
# @return [Set] the configuration keys that are found in the code comment
|
160
158
|
def given_configuration_keys
|
161
159
|
parsed_options.keys.map(&:to_sym).to_set
|
162
160
|
end
|
163
161
|
|
164
|
-
# @return [String]
|
162
|
+
# @return [String] all keys from the code comment that look bad
|
165
163
|
def configuration_keys_difference
|
166
164
|
given_configuration_keys.difference(valid_detector_keys).
|
167
165
|
to_a.map { |key| "'#{key}'" }.
|
168
166
|
join(', ')
|
169
167
|
end
|
170
168
|
|
171
|
-
# @return [Set]
|
169
|
+
# @return [Set] all keys that are legit for the given detector
|
172
170
|
def valid_detector_keys
|
173
171
|
detector_class.configuration_keys
|
174
172
|
end
|