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
|
|
@@ -20,11 +21,10 @@ module Reek
|
|
|
20
21
|
#
|
|
21
22
|
# See {file:docs/Uncommunicative-Variable-Name.md} for details.
|
|
22
23
|
#
|
|
23
|
-
# :reek:DataClump: { max_copies: 4 }
|
|
24
24
|
class UncommunicativeVariableName < BaseDetector
|
|
25
25
|
# The name of the config field that lists the regexps of
|
|
26
26
|
# smelly names to be reported.
|
|
27
|
-
REJECT_KEY = 'reject'
|
|
27
|
+
REJECT_KEY = 'reject'
|
|
28
28
|
DEFAULT_REJECT_SET = [
|
|
29
29
|
/^.$/, # single-character names
|
|
30
30
|
/[0-9]$/, # any name ending with a number
|
|
@@ -34,7 +34,7 @@ module Reek
|
|
|
34
34
|
# The name of the config field that lists the specific names that are
|
|
35
35
|
# to be treated as exceptions; these names will not be reported as
|
|
36
36
|
# uncommunicative.
|
|
37
|
-
ACCEPT_KEY = 'accept'
|
|
37
|
+
ACCEPT_KEY = 'accept'
|
|
38
38
|
DEFAULT_ACCEPT_SET = [/^_$/].freeze
|
|
39
39
|
|
|
40
40
|
def self.default_config
|
|
@@ -52,14 +52,11 @@ module Reek
|
|
|
52
52
|
#
|
|
53
53
|
# @return [Array<SmellWarning>]
|
|
54
54
|
#
|
|
55
|
-
def sniff
|
|
56
|
-
|
|
57
|
-
self.accept_names = value(ACCEPT_KEY, ctx)
|
|
58
|
-
variable_names(ctx.exp).select do |name, _lines|
|
|
55
|
+
def sniff
|
|
56
|
+
variable_names.select do |name, _lines|
|
|
59
57
|
uncommunicative_variable_name?(name)
|
|
60
58
|
end.map do |name, lines|
|
|
61
59
|
smell_warning(
|
|
62
|
-
context: ctx,
|
|
63
60
|
lines: lines,
|
|
64
61
|
message: "has the variable name '#{name}'",
|
|
65
62
|
parameters: { name: name.to_s })
|
|
@@ -68,6 +65,14 @@ module Reek
|
|
|
68
65
|
|
|
69
66
|
private
|
|
70
67
|
|
|
68
|
+
def reject_names
|
|
69
|
+
@reject_names ||= value(REJECT_KEY, context)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def accept_names
|
|
73
|
+
@accept_names ||= value(ACCEPT_KEY, context)
|
|
74
|
+
end
|
|
75
|
+
|
|
71
76
|
def uncommunicative_variable_name?(name)
|
|
72
77
|
sanitized_name = name.to_s.gsub(/^[@\*\&]*/, '')
|
|
73
78
|
!acceptable_name?(sanitized_name)
|
|
@@ -78,34 +83,31 @@ module Reek
|
|
|
78
83
|
Array(reject_names).none? { |reject_pattern| name.match reject_pattern }
|
|
79
84
|
end
|
|
80
85
|
|
|
81
|
-
|
|
82
|
-
def variable_names(exp)
|
|
86
|
+
def variable_names
|
|
83
87
|
result = Hash.new { |hash, key| hash[key] = [] }
|
|
84
|
-
find_assignment_variable_names(
|
|
85
|
-
find_block_argument_variable_names(
|
|
86
|
-
result
|
|
88
|
+
find_assignment_variable_names(result)
|
|
89
|
+
find_block_argument_variable_names(result)
|
|
90
|
+
result
|
|
87
91
|
end
|
|
88
92
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
assignment_nodes = exp.each_node(:lvasgn, [:class, :module, :defs, :def])
|
|
93
|
+
def find_assignment_variable_names(accumulator)
|
|
94
|
+
assignment_nodes = expression.each_node(:lvasgn, [:class, :module, :defs, :def]).to_a
|
|
92
95
|
|
|
93
|
-
case
|
|
96
|
+
case expression.type
|
|
94
97
|
when :class, :module
|
|
95
|
-
assignment_nodes +=
|
|
98
|
+
assignment_nodes += expression.each_node(:ivasgn, [:class, :module]).to_a
|
|
96
99
|
end
|
|
97
100
|
|
|
98
101
|
assignment_nodes.each { |asgn| accumulator[asgn.children.first].push(asgn.line) }
|
|
99
102
|
end
|
|
100
103
|
|
|
101
|
-
# :reek:
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
arg_search_exp = case exp.type
|
|
104
|
+
# @quality :reek:TooManyStatements { max_statements: 6 }
|
|
105
|
+
def find_block_argument_variable_names(accumulator)
|
|
106
|
+
arg_search_exp = case expression.type
|
|
105
107
|
when :class, :module
|
|
106
|
-
|
|
108
|
+
expression
|
|
107
109
|
when :defs, :def
|
|
108
|
-
|
|
110
|
+
expression.body
|
|
109
111
|
end
|
|
110
112
|
|
|
111
113
|
return unless arg_search_exp
|
|
@@ -127,15 +129,13 @@ module Reek
|
|
|
127
129
|
end
|
|
128
130
|
end
|
|
129
131
|
|
|
130
|
-
# :reek:UtilityFunction
|
|
132
|
+
# @quality :reek:UtilityFunction
|
|
131
133
|
def record_variable_name(exp, symbol, accumulator)
|
|
132
134
|
varname = symbol.to_s.sub(/^\*/, '')
|
|
133
135
|
return if varname == ''
|
|
134
136
|
var = varname.to_sym
|
|
135
137
|
accumulator[var].push(exp.line)
|
|
136
138
|
end
|
|
137
|
-
|
|
138
|
-
attr_accessor :accept_names, :reject_names
|
|
139
139
|
end
|
|
140
140
|
end
|
|
141
141
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -13,14 +14,12 @@ module Reek
|
|
|
13
14
|
#
|
|
14
15
|
# @return [Array<SmellWarning>]
|
|
15
16
|
#
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
ctx.unused_params.map do |param|
|
|
17
|
+
def sniff
|
|
18
|
+
return [] if context.uses_super_with_implicit_arguments?
|
|
19
|
+
context.unused_params.map do |param|
|
|
20
20
|
name = param.name.to_s
|
|
21
21
|
smell_warning(
|
|
22
|
-
|
|
23
|
-
lines: [ctx.exp.line],
|
|
22
|
+
lines: [source_line],
|
|
24
23
|
message: "has unused parameter '#{name}'",
|
|
25
24
|
parameters: { name: name })
|
|
26
25
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'base_detector'
|
|
3
4
|
|
|
4
5
|
module Reek
|
|
@@ -31,15 +32,12 @@ module Reek
|
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
#
|
|
34
|
-
# @param ctx [Context::ClassContext]
|
|
35
35
|
# @return [Array<SmellWarning>]
|
|
36
36
|
#
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
hits(ctx).map do |hit|
|
|
37
|
+
def sniff
|
|
38
|
+
hits.map do |hit|
|
|
40
39
|
name = hit.name
|
|
41
40
|
smell_warning(
|
|
42
|
-
context: ctx,
|
|
43
41
|
lines: [hit.line],
|
|
44
42
|
message: "has the unused private instance method '#{name}'",
|
|
45
43
|
parameters: { name: name.to_s })
|
|
@@ -49,37 +47,33 @@ module Reek
|
|
|
49
47
|
private
|
|
50
48
|
|
|
51
49
|
#
|
|
52
|
-
# @param ctx [Context::ClassContext]
|
|
53
50
|
# @return [Array<Hit>]
|
|
54
51
|
#
|
|
55
|
-
def hits
|
|
56
|
-
unused_private_methods
|
|
57
|
-
Hit.new(defined_method) unless ignore_method?(
|
|
52
|
+
def hits
|
|
53
|
+
unused_private_methods.map do |defined_method|
|
|
54
|
+
Hit.new(defined_method) unless ignore_method?(defined_method)
|
|
58
55
|
end.compact
|
|
59
56
|
end
|
|
60
57
|
|
|
61
58
|
#
|
|
62
|
-
# @param ctx [Context::ClassContext]
|
|
63
59
|
# @return [Array<Context::MethodContext]
|
|
64
60
|
#
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
called_method_names = ctx.instance_method_calls.map(&:name)
|
|
61
|
+
def unused_private_methods
|
|
62
|
+
defined_private_methods = context.defined_instance_methods(visibility: :private)
|
|
63
|
+
called_method_names = context.instance_method_calls.map(&:name)
|
|
69
64
|
|
|
70
|
-
defined_private_methods.
|
|
71
|
-
|
|
65
|
+
defined_private_methods.reject do |defined_method|
|
|
66
|
+
called_method_names.include?(defined_method.name)
|
|
72
67
|
end
|
|
73
68
|
end
|
|
74
69
|
|
|
75
70
|
#
|
|
76
|
-
# @param
|
|
71
|
+
# @param method [Context::MethodContext]
|
|
77
72
|
# @return [Boolean]
|
|
78
73
|
#
|
|
79
|
-
|
|
80
|
-
def ignore_method?(ctx, method)
|
|
74
|
+
def ignore_method?(method)
|
|
81
75
|
# ignore_contexts will be e.g. ["Foo::Smelly#my_method", "..."]
|
|
82
|
-
ignore_contexts = value(EXCLUDE_KEY,
|
|
76
|
+
ignore_contexts = value(EXCLUDE_KEY, context)
|
|
83
77
|
ignore_contexts.any? do |ignore_context|
|
|
84
78
|
full_name = "#{method.parent.full_name}##{method.name}"
|
|
85
79
|
full_name[ignore_context]
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative '../ast/reference_collector'
|
|
3
4
|
require_relative 'base_detector'
|
|
4
5
|
|
|
@@ -37,7 +38,7 @@ module Reek
|
|
|
37
38
|
#
|
|
38
39
|
# See {file:docs/Utility-Function.md} for details.
|
|
39
40
|
class UtilityFunction < BaseDetector
|
|
40
|
-
PUBLIC_METHODS_ONLY_KEY = 'public_methods_only'
|
|
41
|
+
PUBLIC_METHODS_ONLY_KEY = 'public_methods_only'
|
|
41
42
|
PUBLIC_METHODS_ONLY_DEFAULT = false
|
|
42
43
|
|
|
43
44
|
def self.default_config
|
|
@@ -55,30 +56,26 @@ module Reek
|
|
|
55
56
|
#
|
|
56
57
|
# @return [Array<SmellWarning>]
|
|
57
58
|
#
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return [] if
|
|
62
|
-
return [] if
|
|
63
|
-
return [] if num_helper_methods(ctx).zero?
|
|
64
|
-
return [] if ignore_method?(ctx)
|
|
59
|
+
def sniff
|
|
60
|
+
return [] if context.singleton_method? || context.module_function?
|
|
61
|
+
return [] if context.references_self?
|
|
62
|
+
return [] if num_helper_methods.zero?
|
|
63
|
+
return [] if ignore_method?
|
|
65
64
|
|
|
66
65
|
[smell_warning(
|
|
67
|
-
|
|
68
|
-
lines: [ctx.exp.line],
|
|
66
|
+
lines: [source_line],
|
|
69
67
|
message: "doesn't depend on instance state (maybe move it to another class?)")]
|
|
70
68
|
end
|
|
71
69
|
|
|
72
70
|
private
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
method_ctx.local_nodes(:send).length
|
|
72
|
+
def num_helper_methods
|
|
73
|
+
context.local_nodes(:send).to_a.length
|
|
77
74
|
end
|
|
78
75
|
|
|
79
|
-
def ignore_method?
|
|
80
|
-
|
|
81
|
-
value(PUBLIC_METHODS_ONLY_KEY,
|
|
76
|
+
def ignore_method?
|
|
77
|
+
context.non_public_visibility? &&
|
|
78
|
+
value(PUBLIC_METHODS_ONLY_KEY, context)
|
|
82
79
|
end
|
|
83
80
|
end
|
|
84
81
|
end
|
data/lib/reek/smell_detectors.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative 'smell_detectors/attribute'
|
|
3
4
|
require_relative 'smell_detectors/boolean_parameter'
|
|
4
5
|
require_relative 'smell_detectors/class_variable'
|
|
@@ -14,7 +15,7 @@ require_relative 'smell_detectors/manual_dispatch'
|
|
|
14
15
|
require_relative 'smell_detectors/module_initialize'
|
|
15
16
|
require_relative 'smell_detectors/nested_iterators'
|
|
16
17
|
require_relative 'smell_detectors/nil_check'
|
|
17
|
-
require_relative 'smell_detectors/
|
|
18
|
+
require_relative 'smell_detectors/missing_safe_method'
|
|
18
19
|
require_relative 'smell_detectors/repeated_conditional'
|
|
19
20
|
require_relative 'smell_detectors/subclassed_from_core_class'
|
|
20
21
|
require_relative 'smell_detectors/too_many_instance_variables'
|
data/lib/reek/smell_warning.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'forwardable'
|
|
4
|
+
require_relative 'documentation_link'
|
|
3
5
|
|
|
4
6
|
module Reek
|
|
5
7
|
#
|
|
@@ -7,7 +9,7 @@ module Reek
|
|
|
7
9
|
#
|
|
8
10
|
# @public
|
|
9
11
|
#
|
|
10
|
-
# :reek:TooManyInstanceVariables
|
|
12
|
+
# @quality :reek:TooManyInstanceVariables { max_instance_variables: 6 }
|
|
11
13
|
class SmellWarning
|
|
12
14
|
include Comparable
|
|
13
15
|
extend Forwardable
|
|
@@ -20,7 +22,7 @@ module Reek
|
|
|
20
22
|
# objects yourself. This is why the initializer is not part of the
|
|
21
23
|
# public API.
|
|
22
24
|
#
|
|
23
|
-
# :reek:LongParameterList
|
|
25
|
+
# @quality :reek:LongParameterList { max_params: 6 }
|
|
24
26
|
def initialize(smell_detector, context: '', lines:, message:,
|
|
25
27
|
source:, parameters: {})
|
|
26
28
|
@smell_detector = smell_detector
|
|
@@ -54,7 +56,9 @@ module Reek
|
|
|
54
56
|
base_hash.merge(stringified_params)
|
|
55
57
|
end
|
|
56
58
|
|
|
57
|
-
|
|
59
|
+
def yaml_hash
|
|
60
|
+
to_hash.merge('documentation_link' => explanatory_link)
|
|
61
|
+
end
|
|
58
62
|
|
|
59
63
|
def base_message
|
|
60
64
|
"#{smell_type}: #{context} #{message}"
|
|
@@ -64,6 +68,10 @@ module Reek
|
|
|
64
68
|
smell_detector.class
|
|
65
69
|
end
|
|
66
70
|
|
|
71
|
+
def explanatory_link
|
|
72
|
+
DocumentationLink.build(smell_type)
|
|
73
|
+
end
|
|
74
|
+
|
|
67
75
|
protected
|
|
68
76
|
|
|
69
77
|
def identifying_values
|
|
@@ -74,11 +82,11 @@ module Reek
|
|
|
74
82
|
|
|
75
83
|
def base_hash
|
|
76
84
|
{
|
|
77
|
-
'context'
|
|
78
|
-
'lines'
|
|
79
|
-
'message'
|
|
80
|
-
'smell_type'
|
|
81
|
-
'source'
|
|
85
|
+
'context' => context,
|
|
86
|
+
'lines' => lines,
|
|
87
|
+
'message' => message,
|
|
88
|
+
'smell_type' => smell_type,
|
|
89
|
+
'source' => source
|
|
82
90
|
}
|
|
83
91
|
end
|
|
84
92
|
end
|
|
@@ -1,65 +1,94 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative '../cli/silencer'
|
|
3
|
-
Reek::CLI::Silencer.
|
|
4
|
-
require 'parser/ruby23'
|
|
5
|
-
end
|
|
4
|
+
Reek::CLI::Silencer.without_warnings { require 'parser/ruby25' }
|
|
6
5
|
require_relative '../tree_dresser'
|
|
7
6
|
require_relative '../ast/node'
|
|
8
|
-
require_relative '../
|
|
7
|
+
require_relative '../ast/builder'
|
|
9
8
|
|
|
10
9
|
# Opt in to new way of representing lambdas
|
|
11
|
-
|
|
10
|
+
Reek::AST::Builder.emit_lambda = true
|
|
12
11
|
|
|
13
12
|
module Reek
|
|
14
13
|
module Source
|
|
15
14
|
#
|
|
16
|
-
# A +
|
|
15
|
+
# A +SourceCode+ object represents a chunk of Ruby source code.
|
|
17
16
|
#
|
|
18
17
|
class SourceCode
|
|
19
|
-
IO_IDENTIFIER = 'STDIN'
|
|
20
|
-
STRING_IDENTIFIER = 'string'
|
|
21
|
-
|
|
22
|
-
attr_reader :origin
|
|
18
|
+
IO_IDENTIFIER = 'STDIN'
|
|
19
|
+
STRING_IDENTIFIER = 'string'
|
|
23
20
|
|
|
24
21
|
# Initializer.
|
|
25
22
|
#
|
|
26
|
-
#
|
|
27
|
-
# origin
|
|
28
|
-
#
|
|
29
|
-
|
|
30
|
-
|
|
23
|
+
# @param source [File|Pathname|IO|String] Ruby source code
|
|
24
|
+
# @param origin [String] Origin of the source code. Will be determined
|
|
25
|
+
# automatically if left blank.
|
|
26
|
+
# @param parser the parser to use for generating AST's out of the given code
|
|
27
|
+
def initialize(source:, origin: nil, parser: self.class.default_parser)
|
|
31
28
|
@origin = origin
|
|
32
29
|
@parser = parser
|
|
30
|
+
@source = source
|
|
33
31
|
end
|
|
34
32
|
|
|
35
33
|
# Initializes an instance of SourceCode given a source.
|
|
36
|
-
# This source can come via
|
|
34
|
+
# This source can come via several different ways:
|
|
37
35
|
# - from Files or Pathnames a la `reek lib/reek/`
|
|
38
36
|
# - from IO (STDIN) a la `echo "class Foo; end" | reek`
|
|
39
37
|
# - from String via our rspec matchers a la `expect("class Foo; end").to reek`
|
|
38
|
+
# - from an existing SourceCode object. This is passed through unchanged
|
|
40
39
|
#
|
|
41
|
-
# @param source [File|IO|String]
|
|
40
|
+
# @param source [SourceCode|File|Pathname|IO|String] the given source
|
|
41
|
+
# @param origin [String|nil]
|
|
42
42
|
#
|
|
43
43
|
# @return an instance of SourceCode
|
|
44
|
-
|
|
45
|
-
def self.from(source)
|
|
44
|
+
def self.from(source, origin: nil)
|
|
46
45
|
case source
|
|
47
|
-
when
|
|
48
|
-
|
|
49
|
-
when Pathname then new(code: source.read, origin: source.to_s)
|
|
50
|
-
when String then new(code: source, origin: STRING_IDENTIFIER)
|
|
46
|
+
when self then source
|
|
47
|
+
else new(source: source, origin: origin)
|
|
51
48
|
end
|
|
52
49
|
end
|
|
53
50
|
|
|
54
|
-
|
|
51
|
+
def syntax_tree
|
|
52
|
+
@syntax_tree ||= parse
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def self.default_parser
|
|
56
|
+
Parser::Ruby25.new(AST::Builder.new).tap do |parser|
|
|
57
|
+
diagnostics = parser.diagnostics
|
|
58
|
+
diagnostics.all_errors_are_fatal = true
|
|
59
|
+
diagnostics.ignore_warnings = true
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def origin
|
|
64
|
+
@origin ||=
|
|
65
|
+
case source
|
|
66
|
+
when File then source.path
|
|
67
|
+
when IO then IO_IDENTIFIER
|
|
68
|
+
when Pathname then source.to_s
|
|
69
|
+
when String then STRING_IDENTIFIER
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def code
|
|
76
|
+
@code ||=
|
|
77
|
+
case source
|
|
78
|
+
when File, Pathname then source.read
|
|
79
|
+
when IO then source.readlines.join
|
|
80
|
+
when String then source
|
|
81
|
+
end.force_encoding(Encoding::UTF_8)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
attr_reader :parser, :source
|
|
85
|
+
|
|
86
|
+
# Parses the given code into an AST and associates the source code comments with it.
|
|
55
87
|
# This AST is then traversed by a TreeDresser which adorns the nodes in the AST
|
|
56
88
|
# with our SexpExtensions.
|
|
57
89
|
# Finally this AST is returned where each node is an anonymous subclass of Reek::AST::Node
|
|
58
90
|
#
|
|
59
|
-
#
|
|
60
|
-
# a warning and then just continue.
|
|
61
|
-
#
|
|
62
|
-
# Given this @source:
|
|
91
|
+
# Given this @code:
|
|
63
92
|
#
|
|
64
93
|
# # comment about C
|
|
65
94
|
# class C
|
|
@@ -80,26 +109,16 @@ module Reek
|
|
|
80
109
|
# where each node is possibly adorned with our SexpExtensions (see ast/ast_node_class_map
|
|
81
110
|
# and ast/sexp_extensions for details).
|
|
82
111
|
#
|
|
83
|
-
#
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
begin
|
|
89
|
-
ast, comments = parser.parse_with_comments(source, origin)
|
|
90
|
-
rescue Racc::ParseError, Parser::SyntaxError => error
|
|
91
|
-
raise Errors::ParseError, origin: origin, original_exception: error
|
|
92
|
-
end
|
|
112
|
+
# @return Reek::AST::Node the AST presentation for the given code
|
|
113
|
+
def parse
|
|
114
|
+
buffer = Parser::Source::Buffer.new(origin, 1)
|
|
115
|
+
buffer.source = code
|
|
116
|
+
ast, comments = parser.parse_with_comments(buffer)
|
|
93
117
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
end
|
|
118
|
+
# See https://whitequark.github.io/parser/Parser/Source/Comment/Associator.html
|
|
119
|
+
comment_map = Parser::Source::Comment.associate(ast, comments)
|
|
120
|
+
TreeDresser.new.dress(ast, comment_map) || AST::Node.new(:empty)
|
|
98
121
|
end
|
|
99
|
-
|
|
100
|
-
private
|
|
101
|
-
|
|
102
|
-
attr_reader :parser, :source
|
|
103
122
|
end
|
|
104
123
|
end
|
|
105
124
|
end
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require 'find'
|
|
3
4
|
require 'pathname'
|
|
4
5
|
|
|
@@ -23,7 +24,7 @@ module Reek
|
|
|
23
24
|
# Traverses all paths we initialized the SourceLocator with, finds
|
|
24
25
|
# all relevant Ruby files and returns them as a list.
|
|
25
26
|
#
|
|
26
|
-
# @return [Array<Pathname>]
|
|
27
|
+
# @return [Array<Pathname>] Ruby paths found
|
|
27
28
|
def sources
|
|
28
29
|
source_paths
|
|
29
30
|
end
|
|
@@ -32,8 +33,8 @@ module Reek
|
|
|
32
33
|
|
|
33
34
|
attr_reader :configuration, :paths, :options
|
|
34
35
|
|
|
35
|
-
# :reek:TooManyStatements
|
|
36
|
-
# :reek:NestedIterators
|
|
36
|
+
# @quality :reek:TooManyStatements { max_statements: 7 }
|
|
37
|
+
# @quality :reek:NestedIterators { max_allowed_nesting: 2 }
|
|
37
38
|
def source_paths
|
|
38
39
|
paths.each_with_object([]) do |given_path, relevant_paths|
|
|
39
40
|
unless given_path.exist?
|
|
@@ -66,12 +67,12 @@ module Reek
|
|
|
66
67
|
configuration.path_excluded?(path)
|
|
67
68
|
end
|
|
68
69
|
|
|
69
|
-
# :reek:UtilityFunction
|
|
70
|
+
# @quality :reek:UtilityFunction
|
|
70
71
|
def print_no_such_file_error(path)
|
|
71
|
-
|
|
72
|
+
warn "Error: No such file - #{path}"
|
|
72
73
|
end
|
|
73
74
|
|
|
74
|
-
# :reek:UtilityFunction
|
|
75
|
+
# @quality :reek:UtilityFunction
|
|
75
76
|
def hidden_directory?(path)
|
|
76
77
|
path.basename.to_s.start_with? '.'
|
|
77
78
|
end
|
|
@@ -80,12 +81,12 @@ module Reek
|
|
|
80
81
|
path_excluded?(path) || hidden_directory?(path)
|
|
81
82
|
end
|
|
82
83
|
|
|
83
|
-
# :reek:UtilityFunction
|
|
84
|
+
# @quality :reek:UtilityFunction
|
|
84
85
|
def ruby_file?(path)
|
|
85
86
|
path.extname == '.rb'
|
|
86
87
|
end
|
|
87
88
|
|
|
88
|
-
# :reek:UtilityFunction
|
|
89
|
+
# @quality :reek:UtilityFunction
|
|
89
90
|
def current_directory?(path)
|
|
90
91
|
[Pathname.new('.'), Pathname.new('./')].include?(path)
|
|
91
92
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative '../examiner'
|
|
3
|
-
require_relative '../report/
|
|
4
|
+
require_relative '../report/simple_warning_formatter'
|
|
4
5
|
|
|
5
6
|
module Reek
|
|
6
7
|
module Spec
|
|
@@ -22,7 +23,7 @@ module Reek
|
|
|
22
23
|
end
|
|
23
24
|
|
|
24
25
|
def failure_message_when_negated
|
|
25
|
-
rpt = Report::
|
|
26
|
+
rpt = Report::SimpleWarningFormatter.new.format_list(examiner.smells)
|
|
26
27
|
"Expected no smells, but got:\n#{rpt}"
|
|
27
28
|
end
|
|
28
29
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
require_relative '../examiner'
|
|
3
4
|
require_relative 'smell_matcher'
|
|
5
|
+
require_relative '../configuration/app_configuration'
|
|
4
6
|
|
|
5
7
|
module Reek
|
|
6
8
|
module Spec
|
|
@@ -11,36 +13,31 @@ module Reek
|
|
|
11
13
|
class ShouldReekOf
|
|
12
14
|
include RSpec::Matchers::Composable
|
|
13
15
|
|
|
14
|
-
# Variant of Examiner that doesn't swallow exceptions
|
|
15
|
-
class UnsafeExaminer < Examiner
|
|
16
|
-
def run
|
|
17
|
-
examine_tree
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
16
|
attr_reader :failure_message, :failure_message_when_negated
|
|
22
17
|
|
|
23
|
-
def initialize(
|
|
18
|
+
def initialize(smell_type,
|
|
24
19
|
smell_details = {},
|
|
25
20
|
configuration = Configuration::AppConfiguration.default)
|
|
26
|
-
@smell_type =
|
|
21
|
+
@smell_type = smell_type.to_s
|
|
27
22
|
@smell_details = smell_details
|
|
28
|
-
configuration.load_values(
|
|
23
|
+
configuration.load_values(Configuration::AppConfiguration::DETECTORS_KEY =>
|
|
24
|
+
{ smell_type => { SmellConfiguration::ENABLED_KEY => true } })
|
|
29
25
|
@configuration = configuration
|
|
30
26
|
end
|
|
31
27
|
|
|
32
28
|
def matches?(source)
|
|
33
29
|
@matching_smell_types = nil
|
|
34
|
-
self.examiner =
|
|
35
|
-
|
|
36
|
-
|
|
30
|
+
self.examiner = Examiner.new(source,
|
|
31
|
+
filter_by_smells: [smell_type],
|
|
32
|
+
configuration: configuration)
|
|
37
33
|
set_failure_messages
|
|
38
34
|
matching_smell_details?
|
|
39
35
|
end
|
|
40
36
|
|
|
41
37
|
def with_config(config_hash)
|
|
42
38
|
new_configuration = Configuration::AppConfiguration.default
|
|
43
|
-
new_configuration.load_values(
|
|
39
|
+
new_configuration.load_values(Configuration::AppConfiguration::DETECTORS_KEY =>
|
|
40
|
+
{ smell_type => config_hash })
|
|
44
41
|
self.class.new(smell_type, smell_details, new_configuration)
|
|
45
42
|
end
|
|
46
43
|
|
|
@@ -88,7 +85,7 @@ module Reek
|
|
|
88
85
|
"#{smell_type} with smell details #{smell_details}, but it did"
|
|
89
86
|
end
|
|
90
87
|
|
|
91
|
-
# :reek:FeatureEnvy
|
|
88
|
+
# @quality :reek:FeatureEnvy
|
|
92
89
|
def all_relevant_smell_details_formatted
|
|
93
90
|
matching_smell_types.each_with_object([]).with_index do |(smell, accumulator), index|
|
|
94
91
|
accumulator << "#{index + 1}.)\n"
|
|
@@ -99,17 +96,7 @@ module Reek
|
|
|
99
96
|
end
|
|
100
97
|
|
|
101
98
|
def origin
|
|
102
|
-
examiner.
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
# :reek:UtilityFunction
|
|
106
|
-
def normalize(smell_type_or_class)
|
|
107
|
-
case smell_type_or_class
|
|
108
|
-
when Class
|
|
109
|
-
smell_type_or_class.smell_type
|
|
110
|
-
else
|
|
111
|
-
smell_type_or_class.to_s
|
|
112
|
-
end
|
|
99
|
+
examiner.origin
|
|
113
100
|
end
|
|
114
101
|
end
|
|
115
102
|
end
|