reek 4.6.0 → 5.0.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/.codeclimate.yml +17 -12
- data/.rubocop.yml +79 -26
- data/.simplecov +1 -0
- data/.travis.yml +3 -9
- data/.yardopts +1 -1
- data/CHANGELOG.md +76 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +5 -5
- data/README.md +138 -107
- data/Rakefile +16 -3
- data/bin/code_climate_reek +1 -0
- data/bin/reek +2 -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 +7 -7
- 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 +3 -3
- 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 +31 -5
- data/features/configuration_files/accept_setting.feature +45 -28
- data/features/configuration_files/directory_specific_directives.feature +80 -75
- 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 +3 -3
- data/features/configuration_via_source_comments/well_formed_source_comments.feature +2 -2
- data/features/locales.feature +32 -0
- data/features/rake_task/rake_task.feature +58 -18
- data/features/reports/codeclimate.feature +59 -0
- 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 +40 -0
- data/features/samples.feature +287 -287
- data/features/step_definitions/reek_steps.rb +14 -2
- data/features/step_definitions/sample_file_steps.rb +9 -4
- data/features/support/env.rb +2 -11
- data/features/todo_list.feature +26 -23
- data/lib/reek/ast/ast_node_class_map.rb +1 -0
- data/lib/reek/ast/builder.rb +16 -0
- data/lib/reek/ast/node.rb +50 -58
- data/lib/reek/ast/object_refs.rb +2 -1
- data/lib/reek/ast/reference_collector.rb +3 -4
- data/lib/reek/ast/sexp_extensions/arguments.rb +1 -0
- data/lib/reek/ast/sexp_extensions/attribute_assignments.rb +1 -0
- data/lib/reek/ast/sexp_extensions/begin.rb +17 -0
- data/lib/reek/ast/sexp_extensions/block.rb +1 -0
- data/lib/reek/ast/sexp_extensions/case.rb +2 -1
- data/lib/reek/ast/sexp_extensions/constant.rb +1 -0
- data/lib/reek/ast/sexp_extensions/if.rb +9 -1
- data/lib/reek/ast/sexp_extensions/lambda.rb +1 -0
- data/lib/reek/ast/sexp_extensions/literal.rb +1 -0
- data/lib/reek/ast/sexp_extensions/logical_operators.rb +2 -1
- data/lib/reek/ast/sexp_extensions/methods.rb +5 -6
- data/lib/reek/ast/sexp_extensions/module.rb +55 -8
- data/lib/reek/ast/sexp_extensions/nested_assignables.rb +1 -0
- data/lib/reek/ast/sexp_extensions/self.rb +1 -0
- data/lib/reek/ast/sexp_extensions/send.rb +1 -4
- data/lib/reek/ast/sexp_extensions/super.rb +1 -0
- data/lib/reek/ast/sexp_extensions/symbols.rb +1 -0
- data/lib/reek/ast/sexp_extensions/variables.rb +1 -0
- data/lib/reek/ast/sexp_extensions/when.rb +1 -0
- data/lib/reek/ast/sexp_extensions/yield.rb +1 -0
- data/lib/reek/ast/sexp_extensions.rb +2 -0
- data/lib/reek/cli/application.rb +5 -3
- data/lib/reek/cli/command/base_command.rb +1 -0
- data/lib/reek/cli/command/report_command.rb +2 -2
- data/lib/reek/cli/command/todo_list_command.rb +9 -8
- data/lib/reek/cli/options.rb +32 -16
- data/lib/reek/cli/silencer.rb +15 -3
- data/lib/reek/cli/status.rb +1 -0
- data/lib/reek/code_comment.rb +14 -16
- data/lib/reek/configuration/app_configuration.rb +34 -28
- data/lib/reek/configuration/configuration_converter.rb +110 -0
- data/lib/reek/configuration/configuration_file_finder.rb +17 -41
- data/lib/reek/configuration/configuration_validator.rb +13 -23
- data/lib/reek/configuration/default_directive.rb +18 -3
- data/lib/reek/configuration/directory_directives.rb +18 -11
- data/lib/reek/configuration/excluded_paths.rb +2 -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 +4 -3
- data/lib/reek/context/class_context.rb +1 -0
- data/lib/reek/context/code_context.rb +49 -44
- data/lib/reek/context/ghost_context.rb +1 -2
- data/lib/reek/context/method_context.rb +26 -18
- data/lib/reek/context/module_context.rb +11 -11
- data/lib/reek/context/root_context.rb +1 -4
- data/lib/reek/context/send_context.rb +3 -2
- data/lib/reek/context/singleton_attribute_context.rb +1 -0
- data/lib/reek/context/singleton_method_context.rb +1 -0
- data/lib/reek/context/statement_counter.rb +1 -0
- data/lib/reek/context/visibility_tracker.rb +1 -0
- data/lib/reek/context_builder.rb +44 -44
- data/lib/reek/detector_repository.rb +12 -11
- data/lib/reek/documentation_link.rb +28 -0
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +15 -13
- data/lib/reek/errors/bad_detector_in_comment_error.rb +13 -11
- data/lib/reek/errors/base_error.rb +3 -0
- data/lib/reek/errors/config_file_error.rb +11 -0
- data/lib/reek/errors/encoding_error.rb +43 -0
- data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +14 -12
- data/lib/reek/errors/incomprehensible_source_error.rb +23 -24
- data/lib/reek/errors/syntax_error.rb +41 -0
- data/lib/reek/examiner.rb +24 -22
- data/lib/reek/logging_error_handler.rb +8 -5
- data/lib/reek/rake/task.rb +8 -5
- data/lib/reek/report/base_report.rb +9 -12
- data/lib/reek/report/code_climate/code_climate_configuration.rb +2 -1
- data/lib/reek/report/code_climate/code_climate_configuration.yml +6 -6
- data/lib/reek/report/code_climate/code_climate_fingerprint.rb +1 -0
- data/lib/reek/report/code_climate/code_climate_formatter.rb +1 -0
- data/lib/reek/report/code_climate/code_climate_report.rb +1 -0
- data/lib/reek/report/code_climate.rb +1 -0
- data/lib/reek/report/documentation_link_warning_formatter.rb +17 -0
- data/lib/reek/report/heading_formatter.rb +54 -0
- data/lib/reek/report/html_report.rb +1 -0
- data/lib/reek/report/json_report.rb +2 -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 +2 -2
- data/lib/reek/report/xml_report.rb +4 -3
- data/lib/reek/report/yaml_report.rb +2 -1
- data/lib/reek/report.rb +16 -10
- data/lib/reek/smell_configuration.rb +3 -2
- data/lib/reek/smell_detectors/attribute.rb +6 -11
- data/lib/reek/smell_detectors/base_detector.rb +31 -26
- data/lib/reek/smell_detectors/boolean_parameter.rb +4 -5
- data/lib/reek/smell_detectors/class_variable.rb +6 -14
- data/lib/reek/smell_detectors/control_parameter.rb +19 -33
- data/lib/reek/smell_detectors/data_clump.rb +16 -9
- data/lib/reek/smell_detectors/duplicate_method_call.rb +24 -17
- data/lib/reek/smell_detectors/feature_envy.rb +10 -7
- data/lib/reek/smell_detectors/instance_variable_assumption.rb +15 -23
- data/lib/reek/smell_detectors/irresponsible_module.rb +6 -12
- data/lib/reek/smell_detectors/long_parameter_list.rb +11 -7
- data/lib/reek/smell_detectors/long_yield_list.rb +11 -7
- data/lib/reek/smell_detectors/manual_dispatch.rb +5 -5
- data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +21 -20
- data/lib/reek/smell_detectors/module_initialize.rb +4 -5
- data/lib/reek/smell_detectors/nested_iterators.rb +17 -24
- data/lib/reek/smell_detectors/nil_check.rb +9 -15
- data/lib/reek/smell_detectors/repeated_conditional.rb +14 -11
- data/lib/reek/smell_detectors/subclassed_from_core_class.rb +8 -8
- data/lib/reek/smell_detectors/too_many_constants.rb +11 -9
- data/lib/reek/smell_detectors/too_many_instance_variables.rb +11 -6
- data/lib/reek/smell_detectors/too_many_methods.rb +12 -7
- data/lib/reek/smell_detectors/too_many_statements.rb +11 -6
- data/lib/reek/smell_detectors/uncommunicative_method_name.rb +11 -11
- data/lib/reek/smell_detectors/uncommunicative_module_name.rb +15 -18
- data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +18 -22
- data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +27 -27
- data/lib/reek/smell_detectors/unused_parameters.rb +5 -6
- data/lib/reek/smell_detectors/unused_private_method.rb +14 -20
- data/lib/reek/smell_detectors/utility_function.rb +13 -16
- data/lib/reek/smell_detectors.rb +2 -1
- data/lib/reek/smell_warning.rb +16 -8
- data/lib/reek/source/source_code.rb +65 -46
- data/lib/reek/source/source_locator.rb +9 -8
- data/lib/reek/spec/should_reek.rb +3 -2
- data/lib/reek/spec/should_reek_of.rb +13 -26
- data/lib/reek/spec/should_reek_only_of.rb +5 -4
- data/lib/reek/spec/smell_matcher.rb +2 -1
- data/lib/reek/spec.rb +7 -6
- data/lib/reek/tree_dresser.rb +9 -8
- data/lib/reek/version.rb +2 -1
- data/lib/reek.rb +1 -0
- data/reek.gemspec +5 -6
- 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/factories/factories.rb +2 -13
- data/spec/reek/ast/node_spec.rb +103 -10
- data/spec/reek/ast/reference_collector_spec.rb +1 -1
- data/spec/reek/ast/sexp_extensions_spec.rb +15 -34
- data/spec/reek/cli/application_spec.rb +52 -42
- data/spec/reek/cli/command/todo_list_command_spec.rb +6 -4
- data/spec/reek/cli/silencer_spec.rb +28 -0
- data/spec/reek/code_comment_spec.rb +31 -38
- data/spec/reek/configuration/app_configuration_spec.rb +46 -33
- data/spec/reek/configuration/configuration_file_finder_spec.rb +133 -51
- data/spec/reek/configuration/default_directive_spec.rb +1 -1
- data/spec/reek/configuration/directory_directives_spec.rb +6 -7
- data/spec/reek/configuration/excluded_paths_spec.rb +6 -6
- 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 +70 -106
- data/spec/reek/context/ghost_context_spec.rb +9 -9
- data/spec/reek/context/method_context_spec.rb +2 -2
- data/spec/reek/context/module_context_spec.rb +3 -3
- data/spec/reek/context/root_context_spec.rb +1 -1
- data/spec/reek/context/statement_counter_spec.rb +1 -0
- data/spec/reek/context_builder_spec.rb +20 -0
- data/spec/reek/documentation_link_spec.rb +20 -0
- data/spec/reek/errors/base_error_spec.rb +13 -0
- data/spec/reek/examiner_spec.rb +137 -29
- data/spec/reek/rake/task_spec.rb +25 -2
- data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +82 -78
- data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +6 -6
- data/spec/reek/report/code_climate/code_climate_report_spec.rb +22 -22
- 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 +3 -3
- data/spec/reek/report/yaml_report_spec.rb +17 -46
- data/spec/reek/report_spec.rb +3 -3
- data/spec/reek/smell_detectors/base_detector_spec.rb +4 -5
- data/spec/reek/smell_detectors/boolean_parameter_spec.rb +2 -2
- data/spec/reek/smell_detectors/class_variable_spec.rb +26 -32
- data/spec/reek/smell_detectors/control_parameter_spec.rb +34 -4
- data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +3 -3
- data/spec/reek/smell_detectors/feature_envy_spec.rb +47 -2
- data/spec/reek/smell_detectors/irresponsible_module_spec.rb +59 -21
- data/spec/reek/smell_detectors/{prima_donna_method_spec.rb → missing_safe_method_spec.rb} +10 -10
- data/spec/reek/smell_detectors/module_initialize_spec.rb +14 -0
- data/spec/reek/smell_detectors/nested_iterators_spec.rb +1 -1
- 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 +36 -15
- data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +9 -9
- data/spec/reek/smell_detectors/unused_parameters_spec.rb +3 -3
- data/spec/reek/smell_detectors/unused_private_method_spec.rb +21 -10
- data/spec/reek/smell_detectors/utility_function_spec.rb +57 -5
- data/spec/reek/smell_warning_spec.rb +12 -8
- data/spec/reek/source/source_code_spec.rb +27 -38
- data/spec/reek/source/source_locator_spec.rb +42 -12
- data/spec/reek/spec/should_reek_of_spec.rb +25 -30
- data/spec/reek/spec/should_reek_only_of_spec.rb +2 -2
- data/spec/reek/spec/should_reek_spec.rb +8 -8
- data/spec/reek/spec/smell_matcher_spec.rb +23 -23
- data/spec/reek/tree_dresser_spec.rb +12 -17
- data/spec/spec_helper.rb +7 -17
- data/tasks/configuration.rake +8 -5
- metadata +77 -40
- data/defaults.reek +0 -128
- data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
- data/lib/reek/errors/parse_error.rb +0 -19
- data/lib/reek/report/formatter/heading_formatter.rb +0 -51
- data/lib/reek/report/formatter/location_formatter.rb +0 -41
- data/lib/reek/report/formatter/progress_formatter.rb +0 -80
- data/lib/reek/report/formatter/simple_warning_formatter.rb +0 -35
- data/lib/reek/report/formatter/wiki_link_warning_formatter.rb +0 -35
- data/lib/reek/report/formatter.rb +0 -32
- 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/{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
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -19,12 +20,12 @@ module Reek
|
|
|
19
20
|
|
|
20
21
|
# The name of the config field that sets the maximum depth
|
|
21
22
|
# of nested iterators to be permitted within any single method.
|
|
22
|
-
MAX_ALLOWED_NESTING_KEY = 'max_allowed_nesting'
|
|
23
|
+
MAX_ALLOWED_NESTING_KEY = 'max_allowed_nesting'
|
|
23
24
|
DEFAULT_MAX_ALLOWED_NESTING = 1
|
|
24
25
|
|
|
25
26
|
# The name of the config field that sets the names of any
|
|
26
27
|
# methods for which nesting should not be considered
|
|
27
|
-
IGNORE_ITERATORS_KEY = 'ignore_iterators'
|
|
28
|
+
IGNORE_ITERATORS_KEY = 'ignore_iterators'
|
|
28
29
|
DEFAULT_IGNORE_ITERATORS = ['tap'].freeze
|
|
29
30
|
|
|
30
31
|
def self.default_config
|
|
@@ -40,14 +41,10 @@ module Reek
|
|
|
40
41
|
#
|
|
41
42
|
# @return [Array<SmellWarning>]
|
|
42
43
|
#
|
|
43
|
-
def sniff
|
|
44
|
-
|
|
45
|
-
violations = find_violations ctx
|
|
46
|
-
|
|
47
|
-
violations.group_by(&:depth).map do |depth, group|
|
|
44
|
+
def sniff
|
|
45
|
+
find_violations.group_by(&:depth).map do |depth, group|
|
|
48
46
|
lines = group.map(&:line)
|
|
49
47
|
smell_warning(
|
|
50
|
-
context: ctx,
|
|
51
48
|
lines: lines,
|
|
52
49
|
message: "contains iterators nested #{depth} deep",
|
|
53
50
|
parameters: { depth: depth })
|
|
@@ -56,8 +53,6 @@ module Reek
|
|
|
56
53
|
|
|
57
54
|
private
|
|
58
55
|
|
|
59
|
-
attr_accessor :ignore_iterators
|
|
60
|
-
|
|
61
56
|
# Finds the set of independent most deeply nested iterators that are
|
|
62
57
|
# nested more deeply than allowed.
|
|
63
58
|
#
|
|
@@ -68,10 +63,8 @@ module Reek
|
|
|
68
63
|
#
|
|
69
64
|
# @return [Array<Iterator>]
|
|
70
65
|
#
|
|
71
|
-
def find_violations
|
|
72
|
-
|
|
73
|
-
max_allowed_nesting = max_nesting(ctx)
|
|
74
|
-
candidates.select { |it| it.depth > max_allowed_nesting }
|
|
66
|
+
def find_violations
|
|
67
|
+
find_candidates.select { |it| it.depth > max_allowed_nesting }
|
|
75
68
|
end
|
|
76
69
|
|
|
77
70
|
# Finds the set of independent most deeply nested iterators regardless of
|
|
@@ -79,9 +72,8 @@ module Reek
|
|
|
79
72
|
#
|
|
80
73
|
# @return [Array<Iterator>]
|
|
81
74
|
#
|
|
82
|
-
def find_candidates
|
|
83
|
-
exp
|
|
84
|
-
scout(exp: exp, depth: 0)
|
|
75
|
+
def find_candidates
|
|
76
|
+
scout(exp: expression, depth: 0)
|
|
85
77
|
end
|
|
86
78
|
|
|
87
79
|
# A little digression into parser's sexp is necessary here:
|
|
@@ -101,10 +93,11 @@ module Reek
|
|
|
101
93
|
#
|
|
102
94
|
# @return [Array<Iterator>]
|
|
103
95
|
#
|
|
104
|
-
# :reek:TooManyStatements
|
|
96
|
+
# @quality :reek:TooManyStatements { max_statements: 6 }
|
|
105
97
|
def scout(exp:, depth:)
|
|
106
98
|
return [] unless exp
|
|
107
|
-
|
|
99
|
+
# Find all non-nested blocks in this expression
|
|
100
|
+
exp.each_node([:block], [:block]).flat_map do |iterator|
|
|
108
101
|
new_depth = increment_depth(iterator, depth)
|
|
109
102
|
# 1st case: we recurse down the given block of the iterator. In this case
|
|
110
103
|
# we need to check if we should increment the depth.
|
|
@@ -120,19 +113,19 @@ module Reek
|
|
|
120
113
|
end
|
|
121
114
|
end
|
|
122
115
|
|
|
123
|
-
def
|
|
124
|
-
|
|
116
|
+
def ignore_iterators
|
|
117
|
+
@ignore_iterators ||= value(IGNORE_ITERATORS_KEY, context)
|
|
125
118
|
end
|
|
126
119
|
|
|
127
120
|
def increment_depth(iterator, depth)
|
|
128
121
|
ignored_iterator?(iterator) ? depth : depth + 1
|
|
129
122
|
end
|
|
130
123
|
|
|
131
|
-
def
|
|
132
|
-
value(MAX_ALLOWED_NESTING_KEY,
|
|
124
|
+
def max_allowed_nesting
|
|
125
|
+
@max_allowed_nesting ||= value(MAX_ALLOWED_NESTING_KEY, context)
|
|
133
126
|
end
|
|
134
127
|
|
|
135
|
-
# :reek:FeatureEnvy
|
|
128
|
+
# @quality :reek:FeatureEnvy
|
|
136
129
|
def ignored_iterator?(exp)
|
|
137
130
|
ignore_iterators.any? { |pattern| /#{pattern}/ =~ exp.call.name } ||
|
|
138
131
|
exp.without_block_arguments?
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -8,11 +9,10 @@ module Reek
|
|
|
8
9
|
#
|
|
9
10
|
# See {file:docs/Nil-Check.md} for details.
|
|
10
11
|
class NilCheck < BaseDetector
|
|
11
|
-
def sniff
|
|
12
|
-
lines =
|
|
12
|
+
def sniff
|
|
13
|
+
lines = detect_nodes.map(&:line)
|
|
13
14
|
if lines.any?
|
|
14
15
|
[smell_warning(
|
|
15
|
-
context: ctx,
|
|
16
16
|
lines: lines,
|
|
17
17
|
message: 'performs a nil-check')]
|
|
18
18
|
else
|
|
@@ -20,19 +20,13 @@ module Reek
|
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
class NodeDetector
|
|
25
|
-
attr_reader :ctx
|
|
26
|
-
def initialize(ctx)
|
|
27
|
-
@ctx = ctx
|
|
28
|
-
end
|
|
23
|
+
private
|
|
29
24
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
end
|
|
25
|
+
def detect_nodes
|
|
26
|
+
finders = [NodeFinder.new(context, :send, NilCallNodeDetector),
|
|
27
|
+
NodeFinder.new(context, :when, NilWhenNodeDetector),
|
|
28
|
+
NodeFinder.new(context, :csend, SafeNavigationNodeDetector)]
|
|
29
|
+
finders.flat_map(&:smelly_nodes)
|
|
36
30
|
end
|
|
37
31
|
|
|
38
32
|
#
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative '../ast/node'
|
|
3
4
|
require_relative 'base_detector'
|
|
4
5
|
|
|
@@ -27,7 +28,7 @@ module Reek
|
|
|
27
28
|
class RepeatedConditional < BaseDetector
|
|
28
29
|
# The name of the config field that sets the maximum number of
|
|
29
30
|
# identical conditionals permitted within any single class.
|
|
30
|
-
MAX_IDENTICAL_IFS_KEY = 'max_ifs'
|
|
31
|
+
MAX_IDENTICAL_IFS_KEY = 'max_ifs'
|
|
31
32
|
DEFAULT_MAX_IFS = 2
|
|
32
33
|
|
|
33
34
|
BLOCK_GIVEN_CONDITION = ::Parser::AST::Node.new(:send, [nil, :block_given?])
|
|
@@ -45,38 +46,40 @@ module Reek
|
|
|
45
46
|
#
|
|
46
47
|
# @return [Array<SmellWarning>]
|
|
47
48
|
#
|
|
48
|
-
# :reek:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
max_identical_ifs = value(MAX_IDENTICAL_IFS_KEY, ctx)
|
|
52
|
-
conditional_counts(ctx).select do |_key, lines|
|
|
49
|
+
# @quality :reek:DuplicateMethodCall { max_calls: 2 }
|
|
50
|
+
def sniff
|
|
51
|
+
conditional_counts.select do |_key, lines|
|
|
53
52
|
lines.length > max_identical_ifs
|
|
54
53
|
end.map do |key, lines|
|
|
55
54
|
occurs = lines.length
|
|
56
55
|
expression = key.format_to_ruby
|
|
57
56
|
smell_warning(
|
|
58
|
-
context: ctx,
|
|
59
57
|
lines: lines,
|
|
60
58
|
message: "tests '#{expression}' at least #{occurs} times",
|
|
61
59
|
parameters: { name: expression, count: occurs })
|
|
62
60
|
end
|
|
63
61
|
end
|
|
64
62
|
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def max_identical_ifs
|
|
66
|
+
@max_identical_ifs ||= value(MAX_IDENTICAL_IFS_KEY, context)
|
|
67
|
+
end
|
|
68
|
+
|
|
65
69
|
#
|
|
66
70
|
# Returns a Hash listing all of the conditional expressions in
|
|
67
71
|
# the given syntax tree together with the number of times each
|
|
68
72
|
# occurs. Ignores nested classes and modules.
|
|
69
73
|
#
|
|
70
|
-
# :reek:TooManyStatements
|
|
71
|
-
|
|
72
|
-
def conditional_counts(sexp)
|
|
74
|
+
# @quality :reek:TooManyStatements { max_statements: 9 }
|
|
75
|
+
def conditional_counts
|
|
73
76
|
result = Hash.new { |hash, key| hash[key] = [] }
|
|
74
77
|
collector = proc do |node|
|
|
75
78
|
next unless (condition = node.condition)
|
|
76
79
|
next if condition == BLOCK_GIVEN_CONDITION
|
|
77
80
|
result[condition].push(condition.line)
|
|
78
81
|
end
|
|
79
|
-
[:if, :case].each { |stmt|
|
|
82
|
+
[:if, :case].each { |stmt| context.local_nodes(stmt, &collector) }
|
|
80
83
|
result
|
|
81
84
|
end
|
|
82
85
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -25,26 +26,25 @@ module Reek
|
|
|
25
26
|
# class Foo < Bar; end;
|
|
26
27
|
#
|
|
27
28
|
# @return [Array<SmellWarning>]
|
|
28
|
-
def sniff
|
|
29
|
-
superclass =
|
|
29
|
+
def sniff
|
|
30
|
+
superclass = expression.superclass
|
|
30
31
|
|
|
31
32
|
return [] unless superclass
|
|
32
33
|
|
|
33
|
-
sniff_superclass
|
|
34
|
+
sniff_superclass superclass.name
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
private
|
|
37
38
|
|
|
38
|
-
def sniff_superclass(
|
|
39
|
+
def sniff_superclass(superclass_name)
|
|
39
40
|
return [] unless CORE_CLASSES.include?(superclass_name)
|
|
40
41
|
|
|
41
|
-
[build_smell_warning(
|
|
42
|
+
[build_smell_warning(superclass_name)]
|
|
42
43
|
end
|
|
43
44
|
|
|
44
|
-
def build_smell_warning(
|
|
45
|
+
def build_smell_warning(ancestor_name)
|
|
45
46
|
smell_attributes = {
|
|
46
|
-
|
|
47
|
-
lines: [ctx.exp.line],
|
|
47
|
+
lines: [source_line],
|
|
48
48
|
message: "inherits from core class '#{ancestor_name}'",
|
|
49
49
|
parameters: { ancestor: ancestor_name }
|
|
50
50
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -14,7 +15,7 @@ module Reek
|
|
|
14
15
|
class TooManyConstants < BaseDetector
|
|
15
16
|
# The name of the config field that sets the maximum number
|
|
16
17
|
# of constants permitted in a class.
|
|
17
|
-
MAX_ALLOWED_CONSTANTS_KEY = 'max_constants'
|
|
18
|
+
MAX_ALLOWED_CONSTANTS_KEY = 'max_constants'
|
|
18
19
|
DEFAULT_MAX_CONSTANTS = 5
|
|
19
20
|
IGNORED_NODES = [:module, :class].freeze
|
|
20
21
|
|
|
@@ -33,22 +34,23 @@ module Reek
|
|
|
33
34
|
#
|
|
34
35
|
# @return [Array<SmellWarning>]
|
|
35
36
|
#
|
|
36
|
-
def sniff
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
count = ctx.each_node(:casgn, IGNORED_NODES).delete_if(&:defines_module?).length
|
|
37
|
+
def sniff
|
|
38
|
+
count = context.local_nodes(:casgn).reject(&:defines_module?).length
|
|
40
39
|
|
|
41
40
|
return [] if count <= max_allowed_constants
|
|
42
41
|
|
|
43
|
-
build_smell_warning(
|
|
42
|
+
build_smell_warning(count)
|
|
44
43
|
end
|
|
45
44
|
|
|
46
45
|
private
|
|
47
46
|
|
|
48
|
-
def
|
|
47
|
+
def max_allowed_constants
|
|
48
|
+
value(MAX_ALLOWED_CONSTANTS_KEY, context)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def build_smell_warning(count)
|
|
49
52
|
[smell_warning(
|
|
50
|
-
|
|
51
|
-
lines: [ctx.exp.line],
|
|
53
|
+
lines: [source_line],
|
|
52
54
|
message: "has #{count} constants",
|
|
53
55
|
parameters: { count: count })]
|
|
54
56
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -14,7 +15,7 @@ module Reek
|
|
|
14
15
|
class TooManyInstanceVariables < BaseDetector
|
|
15
16
|
# The name of the config field that sets the maximum number of instance
|
|
16
17
|
# variables permitted in a class.
|
|
17
|
-
MAX_ALLOWED_IVARS_KEY = 'max_instance_variables'
|
|
18
|
+
MAX_ALLOWED_IVARS_KEY = 'max_instance_variables'
|
|
18
19
|
DEFAULT_MAX_IVARS = 4
|
|
19
20
|
|
|
20
21
|
def self.contexts
|
|
@@ -32,17 +33,21 @@ module Reek
|
|
|
32
33
|
#
|
|
33
34
|
# @return [Array<SmellWarning>]
|
|
34
35
|
#
|
|
35
|
-
def sniff
|
|
36
|
-
|
|
37
|
-
variables = ctx.local_nodes(:ivasgn, [:or_asgn]).map(&:name)
|
|
36
|
+
def sniff
|
|
37
|
+
variables = context.local_nodes(:ivasgn, [:or_asgn]).map(&:name)
|
|
38
38
|
count = variables.uniq.size
|
|
39
39
|
return [] if count <= max_allowed_ivars
|
|
40
40
|
[smell_warning(
|
|
41
|
-
|
|
42
|
-
lines: [ctx.exp.line],
|
|
41
|
+
lines: [source_line],
|
|
43
42
|
message: "has at least #{count} instance variables",
|
|
44
43
|
parameters: { count: count })]
|
|
45
44
|
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def max_allowed_ivars
|
|
49
|
+
value(MAX_ALLOWED_IVARS_KEY, context)
|
|
50
|
+
end
|
|
46
51
|
end
|
|
47
52
|
end
|
|
48
53
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -16,7 +17,7 @@ module Reek
|
|
|
16
17
|
class TooManyMethods < BaseDetector
|
|
17
18
|
# The name of the config field that sets the maximum number of methods
|
|
18
19
|
# permitted in a class.
|
|
19
|
-
MAX_ALLOWED_METHODS_KEY = 'max_methods'
|
|
20
|
+
MAX_ALLOWED_METHODS_KEY = 'max_methods'
|
|
20
21
|
DEFAULT_MAX_METHODS = 15
|
|
21
22
|
|
|
22
23
|
def self.contexts
|
|
@@ -30,21 +31,25 @@ module Reek
|
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
#
|
|
33
|
-
# Checks
|
|
34
|
+
# Checks context for too many methods
|
|
34
35
|
#
|
|
35
36
|
# @return [Array<SmellWarning>]
|
|
36
37
|
#
|
|
37
|
-
def sniff
|
|
38
|
-
max_allowed_methods = value(MAX_ALLOWED_METHODS_KEY, ctx)
|
|
38
|
+
def sniff
|
|
39
39
|
# TODO: Only checks instance methods!
|
|
40
|
-
actual =
|
|
40
|
+
actual = context.node_instance_methods.length
|
|
41
41
|
return [] if actual <= max_allowed_methods
|
|
42
42
|
[smell_warning(
|
|
43
|
-
|
|
44
|
-
lines: [ctx.exp.line],
|
|
43
|
+
lines: [source_line],
|
|
45
44
|
message: "has at least #{actual} methods",
|
|
46
45
|
parameters: { count: actual })]
|
|
47
46
|
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def max_allowed_methods
|
|
51
|
+
value(MAX_ALLOWED_METHODS_KEY, context)
|
|
52
|
+
end
|
|
48
53
|
end
|
|
49
54
|
end
|
|
50
55
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -12,7 +13,7 @@ module Reek
|
|
|
12
13
|
class TooManyStatements < BaseDetector
|
|
13
14
|
# The name of the config field that sets the maximum number of
|
|
14
15
|
# statements permitted in any method.
|
|
15
|
-
MAX_ALLOWED_STATEMENTS_KEY = 'max_statements'
|
|
16
|
+
MAX_ALLOWED_STATEMENTS_KEY = 'max_statements'
|
|
16
17
|
DEFAULT_MAX_STATEMENTS = 5
|
|
17
18
|
|
|
18
19
|
def self.default_config
|
|
@@ -26,16 +27,20 @@ module Reek
|
|
|
26
27
|
#
|
|
27
28
|
# @return [Array<SmellWarning>]
|
|
28
29
|
#
|
|
29
|
-
def sniff
|
|
30
|
-
|
|
31
|
-
count = ctx.number_of_statements
|
|
30
|
+
def sniff
|
|
31
|
+
count = context.number_of_statements
|
|
32
32
|
return [] if count <= max_allowed_statements
|
|
33
33
|
[smell_warning(
|
|
34
|
-
|
|
35
|
-
lines: [ctx.exp.line],
|
|
34
|
+
lines: [source_line],
|
|
36
35
|
message: "has approx #{count} statements",
|
|
37
36
|
parameters: { count: count })]
|
|
38
37
|
end
|
|
38
|
+
|
|
39
|
+
private
|
|
40
|
+
|
|
41
|
+
def max_allowed_statements
|
|
42
|
+
value(MAX_ALLOWED_STATEMENTS_KEY, context)
|
|
43
|
+
end
|
|
39
44
|
end
|
|
40
45
|
end
|
|
41
46
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -19,8 +20,8 @@ module Reek
|
|
|
19
20
|
#
|
|
20
21
|
# See {file:docs/Uncommunicative-Method-Name.md} for details.
|
|
21
22
|
class UncommunicativeMethodName < BaseDetector
|
|
22
|
-
REJECT_KEY = 'reject'
|
|
23
|
-
ACCEPT_KEY = 'accept'
|
|
23
|
+
REJECT_KEY = 'reject'
|
|
24
|
+
ACCEPT_KEY = 'accept'
|
|
24
25
|
DEFAULT_REJECT_PATTERNS = [/^[a-z]$/, /[0-9]$/, /[A-Z]/].freeze
|
|
25
26
|
DEFAULT_ACCEPT_PATTERNS = [].freeze
|
|
26
27
|
|
|
@@ -35,29 +36,28 @@ module Reek
|
|
|
35
36
|
#
|
|
36
37
|
# @return [Array<SmellWarning>]
|
|
37
38
|
#
|
|
38
|
-
def sniff
|
|
39
|
+
def sniff
|
|
39
40
|
name = context.name.to_s
|
|
40
|
-
return [] if acceptable_name?(name
|
|
41
|
+
return [] if acceptable_name?(name)
|
|
41
42
|
|
|
42
43
|
[smell_warning(
|
|
43
|
-
|
|
44
|
-
lines: [context.exp.line],
|
|
44
|
+
lines: [source_line],
|
|
45
45
|
message: "has the name '#{name}'",
|
|
46
46
|
parameters: { name: name })]
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
private
|
|
50
50
|
|
|
51
|
-
def acceptable_name?(name
|
|
52
|
-
accept_patterns
|
|
53
|
-
reject_patterns
|
|
51
|
+
def acceptable_name?(name)
|
|
52
|
+
accept_patterns.any? { |accept_pattern| name.match accept_pattern } ||
|
|
53
|
+
reject_patterns.none? { |reject_pattern| name.match reject_pattern }
|
|
54
54
|
end
|
|
55
55
|
|
|
56
|
-
def reject_patterns
|
|
56
|
+
def reject_patterns
|
|
57
57
|
Array value(REJECT_KEY, context)
|
|
58
58
|
end
|
|
59
59
|
|
|
60
|
-
def accept_patterns
|
|
60
|
+
def accept_patterns
|
|
61
61
|
Array value(ACCEPT_KEY, context)
|
|
62
62
|
end
|
|
63
63
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -20,13 +21,13 @@ module Reek
|
|
|
20
21
|
class UncommunicativeModuleName < BaseDetector
|
|
21
22
|
# The name of the config field that lists the regexps of
|
|
22
23
|
# smelly names to be reported.
|
|
23
|
-
REJECT_KEY = 'reject'
|
|
24
|
+
REJECT_KEY = 'reject'
|
|
24
25
|
DEFAULT_REJECT_PATTERNS = [/^.$/, /[0-9]$/].freeze
|
|
25
26
|
|
|
26
27
|
# The name of the config field that lists the specific names that are
|
|
27
28
|
# to be treated as exceptions; these names will not be reported as
|
|
28
29
|
# uncommunicative.
|
|
29
|
-
ACCEPT_KEY = 'accept'
|
|
30
|
+
ACCEPT_KEY = 'accept'
|
|
30
31
|
DEFAULT_ACCEPT_PATTERNS = [].freeze
|
|
31
32
|
|
|
32
33
|
def self.default_config
|
|
@@ -40,40 +41,36 @@ module Reek
|
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
#
|
|
43
|
-
# Checks the
|
|
44
|
+
# Checks the detector's context for uncommunicative names.
|
|
44
45
|
#
|
|
45
46
|
# @return [Array<SmellWarning>]
|
|
46
47
|
#
|
|
47
|
-
def sniff
|
|
48
|
+
def sniff
|
|
48
49
|
fully_qualified_name = context.full_name
|
|
49
|
-
|
|
50
|
-
module_name = exp.simple_name
|
|
50
|
+
module_name = expression.simple_name
|
|
51
51
|
|
|
52
|
-
return [] if acceptable_name?(
|
|
53
|
-
module_name: module_name,
|
|
52
|
+
return [] if acceptable_name?(module_name: module_name,
|
|
54
53
|
fully_qualified_name: fully_qualified_name)
|
|
55
54
|
|
|
56
55
|
[smell_warning(
|
|
57
|
-
|
|
58
|
-
lines: [exp.line],
|
|
56
|
+
lines: [source_line],
|
|
59
57
|
message: "has the name '#{module_name}'",
|
|
60
58
|
parameters: { name: module_name })]
|
|
61
59
|
end
|
|
62
60
|
|
|
63
61
|
private
|
|
64
62
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
reject_patterns(context).none? { |reject_pattern| module_name.match reject_pattern }
|
|
63
|
+
def acceptable_name?(module_name:, fully_qualified_name:)
|
|
64
|
+
accept_patterns.any? { |accept_pattern| fully_qualified_name.match accept_pattern } ||
|
|
65
|
+
reject_patterns.none? { |reject_pattern| module_name.match reject_pattern }
|
|
69
66
|
end
|
|
70
67
|
|
|
71
|
-
def reject_patterns
|
|
72
|
-
Array value(REJECT_KEY, context)
|
|
68
|
+
def reject_patterns
|
|
69
|
+
@reject_patterns ||= Array value(REJECT_KEY, context)
|
|
73
70
|
end
|
|
74
71
|
|
|
75
|
-
def accept_patterns
|
|
76
|
-
Array value(ACCEPT_KEY, context)
|
|
72
|
+
def accept_patterns
|
|
73
|
+
@accept_patterns ||= Array value(ACCEPT_KEY, context)
|
|
77
74
|
end
|
|
78
75
|
end
|
|
79
76
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -20,10 +21,10 @@ module Reek
|
|
|
20
21
|
#
|
|
21
22
|
# See {file:docs/Uncommunicative-Parameter-Name.md} for details.
|
|
22
23
|
class UncommunicativeParameterName < BaseDetector
|
|
23
|
-
REJECT_KEY = 'reject'
|
|
24
|
+
REJECT_KEY = 'reject'
|
|
24
25
|
DEFAULT_REJECT_PATTERNS = [/^.$/, /[0-9]$/, /[A-Z]/, /^_/].freeze
|
|
25
26
|
|
|
26
|
-
ACCEPT_KEY = 'accept'
|
|
27
|
+
ACCEPT_KEY = 'accept'
|
|
27
28
|
DEFAULT_ACCEPT_PATTERNS = [].freeze
|
|
28
29
|
|
|
29
30
|
def self.default_config
|
|
@@ -37,15 +38,14 @@ module Reek
|
|
|
37
38
|
#
|
|
38
39
|
# @return [Array<SmellWarning>]
|
|
39
40
|
#
|
|
40
|
-
def sniff
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
41
|
+
def sniff
|
|
42
|
+
params = expression.parameters.select do |param|
|
|
43
|
+
uncommunicative_parameter?(param)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
params.map(&:name).map do |name|
|
|
46
47
|
smell_warning(
|
|
47
|
-
|
|
48
|
-
lines: [expression.line],
|
|
48
|
+
lines: [source_line],
|
|
49
49
|
message: "has the parameter name '#{name}'",
|
|
50
50
|
parameters: { name: name.to_s })
|
|
51
51
|
end
|
|
@@ -53,27 +53,23 @@ module Reek
|
|
|
53
53
|
|
|
54
54
|
private
|
|
55
55
|
|
|
56
|
-
def
|
|
57
|
-
!acceptable_name?(
|
|
56
|
+
def uncommunicative_parameter?(parameter)
|
|
57
|
+
!acceptable_name?(parameter.plain_name) &&
|
|
58
|
+
(context.uses_param?(parameter) || !parameter.marked_unused?)
|
|
58
59
|
end
|
|
59
60
|
|
|
60
|
-
def acceptable_name?(name
|
|
61
|
-
accept_patterns
|
|
62
|
-
reject_patterns
|
|
61
|
+
def acceptable_name?(name)
|
|
62
|
+
accept_patterns.any? { |accept_pattern| name.match accept_pattern } ||
|
|
63
|
+
reject_patterns.none? { |reject_pattern| name.match reject_pattern }
|
|
63
64
|
end
|
|
64
65
|
|
|
65
|
-
def reject_patterns
|
|
66
|
+
def reject_patterns
|
|
66
67
|
Array value(REJECT_KEY, context)
|
|
67
68
|
end
|
|
68
69
|
|
|
69
|
-
def accept_patterns
|
|
70
|
+
def accept_patterns
|
|
70
71
|
Array value(ACCEPT_KEY, context)
|
|
71
72
|
end
|
|
72
|
-
|
|
73
|
-
# :reek:UtilityFunction
|
|
74
|
-
def sanitize(name)
|
|
75
|
-
name.to_s.gsub(/^[@\*\&]*/, '')
|
|
76
|
-
end
|
|
77
73
|
end
|
|
78
74
|
end
|
|
79
75
|
end
|