reek 6.0.2 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/dependabot.yml +13 -0
- data/.github/workflows/ruby.yml +57 -0
- data/.rubocop.yml +6 -12
- data/.rubocop_todo.yml +6 -4
- data/CHANGELOG.md +95 -0
- data/CONTRIBUTING.md +10 -10
- data/Dockerfile +1 -1
- data/Gemfile +8 -7
- data/README.md +29 -29
- data/bin/code_climate_reek +56 -8
- data/lib/reek/ast/ast_node_class_map.rb +1 -1
- data/lib/reek/ast/node.rb +1 -1
- data/lib/reek/ast/sexp_extensions/arguments.rb +20 -0
- data/lib/reek/ast/sexp_extensions/case.rb +1 -1
- data/lib/reek/ast/sexp_extensions/if.rb +1 -1
- data/lib/reek/ast/sexp_extensions/send.rb +22 -7
- data/lib/reek/cli/command/todo_list_command.rb +3 -3
- data/lib/reek/cli/options.rb +6 -6
- data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.rb +1 -1
- data/lib/reek/{report/code_climate → code_climate}/code_climate_configuration.yml +41 -41
- data/lib/reek/{report/code_climate → code_climate}/code_climate_fingerprint.rb +2 -2
- data/lib/reek/{report/code_climate → code_climate}/code_climate_formatter.rb +2 -4
- data/lib/reek/{report/code_climate → code_climate}/code_climate_report.rb +3 -3
- data/lib/reek/code_comment.rb +25 -20
- data/lib/reek/configuration/app_configuration.rb +5 -5
- data/lib/reek/configuration/configuration_converter.rb +1 -1
- data/lib/reek/configuration/configuration_file_finder.rb +5 -4
- data/lib/reek/configuration/default_directive.rb +1 -1
- data/lib/reek/configuration/directory_directives.rb +1 -1
- data/lib/reek/configuration/excluded_paths.rb +3 -2
- data/lib/reek/configuration/schema.rb +177 -0
- data/lib/reek/configuration/schema_validator.rb +12 -13
- data/lib/reek/context/attribute_context.rb +1 -1
- data/lib/reek/context/code_context.rb +1 -1
- data/lib/reek/context/method_context.rb +1 -1
- data/lib/reek/context/module_context.rb +4 -0
- data/lib/reek/context/refinement_context.rb +16 -0
- data/lib/reek/context/send_context.rb +7 -1
- data/lib/reek/context_builder.rb +17 -3
- data/lib/reek/documentation_link.rb +3 -5
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +2 -2
- data/lib/reek/errors/bad_detector_in_comment_error.rb +2 -2
- data/lib/reek/errors/encoding_error.rb +1 -1
- data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +2 -2
- data/lib/reek/errors/incomprehensible_source_error.rb +1 -1
- data/lib/reek/errors/legacy_comment_separator_error.rb +2 -2
- data/lib/reek/errors/syntax_error.rb +1 -1
- data/lib/reek/rake/task.rb +5 -5
- data/lib/reek/smell_detectors/base_detector.rb +1 -1
- data/lib/reek/smell_detectors/class_variable.rb +2 -2
- data/lib/reek/smell_detectors/control_parameter_helpers/candidate.rb +6 -6
- data/lib/reek/smell_detectors/control_parameter_helpers/control_parameter_finder.rb +1 -1
- data/lib/reek/smell_detectors/duplicate_method_call.rb +5 -5
- data/lib/reek/smell_detectors/instance_variable_assumption.rb +8 -8
- data/lib/reek/smell_detectors/nested_iterators.rb +4 -3
- data/lib/reek/smell_detectors/unused_private_method.rb +3 -2
- data/lib/reek/smell_warning.rb +1 -1
- data/lib/reek/source/source_locator.rb +1 -3
- data/lib/reek/spec/should_reek_of.rb +11 -9
- data/lib/reek/spec.rb +1 -1
- data/lib/reek/version.rb +2 -2
- data/reek.gemspec +29 -25
- metadata +37 -250
- data/.travis.yml +0 -40
- data/docs/API.md +0 -174
- data/docs/Attribute.md +0 -39
- data/docs/Basic-Smell-Options.md +0 -85
- data/docs/Boolean-Parameter.md +0 -54
- data/docs/Class-Variable.md +0 -40
- data/docs/Code-Smells.md +0 -39
- data/docs/Command-Line-Options.md +0 -119
- data/docs/Control-Couple.md +0 -26
- data/docs/Control-Parameter.md +0 -32
- data/docs/Data-Clump.md +0 -46
- data/docs/Duplicate-Method-Call.md +0 -264
- data/docs/Feature-Envy.md +0 -93
- data/docs/How-To-Write-New-Detectors.md +0 -132
- data/docs/How-reek-works-internally.md +0 -114
- data/docs/Instance-Variable-Assumption.md +0 -163
- data/docs/Irresponsible-Module.md +0 -47
- data/docs/Large-Class.md +0 -16
- data/docs/Long-Parameter-List.md +0 -39
- data/docs/Long-Yield-List.md +0 -37
- data/docs/Manual-Dispatch.md +0 -30
- data/docs/Missing-Safe-Method.md +0 -92
- data/docs/Module-Initialize.md +0 -62
- data/docs/Nested-Iterators.md +0 -59
- data/docs/Nil-Check.md +0 -47
- data/docs/RSpec-matchers.md +0 -129
- data/docs/Rake-Task.md +0 -66
- data/docs/Reek-4-to-Reek-5-migration.md +0 -188
- data/docs/Reek-Driven-Development.md +0 -46
- data/docs/Repeated-Conditional.md +0 -47
- data/docs/Simulated-Polymorphism.md +0 -16
- data/docs/Smell-Suppression.md +0 -96
- data/docs/Style-Guide.md +0 -19
- data/docs/Subclassed-From-Core-Class.md +0 -79
- data/docs/Too-Many-Constants.md +0 -37
- data/docs/Too-Many-Instance-Variables.md +0 -43
- data/docs/Too-Many-Methods.md +0 -56
- data/docs/Too-Many-Statements.md +0 -54
- data/docs/Uncommunicative-Method-Name.md +0 -94
- data/docs/Uncommunicative-Module-Name.md +0 -92
- data/docs/Uncommunicative-Name.md +0 -18
- data/docs/Uncommunicative-Parameter-Name.md +0 -90
- data/docs/Uncommunicative-Variable-Name.md +0 -96
- data/docs/Unused-Parameters.md +0 -28
- data/docs/Unused-Private-Method.md +0 -101
- data/docs/Utility-Function.md +0 -56
- data/docs/Versioning-Policy.md +0 -7
- data/docs/YAML-Reports.md +0 -93
- data/docs/defaults.reek.yml +0 -129
- data/docs/templates/default/docstring/html/public_api_marker.erb +0 -3
- data/docs/templates/default/docstring/setup.rb +0 -37
- data/docs/templates/default/fulldoc/html/css/common.css +0 -1
- data/docs/yard_plugin.rb +0 -17
- data/features/command_line_interface/basic_usage.feature +0 -15
- data/features/command_line_interface/options.feature +0 -123
- data/features/command_line_interface/show_progress.feature +0 -33
- data/features/command_line_interface/smell_selection.feature +0 -15
- data/features/command_line_interface/smells_count.feature +0 -38
- data/features/command_line_interface/stdin.feature +0 -65
- data/features/configuration_files/accept_setting.feature +0 -87
- data/features/configuration_files/directory_specific_directives.feature +0 -274
- data/features/configuration_files/exclude_directives.feature +0 -35
- data/features/configuration_files/exclude_paths_directives.feature +0 -42
- data/features/configuration_files/masking_smells.feature +0 -94
- data/features/configuration_files/mix_accept_reject_setting.feature +0 -84
- data/features/configuration_files/reject_setting.feature +0 -89
- data/features/configuration_files/schema_validation.feature +0 -59
- data/features/configuration_files/show_configuration_file.feature +0 -44
- data/features/configuration_files/unused_private_method.feature +0 -68
- data/features/configuration_loading.feature +0 -91
- data/features/configuration_via_source_comments/erroneous_source_comments.feature +0 -68
- data/features/configuration_via_source_comments/well_formed_source_comments.feature +0 -116
- data/features/locales.feature +0 -32
- data/features/programmatic_access.feature +0 -41
- data/features/rake_task/rake_task.feature +0 -138
- data/features/reports/codeclimate.feature +0 -59
- data/features/reports/json.feature +0 -59
- data/features/reports/reports.feature +0 -219
- data/features/reports/yaml.feature +0 -52
- data/features/rspec_matcher.feature +0 -41
- data/features/samples.feature +0 -305
- data/features/step_definitions/.rubocop.yml +0 -5
- data/features/step_definitions/reek_steps.rb +0 -102
- data/features/step_definitions/sample_file_steps.rb +0 -63
- data/features/support/env.rb +0 -33
- data/features/todo_list.feature +0 -108
- data/lib/reek/configuration/schema.yml +0 -210
- data/samples/checkstyle.xml +0 -7
- data/samples/clean_source/clean.rb +0 -6
- data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +0 -29
- data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +0 -30
- data/samples/configuration/corrupt.reek +0 -1
- data/samples/configuration/empty.reek +0 -0
- data/samples/configuration/full_configuration.reek +0 -13
- data/samples/configuration/full_mask.reek +0 -6
- data/samples/configuration/home/home.reek.yml +0 -4
- data/samples/configuration/partial_mask.reek +0 -4
- data/samples/configuration/regular_configuration/.reek.yml +0 -4
- data/samples/configuration/regular_configuration/empty_sub_directory/.gitignore +0 -0
- data/samples/configuration/with_excluded_paths.reek +0 -5
- data/samples/no_config_file/.keep +0 -0
- data/samples/paths.rb +0 -5
- data/samples/smelly_source/inline.rb +0 -704
- data/samples/smelly_source/optparse.rb +0 -1788
- data/samples/smelly_source/redcloth.rb +0 -1130
- data/samples/smelly_source/ruby.rb +0 -368
- data/samples/smelly_source/smelly.rb +0 -7
- data/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +0 -5
- data/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +0 -2
- data/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +0 -6
- data/samples/source_with_exclude_paths/nested/uncommunicative_variable_name.rb +0 -6
- data/samples/source_with_hidden_directories/.hidden/hidden.rb +0 -1
- data/samples/source_with_hidden_directories/not_hidden.rb +0 -1
- data/samples/source_with_non_ruby_files/gibberish +0 -1
- data/samples/source_with_non_ruby_files/python_source.py +0 -1
- data/samples/source_with_non_ruby_files/ruby.rb +0 -6
- data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +0 -15
- data/spec/quality/documentation_spec.rb +0 -41
- data/spec/quality/reek_source_spec.rb +0 -11
- data/spec/reek/ast/node_spec.rb +0 -211
- data/spec/reek/ast/object_refs_spec.rb +0 -83
- data/spec/reek/ast/reference_collector_spec.rb +0 -47
- data/spec/reek/ast/sexp_extensions_spec.rb +0 -498
- data/spec/reek/cli/application_spec.rb +0 -168
- data/spec/reek/cli/command/report_command_spec.rb +0 -44
- data/spec/reek/cli/command/todo_list_command_spec.rb +0 -86
- data/spec/reek/cli/options_spec.rb +0 -51
- data/spec/reek/cli/silencer_spec.rb +0 -28
- data/spec/reek/code_comment_spec.rb +0 -184
- data/spec/reek/configuration/app_configuration_spec.rb +0 -195
- data/spec/reek/configuration/configuration_file_finder_spec.rb +0 -230
- data/spec/reek/configuration/default_directive_spec.rb +0 -13
- data/spec/reek/configuration/directory_directives_spec.rb +0 -122
- data/spec/reek/configuration/excluded_paths_spec.rb +0 -16
- data/spec/reek/configuration/rake_task_converter_spec.rb +0 -33
- data/spec/reek/configuration/schema_validator_spec.rb +0 -165
- data/spec/reek/context/code_context_spec.rb +0 -192
- data/spec/reek/context/ghost_context_spec.rb +0 -60
- data/spec/reek/context/method_context_spec.rb +0 -72
- data/spec/reek/context/module_context_spec.rb +0 -55
- data/spec/reek/context/root_context_spec.rb +0 -12
- data/spec/reek/context/statement_counter_spec.rb +0 -24
- data/spec/reek/context_builder_spec.rb +0 -457
- data/spec/reek/detector_repository_spec.rb +0 -22
- data/spec/reek/documentation_link_spec.rb +0 -20
- data/spec/reek/errors/base_error_spec.rb +0 -13
- data/spec/reek/examiner_spec.rb +0 -309
- data/spec/reek/logging_error_handler_spec.rb +0 -24
- data/spec/reek/rake/task_spec.rb +0 -56
- data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +0 -22
- data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +0 -126
- data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +0 -51
- data/spec/reek/report/code_climate/code_climate_report_spec.rb +0 -56
- data/spec/reek/report/html_report_spec.rb +0 -19
- data/spec/reek/report/json_report_spec.rb +0 -58
- data/spec/reek/report/location_formatter_spec.rb +0 -32
- data/spec/reek/report/progress_formatter_spec.rb +0 -68
- data/spec/reek/report/text_report_spec.rb +0 -89
- data/spec/reek/report/xml_report_spec.rb +0 -24
- data/spec/reek/report/yaml_report_spec.rb +0 -55
- data/spec/reek/report_spec.rb +0 -28
- data/spec/reek/smell_configuration_spec.rb +0 -56
- data/spec/reek/smell_detectors/attribute_spec.rb +0 -197
- data/spec/reek/smell_detectors/base_detector_spec.rb +0 -50
- data/spec/reek/smell_detectors/boolean_parameter_spec.rb +0 -93
- data/spec/reek/smell_detectors/class_variable_spec.rb +0 -106
- data/spec/reek/smell_detectors/control_parameter_spec.rb +0 -300
- data/spec/reek/smell_detectors/data_clump_spec.rb +0 -134
- data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +0 -211
- data/spec/reek/smell_detectors/feature_envy_spec.rb +0 -295
- data/spec/reek/smell_detectors/instance_variable_assumption_spec.rb +0 -96
- data/spec/reek/smell_detectors/irresponsible_module_spec.rb +0 -226
- data/spec/reek/smell_detectors/long_parameter_list_spec.rb +0 -61
- data/spec/reek/smell_detectors/long_yield_list_spec.rb +0 -49
- data/spec/reek/smell_detectors/manual_dispatch_spec.rb +0 -75
- data/spec/reek/smell_detectors/missing_safe_method_spec.rb +0 -68
- data/spec/reek/smell_detectors/module_initialize_spec.rb +0 -77
- data/spec/reek/smell_detectors/nested_iterators_spec.rb +0 -333
- data/spec/reek/smell_detectors/nil_check_spec.rb +0 -100
- data/spec/reek/smell_detectors/repeated_conditional_spec.rb +0 -100
- data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -77
- data/spec/reek/smell_detectors/too_many_constants_spec.rb +0 -144
- data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +0 -132
- data/spec/reek/smell_detectors/too_many_methods_spec.rb +0 -54
- data/spec/reek/smell_detectors/too_many_statements_spec.rb +0 -90
- data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +0 -78
- data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +0 -78
- data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +0 -147
- data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +0 -201
- data/spec/reek/smell_detectors/unused_parameters_spec.rb +0 -114
- data/spec/reek/smell_detectors/unused_private_method_spec.rb +0 -205
- data/spec/reek/smell_detectors/utility_function_spec.rb +0 -293
- data/spec/reek/smell_warning_spec.rb +0 -137
- data/spec/reek/source/source_code_spec.rb +0 -79
- data/spec/reek/source/source_locator_spec.rb +0 -166
- data/spec/reek/spec/should_reek_of_spec.rb +0 -153
- data/spec/reek/spec/should_reek_only_of_spec.rb +0 -91
- data/spec/reek/spec/should_reek_spec.rb +0 -52
- data/spec/reek/spec/smell_matcher_spec.rb +0 -87
- data/spec/reek/tree_dresser_spec.rb +0 -46
- data/spec/spec_helper.rb +0 -110
- data/tasks/configuration.rake +0 -18
- data/tasks/console.rake +0 -5
- data/tasks/reek.rake +0 -6
- data/tasks/rubocop.rake +0 -11
- data/tasks/test.rake +0 -32
- /data/lib/reek/{report/code_climate.rb → code_climate.rb} +0 -0
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '../base_report'
|
|
3
|
+
require_relative '../report/base_report'
|
|
4
4
|
require_relative 'code_climate_formatter'
|
|
5
5
|
|
|
6
6
|
module Reek
|
|
7
|
-
module
|
|
7
|
+
module CodeClimate
|
|
8
8
|
#
|
|
9
9
|
# Displays a list of smells in Code Climate engine format
|
|
10
10
|
# (https://github.com/codeclimate/spec/blob/master/SPEC.md)
|
|
11
11
|
# JSON with empty array for 0 smells
|
|
12
12
|
#
|
|
13
|
-
class CodeClimateReport < BaseReport
|
|
13
|
+
class CodeClimateReport < Report::BaseReport
|
|
14
14
|
def show(out = $stdout)
|
|
15
15
|
smells.map do |smell|
|
|
16
16
|
out.print CodeClimateFormatter.new(smell).render
|
data/lib/reek/code_comment.rb
CHANGED
|
@@ -19,8 +19,8 @@ module Reek
|
|
|
19
19
|
(\w+) # smell detector e.g.: UncommunicativeVariableName
|
|
20
20
|
(:?\s*) # separator
|
|
21
21
|
(\{.*?\})? # details in hash style e.g.: { max_methods: 30 }
|
|
22
|
-
/x
|
|
23
|
-
SANITIZE_REGEX = /(#|\n|\s)
|
|
22
|
+
/x
|
|
23
|
+
SANITIZE_REGEX = /(#|\n|\s)+/ # Matches '#', newlines and > 1 whitespaces.
|
|
24
24
|
DISABLE_DETECTOR_CONFIGURATION = '{ enabled: false }'
|
|
25
25
|
MINIMUM_CONTENT_LENGTH = 2
|
|
26
26
|
|
|
@@ -39,13 +39,13 @@ module Reek
|
|
|
39
39
|
|
|
40
40
|
@original_comment.scan(CONFIGURATION_REGEX) do |detector_name, separator, options|
|
|
41
41
|
escalate_legacy_separator separator
|
|
42
|
-
CodeCommentValidator.new(detector_name: detector_name,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
validator = CodeCommentValidator.new(detector_name: detector_name,
|
|
43
|
+
original_comment: original_comment,
|
|
44
|
+
line: line,
|
|
45
|
+
source: source,
|
|
46
|
+
options: options)
|
|
47
|
+
validator.validate
|
|
48
|
+
@config.merge! detector_name => validator.parsed_options
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
@@ -115,6 +115,21 @@ module Reek
|
|
|
115
115
|
escalate_unknown_configuration_key
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
+
def parsed_options
|
|
119
|
+
@parsed_options ||=
|
|
120
|
+
if Psych::VERSION < '3.1.0'
|
|
121
|
+
YAML.safe_load(options || CodeComment::DISABLE_DETECTOR_CONFIGURATION, [Regexp])
|
|
122
|
+
else
|
|
123
|
+
YAML.safe_load(options || CodeComment::DISABLE_DETECTOR_CONFIGURATION,
|
|
124
|
+
permitted_classes: [Regexp])
|
|
125
|
+
end
|
|
126
|
+
rescue Psych::SyntaxError
|
|
127
|
+
raise Errors::GarbageDetectorConfigurationInCommentError.new(detector_name: detector_name,
|
|
128
|
+
original_comment: original_comment,
|
|
129
|
+
source: source,
|
|
130
|
+
line: line)
|
|
131
|
+
end
|
|
132
|
+
|
|
118
133
|
private
|
|
119
134
|
|
|
120
135
|
attr_reader :detector_name,
|
|
@@ -124,16 +139,6 @@ module Reek
|
|
|
124
139
|
:separator,
|
|
125
140
|
:options
|
|
126
141
|
|
|
127
|
-
def parsed_options
|
|
128
|
-
@parsed_options ||= YAML.safe_load(options || CodeComment::DISABLE_DETECTOR_CONFIGURATION,
|
|
129
|
-
permitted_classes: [Regexp])
|
|
130
|
-
rescue Psych::SyntaxError
|
|
131
|
-
raise Errors::GarbageDetectorConfigurationInCommentError.new(detector_name: detector_name,
|
|
132
|
-
original_comment: original_comment,
|
|
133
|
-
source: source,
|
|
134
|
-
line: line)
|
|
135
|
-
end
|
|
136
|
-
|
|
137
142
|
def escalate_unknown_configuration_key
|
|
138
143
|
return if given_keys_legit?
|
|
139
144
|
|
|
@@ -165,7 +170,7 @@ module Reek
|
|
|
165
170
|
|
|
166
171
|
# @return [Set] the configuration keys that are found in the code comment
|
|
167
172
|
def given_configuration_keys
|
|
168
|
-
parsed_options.keys.
|
|
173
|
+
parsed_options.keys.to_set(&:to_sym)
|
|
169
174
|
end
|
|
170
175
|
|
|
171
176
|
# @return [String] all keys from the code comment that look bad
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'pathname'
|
|
4
|
-
require_relative '
|
|
5
|
-
require_relative '
|
|
6
|
-
require_relative '
|
|
7
|
-
require_relative '
|
|
8
|
-
require_relative '
|
|
4
|
+
require_relative 'configuration_file_finder'
|
|
5
|
+
require_relative 'configuration_validator'
|
|
6
|
+
require_relative 'default_directive'
|
|
7
|
+
require_relative 'directory_directives'
|
|
8
|
+
require_relative 'excluded_paths'
|
|
9
9
|
|
|
10
10
|
module Reek
|
|
11
11
|
module Configuration
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'pathname'
|
|
4
|
-
require_relative '
|
|
5
|
-
require_relative '
|
|
4
|
+
require_relative 'configuration_converter'
|
|
5
|
+
require_relative 'schema_validator'
|
|
6
6
|
require_relative '../errors/config_file_error'
|
|
7
7
|
|
|
8
8
|
module Reek
|
|
@@ -58,11 +58,11 @@ module Reek
|
|
|
58
58
|
|
|
59
59
|
begin
|
|
60
60
|
configuration = YAML.load_file(path) || {}
|
|
61
|
+
SchemaValidator.new(configuration).validate
|
|
61
62
|
rescue StandardError => error
|
|
62
63
|
raise Errors::ConfigFileError, "Invalid configuration file #{path}, error is #{error}"
|
|
63
64
|
end
|
|
64
65
|
|
|
65
|
-
SchemaValidator.new(configuration).validate
|
|
66
66
|
ConfigurationConverter.new(configuration).convert
|
|
67
67
|
end
|
|
68
68
|
|
|
@@ -87,7 +87,8 @@ module Reek
|
|
|
87
87
|
#
|
|
88
88
|
# @quality :reek:FeatureEnvy
|
|
89
89
|
def find_in_dir(dir)
|
|
90
|
-
|
|
90
|
+
file = dir + DEFAULT_FILE_NAME
|
|
91
|
+
file if file.file?
|
|
91
92
|
end
|
|
92
93
|
end
|
|
93
94
|
end
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require_relative '
|
|
3
|
+
require_relative 'configuration_validator'
|
|
4
4
|
require_relative '../errors/config_file_error'
|
|
5
5
|
|
|
6
6
|
module Reek
|
|
@@ -14,7 +14,8 @@ module Reek
|
|
|
14
14
|
# @param paths [String]
|
|
15
15
|
# @return [undefined]
|
|
16
16
|
def add(paths)
|
|
17
|
-
paths.
|
|
17
|
+
paths.flat_map { |path| Dir[path] }.
|
|
18
|
+
each { |path| self << Pathname(path) }
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
end
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'dry/schema'
|
|
4
|
+
|
|
5
|
+
module Reek
|
|
6
|
+
module Configuration
|
|
7
|
+
#
|
|
8
|
+
# Configuration schema constants.
|
|
9
|
+
#
|
|
10
|
+
class Schema
|
|
11
|
+
# Enable the :info extension so we can introspect
|
|
12
|
+
# your keys and types
|
|
13
|
+
Dry::Schema.load_extensions(:info)
|
|
14
|
+
|
|
15
|
+
# rubocop:disable Metrics/BlockLength
|
|
16
|
+
ALL_DETECTORS_SCHEMA = Dry::Schema.Params do
|
|
17
|
+
optional(:Attribute).filled(:hash) do
|
|
18
|
+
optional(:enabled).filled(:bool)
|
|
19
|
+
optional(:exclude).array(:string)
|
|
20
|
+
end
|
|
21
|
+
optional(:BooleanParameter).filled(:hash) do
|
|
22
|
+
optional(:enabled).filled(:bool)
|
|
23
|
+
optional(:exclude).array(:string)
|
|
24
|
+
end
|
|
25
|
+
optional(:ClassVariable).filled(:hash) do
|
|
26
|
+
optional(:enabled).filled(:bool)
|
|
27
|
+
optional(:exclude).array(:string)
|
|
28
|
+
end
|
|
29
|
+
optional(:ControlParameter).filled(:hash) do
|
|
30
|
+
optional(:enabled).filled(:bool)
|
|
31
|
+
optional(:exclude).array(:string)
|
|
32
|
+
end
|
|
33
|
+
optional(:DataClump).filled(:hash) do
|
|
34
|
+
optional(:enabled).filled(:bool)
|
|
35
|
+
optional(:exclude).array(:string)
|
|
36
|
+
optional(:max_copies).filled(:integer)
|
|
37
|
+
optional(:min_clump_size).filled(:integer)
|
|
38
|
+
end
|
|
39
|
+
optional(:DuplicateMethodCall).filled(:hash) do
|
|
40
|
+
optional(:enabled).filled(:bool)
|
|
41
|
+
optional(:exclude).array(:string)
|
|
42
|
+
optional(:max_calls).filled(:integer)
|
|
43
|
+
optional(:allow_calls).array(:string)
|
|
44
|
+
end
|
|
45
|
+
optional(:FeatureEnvy).filled(:hash) do
|
|
46
|
+
optional(:enabled).filled(:bool)
|
|
47
|
+
optional(:exclude).array(:string)
|
|
48
|
+
end
|
|
49
|
+
optional(:InstanceVariableAssumption).filled(:hash) do
|
|
50
|
+
optional(:enabled).filled(:bool)
|
|
51
|
+
optional(:exclude).array(:string)
|
|
52
|
+
end
|
|
53
|
+
optional(:IrresponsibleModule).filled(:hash) do
|
|
54
|
+
optional(:enabled).filled(:bool)
|
|
55
|
+
optional(:exclude).array(:string)
|
|
56
|
+
end
|
|
57
|
+
optional(:LongParameterList).filled(:hash) do
|
|
58
|
+
optional(:enabled).filled(:bool)
|
|
59
|
+
optional(:exclude).array(:string)
|
|
60
|
+
optional(:max_params).filled(:integer)
|
|
61
|
+
optional(:overrides).filled(:hash) do
|
|
62
|
+
required(:initialize).filled(:hash) do
|
|
63
|
+
required(:max_params).filled(:integer)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
optional(:LongYieldList).filled(:hash) do
|
|
68
|
+
optional(:enabled).filled(:bool)
|
|
69
|
+
optional(:exclude).array(:string)
|
|
70
|
+
optional(:max_params).filled(:integer)
|
|
71
|
+
end
|
|
72
|
+
optional(:ManualDispatch).filled(:hash) do
|
|
73
|
+
optional(:enabled).filled(:bool)
|
|
74
|
+
optional(:exclude).array(:string)
|
|
75
|
+
end
|
|
76
|
+
optional(:MissingSafeMethod).filled(:hash) do
|
|
77
|
+
optional(:enabled).filled(:bool)
|
|
78
|
+
optional(:exclude).array(:string)
|
|
79
|
+
end
|
|
80
|
+
optional(:ModuleInitialize).filled(:hash) do
|
|
81
|
+
optional(:enabled).filled(:bool)
|
|
82
|
+
optional(:exclude).array(:string)
|
|
83
|
+
end
|
|
84
|
+
optional(:NestedIterators).filled(:hash) do
|
|
85
|
+
optional(:enabled).filled(:bool)
|
|
86
|
+
optional(:exclude).array(:string)
|
|
87
|
+
optional(:max_allowed_nesting).filled(:integer)
|
|
88
|
+
optional(:ignore_iterators) { array(:string) & filled? }
|
|
89
|
+
end
|
|
90
|
+
optional(:NilCheck).filled(:hash) do
|
|
91
|
+
optional(:enabled).filled(:bool)
|
|
92
|
+
optional(:exclude).array(:string)
|
|
93
|
+
end
|
|
94
|
+
optional(:RepeatedConditional).filled(:hash) do
|
|
95
|
+
optional(:enabled).filled(:bool)
|
|
96
|
+
optional(:exclude).array(:string)
|
|
97
|
+
optional(:max_ifs).filled(:integer)
|
|
98
|
+
end
|
|
99
|
+
optional(:SubclassedFromCoreClass).filled(:hash) do
|
|
100
|
+
optional(:enabled).filled(:bool)
|
|
101
|
+
optional(:exclude).array(:string)
|
|
102
|
+
end
|
|
103
|
+
optional(:TooManyConstants).filled(:hash) do
|
|
104
|
+
optional(:enabled).filled(:bool)
|
|
105
|
+
optional(:exclude).array(:string)
|
|
106
|
+
optional(:max_constants).filled(:integer)
|
|
107
|
+
end
|
|
108
|
+
optional(:TooManyInstanceVariables).filled(:hash) do
|
|
109
|
+
optional(:enabled).filled(:bool)
|
|
110
|
+
optional(:exclude).array(:string)
|
|
111
|
+
optional(:max_instance_variables).filled(:integer)
|
|
112
|
+
end
|
|
113
|
+
optional(:TooManyMethods).filled(:hash) do
|
|
114
|
+
optional(:enabled).filled(:bool)
|
|
115
|
+
optional(:exclude).array(:string)
|
|
116
|
+
optional(:max_methods).filled(:integer)
|
|
117
|
+
end
|
|
118
|
+
optional(:TooManyStatements).filled(:hash) do
|
|
119
|
+
optional(:enabled).filled(:bool)
|
|
120
|
+
optional(:exclude).array(:string)
|
|
121
|
+
optional(:max_statements).filled(:integer)
|
|
122
|
+
end
|
|
123
|
+
optional(:UncommunicativeMethodName).filled(:hash) do
|
|
124
|
+
optional(:enabled).filled(:bool)
|
|
125
|
+
optional(:exclude).array(:string)
|
|
126
|
+
optional(:reject).array(:string)
|
|
127
|
+
optional(:accept).array(:string)
|
|
128
|
+
end
|
|
129
|
+
optional(:UncommunicativeModuleName).filled(:hash) do
|
|
130
|
+
optional(:enabled).filled(:bool)
|
|
131
|
+
optional(:exclude).array(:string)
|
|
132
|
+
optional(:reject).array(:string)
|
|
133
|
+
optional(:accept).array(:string)
|
|
134
|
+
end
|
|
135
|
+
optional(:UncommunicativeParameterName).filled(:hash) do
|
|
136
|
+
optional(:enabled).filled(:bool)
|
|
137
|
+
optional(:exclude).array(:string)
|
|
138
|
+
optional(:reject).array(:string)
|
|
139
|
+
optional(:accept).array(:string)
|
|
140
|
+
end
|
|
141
|
+
optional(:UncommunicativeVariableName).filled(:hash) do
|
|
142
|
+
optional(:enabled).filled(:bool)
|
|
143
|
+
optional(:exclude).array(:string)
|
|
144
|
+
optional(:reject).array(:string)
|
|
145
|
+
optional(:accept).array(:string)
|
|
146
|
+
end
|
|
147
|
+
optional(:UnusedParameters).filled(:hash) do
|
|
148
|
+
optional(:enabled).filled(:bool)
|
|
149
|
+
optional(:exclude).array(:string)
|
|
150
|
+
end
|
|
151
|
+
optional(:UnusedPrivateMethod).filled(:hash) do
|
|
152
|
+
optional(:enabled).filled(:bool)
|
|
153
|
+
optional(:exclude).array(:string)
|
|
154
|
+
end
|
|
155
|
+
optional(:UtilityFunction).filled(:hash) do
|
|
156
|
+
optional(:enabled).filled(:bool)
|
|
157
|
+
optional(:exclude).array(:string)
|
|
158
|
+
optional(:public_methods_only).filled(:bool)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
# rubocop:enable Metrics/BlockLength
|
|
162
|
+
|
|
163
|
+
# @quality :reek:TooManyStatements { max_statements: 7 }
|
|
164
|
+
def self.schema(directories = [])
|
|
165
|
+
Dry::Schema.Params do
|
|
166
|
+
config.validate_keys = true
|
|
167
|
+
|
|
168
|
+
optional(:detectors).filled(ALL_DETECTORS_SCHEMA)
|
|
169
|
+
optional(:directories).filled(:hash) do
|
|
170
|
+
directories.each { |dir| optional(dir.to_sym).filled(ALL_DETECTORS_SCHEMA) }
|
|
171
|
+
end
|
|
172
|
+
optional(:exclude_paths).array(:string)
|
|
173
|
+
end
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
end
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'yaml'
|
|
4
|
-
require_relative '../cli/silencer'
|
|
5
|
-
Reek::CLI::Silencer.without_warnings { require 'kwalify' }
|
|
6
3
|
require_relative '../errors/config_file_error'
|
|
4
|
+
require_relative 'schema'
|
|
7
5
|
|
|
8
6
|
module Reek
|
|
9
7
|
module Configuration
|
|
@@ -11,28 +9,29 @@ module Reek
|
|
|
11
9
|
# Schema validator module.
|
|
12
10
|
#
|
|
13
11
|
class SchemaValidator
|
|
14
|
-
SCHEMA_FILE_PATH = File.expand_path('./schema.yml', __dir__)
|
|
15
|
-
|
|
16
12
|
def initialize(configuration)
|
|
17
13
|
@configuration = configuration
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
Kwalify::Validator.new(schema_file)
|
|
21
|
-
end
|
|
14
|
+
config_directories = configuration['directories']&.keys || []
|
|
15
|
+
@validator = Reek::Configuration::Schema.schema(config_directories)
|
|
22
16
|
end
|
|
23
17
|
|
|
24
18
|
def validate
|
|
25
|
-
|
|
26
|
-
return if
|
|
19
|
+
result = @validator.call(@configuration)
|
|
20
|
+
return if result.success?
|
|
27
21
|
|
|
28
|
-
raise Errors::ConfigFileError, error_message(errors)
|
|
22
|
+
raise Errors::ConfigFileError, error_message(result.errors)
|
|
23
|
+
rescue NoMethodError
|
|
24
|
+
raise Errors::ConfigFileError, 'unrecognized configuration data'
|
|
29
25
|
end
|
|
30
26
|
|
|
31
27
|
private
|
|
32
28
|
|
|
33
29
|
# :reek:UtilityFunction
|
|
34
30
|
def error_message(errors)
|
|
35
|
-
|
|
31
|
+
messages = errors.map do |error|
|
|
32
|
+
"[/#{error.path.join('/')}] #{error.text}."
|
|
33
|
+
end.join("\n")
|
|
34
|
+
"\n#{messages}"
|
|
36
35
|
end
|
|
37
36
|
end
|
|
38
37
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'module_context'
|
|
4
|
+
|
|
5
|
+
module Reek
|
|
6
|
+
module Context
|
|
7
|
+
#
|
|
8
|
+
# A context wrapper for any refinement blocks found in a syntax tree.
|
|
9
|
+
#
|
|
10
|
+
class RefinementContext < ModuleContext
|
|
11
|
+
def full_name
|
|
12
|
+
exp.call.args.first.name
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/reek/context_builder.rb
CHANGED
|
@@ -5,6 +5,7 @@ require_relative 'context/class_context'
|
|
|
5
5
|
require_relative 'context/ghost_context'
|
|
6
6
|
require_relative 'context/method_context'
|
|
7
7
|
require_relative 'context/module_context'
|
|
8
|
+
require_relative 'context/refinement_context'
|
|
8
9
|
require_relative 'context/root_context'
|
|
9
10
|
require_relative 'context/send_context'
|
|
10
11
|
require_relative 'context/singleton_attribute_context'
|
|
@@ -20,7 +21,7 @@ module Reek
|
|
|
20
21
|
# counting. Ideally `ContextBuilder` would only build up the context tree and leave the
|
|
21
22
|
# statement and reference counting to the contexts.
|
|
22
23
|
#
|
|
23
|
-
# @quality :reek:TooManyMethods { max_methods:
|
|
24
|
+
# @quality :reek:TooManyMethods { max_methods: 32 }
|
|
24
25
|
# @quality :reek:UnusedPrivateMethod { exclude: [ !ruby/regexp /process_/ ] }
|
|
25
26
|
# @quality :reek:DataClump
|
|
26
27
|
class ContextBuilder
|
|
@@ -263,9 +264,16 @@ module Reek
|
|
|
263
264
|
#
|
|
264
265
|
# Counts non-empty blocks as one statement.
|
|
265
266
|
#
|
|
267
|
+
# A refinement block is handled differently and causes a RefinementContext
|
|
268
|
+
# to be opened.
|
|
269
|
+
#
|
|
266
270
|
def process_block(exp, _parent)
|
|
267
271
|
increase_statement_count_by(exp.block)
|
|
268
|
-
|
|
272
|
+
if exp.call.name == :refine
|
|
273
|
+
handle_refinement_block(exp)
|
|
274
|
+
else
|
|
275
|
+
process(exp)
|
|
276
|
+
end
|
|
269
277
|
end
|
|
270
278
|
|
|
271
279
|
# Handles `begin` and `kwbegin` nodes. `begin` nodes are created implicitly
|
|
@@ -414,7 +422,7 @@ module Reek
|
|
|
414
422
|
# See `process_rescue` for additional reference.
|
|
415
423
|
#
|
|
416
424
|
def process_resbody(exp, _parent)
|
|
417
|
-
increase_statement_count_by(exp.children[1
|
|
425
|
+
increase_statement_count_by(exp.children[1..].compact)
|
|
418
426
|
process(exp)
|
|
419
427
|
end
|
|
420
428
|
|
|
@@ -508,6 +516,12 @@ module Reek
|
|
|
508
516
|
end
|
|
509
517
|
end
|
|
510
518
|
|
|
519
|
+
def handle_refinement_block(exp)
|
|
520
|
+
inside_new_context(Context::RefinementContext, exp) do
|
|
521
|
+
process(exp)
|
|
522
|
+
end
|
|
523
|
+
end
|
|
524
|
+
|
|
511
525
|
def handle_send_for_modules(exp)
|
|
512
526
|
arg_names = exp.args.map { |arg| arg.children.first }
|
|
513
527
|
current_context.track_visibility(exp.name, arg_names)
|
|
@@ -17,12 +17,10 @@ module Reek
|
|
|
17
17
|
Kernel.format(HELP_LINK_TEMPLATE, version: Version::STRING, item: name_to_param(subject))
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
# Convert the given subject name to a form that is acceptable in a URL
|
|
20
|
+
# Convert the given subject name to a form that is acceptable in a URL, by
|
|
21
|
+
# dasherizeing it at the start of capitalized words. Spaces are discared.
|
|
21
22
|
def name_to_param(name)
|
|
22
|
-
|
|
23
|
-
# preceded by a space. The space is discarded, the start of the word is
|
|
24
|
-
# not.
|
|
25
|
-
name.split(/ *(?=[A-Z][a-z])/).join('-')
|
|
23
|
+
name.split(/([A-Z][a-z][a-z]*)/).map(&:strip).reject(&:empty?).join('-')
|
|
26
24
|
end
|
|
27
25
|
end
|
|
28
26
|
end
|
|
@@ -8,7 +8,7 @@ module Reek
|
|
|
8
8
|
# Gets raised when trying to configure a detector with an option
|
|
9
9
|
# which is unknown to it.
|
|
10
10
|
class BadDetectorConfigurationKeyInCommentError < BaseError
|
|
11
|
-
UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE
|
|
11
|
+
UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE.freeze
|
|
12
12
|
|
|
13
13
|
Error: You are trying to configure the smell detector '%<detector>s'
|
|
14
14
|
in one of your source code comments with the unknown option %<option>s.
|
|
@@ -32,7 +32,7 @@ module Reek
|
|
|
32
32
|
source: source,
|
|
33
33
|
line: line,
|
|
34
34
|
comment: original_comment)
|
|
35
|
-
super
|
|
35
|
+
super(message)
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
38
|
end
|
|
@@ -9,7 +9,7 @@ module Reek
|
|
|
9
9
|
# This might happen for multiple reasons. The users might have a typo in
|
|
10
10
|
# his comment or he might use a detector that does not exist anymore.
|
|
11
11
|
class BadDetectorInCommentError < BaseError
|
|
12
|
-
UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE
|
|
12
|
+
UNKNOWN_SMELL_DETECTOR_MESSAGE = <<-MESSAGE.freeze
|
|
13
13
|
|
|
14
14
|
Error: You are trying to configure an unknown smell detector '%<detector>s' in one
|
|
15
15
|
of your source code comments.
|
|
@@ -31,7 +31,7 @@ module Reek
|
|
|
31
31
|
source: source,
|
|
32
32
|
line: line,
|
|
33
33
|
comment: original_comment)
|
|
34
|
-
super
|
|
34
|
+
super(message)
|
|
35
35
|
end
|
|
36
36
|
end
|
|
37
37
|
end
|
|
@@ -8,7 +8,7 @@ module Reek
|
|
|
8
8
|
# Gets raised when trying to use a configuration for a detector
|
|
9
9
|
# that can't be parsed into a hash.
|
|
10
10
|
class GarbageDetectorConfigurationInCommentError < BaseError
|
|
11
|
-
BAD_DETECTOR_CONFIGURATION_MESSAGE = <<-MESSAGE
|
|
11
|
+
BAD_DETECTOR_CONFIGURATION_MESSAGE = <<-MESSAGE.freeze
|
|
12
12
|
|
|
13
13
|
Error: You are trying to configure the smell detector '%<detector>s'.
|
|
14
14
|
Unfortunately we cannot parse the configuration you have given.
|
|
@@ -30,7 +30,7 @@ module Reek
|
|
|
30
30
|
source: source,
|
|
31
31
|
line: line,
|
|
32
32
|
comment: original_comment)
|
|
33
|
-
super
|
|
33
|
+
super(message)
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
end
|
|
@@ -6,7 +6,7 @@ module Reek
|
|
|
6
6
|
module Errors
|
|
7
7
|
# Gets raised for old-style comment configuration format.
|
|
8
8
|
class LegacyCommentSeparatorError < BaseError
|
|
9
|
-
MESSAGE = <<-MESSAGE
|
|
9
|
+
MESSAGE = <<-MESSAGE.freeze
|
|
10
10
|
Error: You are using the legacy configuration format (including three
|
|
11
11
|
colons) to configure Reek in one your source code comments.
|
|
12
12
|
|
|
@@ -29,7 +29,7 @@ module Reek
|
|
|
29
29
|
source: source,
|
|
30
30
|
line: line,
|
|
31
31
|
comment: original_comment)
|
|
32
|
-
super
|
|
32
|
+
super(message)
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
35
|
end
|