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
|
@@ -29,7 +29,7 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeVariableName do
|
|
|
29
29
|
and reek_of(:UncommunicativeVariableName, lines: [3], name: 'y')
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
context 'instance variables' do
|
|
32
|
+
context 'when examining instance variables' do
|
|
33
33
|
it 'does not report use of one-letter names' do
|
|
34
34
|
src = 'class Alfa; def bravo; @x; end; end'
|
|
35
35
|
expect(src).not_to reek_of(:UncommunicativeVariableName)
|
|
@@ -41,7 +41,7 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeVariableName do
|
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
43
|
|
|
44
|
-
context 'local variables' do
|
|
44
|
+
context 'when examining local variables' do
|
|
45
45
|
it 'does not report single underscore as a variable name' do
|
|
46
46
|
src = 'def alfa; _ = bravo(); end'
|
|
47
47
|
expect(src).not_to reek_of(:UncommunicativeVariableName)
|
|
@@ -78,7 +78,7 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeVariableName do
|
|
|
78
78
|
end
|
|
79
79
|
end
|
|
80
80
|
|
|
81
|
-
context 'block parameters' do
|
|
81
|
+
context 'when examining block parameters' do
|
|
82
82
|
it 'reports all relevant block parameters' do
|
|
83
83
|
src = <<-EOS
|
|
84
84
|
def alfa
|
|
@@ -159,9 +159,9 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeVariableName do
|
|
|
159
159
|
describe '`accept` patterns' do
|
|
160
160
|
let(:src) { 'def alfa; bravo2 = 42; end' }
|
|
161
161
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
162
|
+
it 'make smelly names pass' do
|
|
163
|
+
patterns = [/ravo2/, /bravo2/]
|
|
164
|
+
patterns.each do |pattern|
|
|
165
165
|
expect(src).to reek_of(:UncommunicativeVariableName).
|
|
166
166
|
and not_reek_of(:UncommunicativeVariableName).with_config('accept' => pattern)
|
|
167
167
|
end
|
|
@@ -171,9 +171,9 @@ RSpec.describe Reek::SmellDetectors::UncommunicativeVariableName do
|
|
|
171
171
|
describe '`reject` patterns' do
|
|
172
172
|
let(:src) { 'def alfa; foobar = 42; end' }
|
|
173
173
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
174
|
+
it 'reject smelly names' do
|
|
175
|
+
patterns = [/fooba/, /oobar/]
|
|
176
|
+
patterns.each do |pattern|
|
|
177
177
|
expect(src).to not_reek_of(:UncommunicativeVariableName).
|
|
178
178
|
and reek_of(:UncommunicativeVariableName).with_config('reject' => pattern)
|
|
179
179
|
end
|
|
@@ -61,7 +61,7 @@ RSpec.describe Reek::SmellDetectors::UnusedParameters do
|
|
|
61
61
|
expect(src).not_to reek_of(:UnusedParameters)
|
|
62
62
|
end
|
|
63
63
|
|
|
64
|
-
context 'using super' do
|
|
64
|
+
context 'when using super' do
|
|
65
65
|
it 'reports nothing with implicit arguments' do
|
|
66
66
|
src = 'def alfa(*bravo); super; end'
|
|
67
67
|
expect(src).not_to reek_of(:UnusedParameters)
|
|
@@ -83,7 +83,7 @@ RSpec.describe Reek::SmellDetectors::UnusedParameters do
|
|
|
83
83
|
end
|
|
84
84
|
end
|
|
85
85
|
|
|
86
|
-
context 'anonymous parameters' do
|
|
86
|
+
context 'with anonymous parameters' do
|
|
87
87
|
it 'reports nothing for unused anonymous parameter' do
|
|
88
88
|
src = 'def alfa(_); end'
|
|
89
89
|
expect(src).not_to reek_of(:UnusedParameters)
|
|
@@ -95,7 +95,7 @@ RSpec.describe Reek::SmellDetectors::UnusedParameters do
|
|
|
95
95
|
end
|
|
96
96
|
end
|
|
97
97
|
|
|
98
|
-
context 'splatted parameters' do
|
|
98
|
+
context 'with splatted parameters' do
|
|
99
99
|
it 'reports nothing for used splatted parameter' do
|
|
100
100
|
src = 'def alfa(*bravo); bravo; end'
|
|
101
101
|
expect(src).not_to reek_of(:UnusedParameters)
|
|
@@ -38,7 +38,7 @@ RSpec.describe Reek::SmellDetectors::UnusedPrivateMethod do
|
|
|
38
38
|
and reek_of(:UnusedPrivateMethod, lines: [7], name: 'charlie')
|
|
39
39
|
end
|
|
40
40
|
|
|
41
|
-
context 'unused private methods' do
|
|
41
|
+
context 'when a class has unused private methods' do
|
|
42
42
|
it 'reports instance methods' do
|
|
43
43
|
source = <<-EOF
|
|
44
44
|
class Alfa
|
|
@@ -103,12 +103,23 @@ RSpec.describe Reek::SmellDetectors::UnusedPrivateMethod do
|
|
|
103
103
|
to reek_of(:UnusedPrivateMethod, name: 'bravo', lines: [3]).
|
|
104
104
|
and reek_of(:UnusedPrivateMethod, name: 'charlie', lines: [4])
|
|
105
105
|
end
|
|
106
|
+
|
|
107
|
+
it 'reports instance methods defined as private with a modifier' do
|
|
108
|
+
source = <<-EOF
|
|
109
|
+
class Alfa
|
|
110
|
+
private def bravo; end
|
|
111
|
+
end
|
|
112
|
+
EOF
|
|
113
|
+
|
|
114
|
+
expect(source).
|
|
115
|
+
to reek_of(:UnusedPrivateMethod, name: 'bravo')
|
|
116
|
+
end
|
|
106
117
|
end
|
|
107
118
|
|
|
108
|
-
|
|
119
|
+
context 'when the detector is configured via a source code comment' do
|
|
109
120
|
it 'does not report methods we excluded' do
|
|
110
121
|
source = <<-EOF
|
|
111
|
-
# :reek:UnusedPrivateMethod
|
|
122
|
+
# :reek:UnusedPrivateMethod { exclude: [ bravo ] }
|
|
112
123
|
class Alfa
|
|
113
124
|
private
|
|
114
125
|
def bravo; end
|
|
@@ -122,8 +133,8 @@ RSpec.describe Reek::SmellDetectors::UnusedPrivateMethod do
|
|
|
122
133
|
end
|
|
123
134
|
end
|
|
124
135
|
|
|
125
|
-
context 'used private methods' do
|
|
126
|
-
it '
|
|
136
|
+
context 'when a class has only used private methods' do
|
|
137
|
+
it 'reports nothing' do
|
|
127
138
|
source = <<-EOF
|
|
128
139
|
class Alfa
|
|
129
140
|
def bravo
|
|
@@ -139,8 +150,8 @@ RSpec.describe Reek::SmellDetectors::UnusedPrivateMethod do
|
|
|
139
150
|
end
|
|
140
151
|
end
|
|
141
152
|
|
|
142
|
-
context 'unused protected methods' do
|
|
143
|
-
it '
|
|
153
|
+
context 'when a class has unused protected methods' do
|
|
154
|
+
it 'reports nothing' do
|
|
144
155
|
source = <<-EOF
|
|
145
156
|
class Alfa
|
|
146
157
|
protected
|
|
@@ -152,8 +163,8 @@ RSpec.describe Reek::SmellDetectors::UnusedPrivateMethod do
|
|
|
152
163
|
end
|
|
153
164
|
end
|
|
154
165
|
|
|
155
|
-
context 'unused public methods' do
|
|
156
|
-
it '
|
|
166
|
+
context 'when a class has unused public methods' do
|
|
167
|
+
it 'reports nothing' do
|
|
157
168
|
source = <<-EOF
|
|
158
169
|
class Alfa
|
|
159
170
|
def bravo; end
|
|
@@ -164,7 +175,7 @@ RSpec.describe Reek::SmellDetectors::UnusedPrivateMethod do
|
|
|
164
175
|
end
|
|
165
176
|
end
|
|
166
177
|
|
|
167
|
-
describe '
|
|
178
|
+
describe 'preventing methods from being reported' do
|
|
168
179
|
let(:source) do
|
|
169
180
|
<<-EOF
|
|
170
181
|
class Alfa
|
|
@@ -98,7 +98,7 @@ RSpec.describe Reek::SmellDetectors::UtilityFunction do
|
|
|
98
98
|
expect(src).to reek_of(:UtilityFunction, context: 'simple')
|
|
99
99
|
end
|
|
100
100
|
|
|
101
|
-
context '
|
|
101
|
+
context 'when examining singleton methods' do
|
|
102
102
|
['class', 'module'].each do |scope|
|
|
103
103
|
it "does not report for #{scope} with `class << self` notation" do
|
|
104
104
|
src = "#{scope} Alfa; class << self; def bravo(charlie) charlie.to_s; end; end; end"
|
|
@@ -111,7 +111,7 @@ RSpec.describe Reek::SmellDetectors::UtilityFunction do
|
|
|
111
111
|
end
|
|
112
112
|
end
|
|
113
113
|
|
|
114
|
-
context 'by using `module_function`' do
|
|
114
|
+
context 'when defined by using `module_function`' do
|
|
115
115
|
it 'does not report UtilityFunction also when using multiple arguments' do
|
|
116
116
|
src = <<-EOS
|
|
117
117
|
class Alfa
|
|
@@ -194,7 +194,7 @@ RSpec.describe Reek::SmellDetectors::UtilityFunction do
|
|
|
194
194
|
{ Reek::SmellDetectors::UtilityFunction::PUBLIC_METHODS_ONLY_KEY => true }
|
|
195
195
|
end
|
|
196
196
|
|
|
197
|
-
context 'public methods' do
|
|
197
|
+
context 'when examining public methods' do
|
|
198
198
|
it 'still reports UtilityFunction' do
|
|
199
199
|
src = <<-EOS
|
|
200
200
|
class Alfa
|
|
@@ -208,7 +208,7 @@ RSpec.describe Reek::SmellDetectors::UtilityFunction do
|
|
|
208
208
|
end
|
|
209
209
|
end
|
|
210
210
|
|
|
211
|
-
context 'private methods' do
|
|
211
|
+
context 'when examining private methods' do
|
|
212
212
|
it 'does not report UtilityFunction' do
|
|
213
213
|
src = <<-EOS
|
|
214
214
|
class Alfa
|
|
@@ -221,9 +221,21 @@ RSpec.describe Reek::SmellDetectors::UtilityFunction do
|
|
|
221
221
|
|
|
222
222
|
expect(src).not_to reek_of(:UtilityFunction).with_config(config)
|
|
223
223
|
end
|
|
224
|
+
|
|
225
|
+
it 'does not report UtilityFunction when private is used as a def modifier' do
|
|
226
|
+
src = <<-EOS
|
|
227
|
+
class Alfa
|
|
228
|
+
private def bravo(charlie)
|
|
229
|
+
charlie.delta.echo
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
EOS
|
|
233
|
+
|
|
234
|
+
expect(src).not_to reek_of(:UtilityFunction).with_config(config)
|
|
235
|
+
end
|
|
224
236
|
end
|
|
225
237
|
|
|
226
|
-
context 'protected methods' do
|
|
238
|
+
context 'when examining protected methods' do
|
|
227
239
|
it 'does not report UtilityFunction' do
|
|
228
240
|
src = <<-EOS
|
|
229
241
|
class Alfa
|
|
@@ -236,6 +248,46 @@ RSpec.describe Reek::SmellDetectors::UtilityFunction do
|
|
|
236
248
|
|
|
237
249
|
expect(src).not_to reek_of(:UtilityFunction).with_config(config)
|
|
238
250
|
end
|
|
251
|
+
|
|
252
|
+
it 'does not report UtilityFunction when protected is used as a def modifier' do
|
|
253
|
+
src = <<-EOS
|
|
254
|
+
class Alfa
|
|
255
|
+
protected def bravo(charlie)
|
|
256
|
+
charlie.delta.echo
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
EOS
|
|
260
|
+
|
|
261
|
+
expect(src).not_to reek_of(:UtilityFunction).with_config(config)
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
describe 'disabling with a comment' do
|
|
267
|
+
it 'disables the method following the comment' do
|
|
268
|
+
src = <<-EOS
|
|
269
|
+
class Alfa
|
|
270
|
+
# :reek:UtilityFunction
|
|
271
|
+
def bravo(charlie)
|
|
272
|
+
charlie.delta.echo
|
|
273
|
+
end
|
|
274
|
+
end
|
|
275
|
+
EOS
|
|
276
|
+
|
|
277
|
+
expect(src).not_to reek_of(:UtilityFunction)
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
it 'disables a method when it has a visibility modifier' do
|
|
281
|
+
src = <<-EOS
|
|
282
|
+
class Alfa
|
|
283
|
+
# :reek:UtilityFunction
|
|
284
|
+
private def bravo(charlie)
|
|
285
|
+
charlie.delta.echo
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
EOS
|
|
289
|
+
|
|
290
|
+
expect(src).not_to reek_of(:UtilityFunction)
|
|
239
291
|
end
|
|
240
292
|
end
|
|
241
293
|
end
|
|
@@ -7,7 +7,7 @@ RSpec.describe Reek::SmellWarning do
|
|
|
7
7
|
let(:utility_function_detector) { build(:smell_detector, smell_type: 'UtilityFunction') }
|
|
8
8
|
let(:uncommunicative_name_detector) { build(:smell_detector, smell_type: 'UncommunicativeVariableName') }
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
describe 'sort order' do
|
|
11
11
|
shared_examples_for 'first sorts ahead of second' do
|
|
12
12
|
it 'hash differently' do
|
|
13
13
|
expect(first.hash).not_to eq(second.hash)
|
|
@@ -26,21 +26,21 @@ RSpec.describe Reek::SmellWarning do
|
|
|
26
26
|
end
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
context 'smells
|
|
29
|
+
context 'when smells differ only by detector' do
|
|
30
30
|
let(:first) { build(:smell_warning, smell_detector: duplication_detector) }
|
|
31
31
|
let(:second) { build(:smell_warning, smell_detector: feature_envy_detector) }
|
|
32
32
|
|
|
33
33
|
it_behaves_like 'first sorts ahead of second'
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
-
context 'smells
|
|
36
|
+
context 'when smells differ only by lines' do
|
|
37
37
|
let(:first) { build(:smell_warning, smell_detector: feature_envy_detector, lines: [2]) }
|
|
38
38
|
let(:second) { build(:smell_warning, smell_detector: feature_envy_detector, lines: [3]) }
|
|
39
39
|
|
|
40
40
|
it_behaves_like 'first sorts ahead of second'
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
context 'smells
|
|
43
|
+
context 'when smells differ only by context' do
|
|
44
44
|
let(:first) { build(:smell_warning, smell_detector: duplication_detector, context: 'first') }
|
|
45
45
|
let(:second) do
|
|
46
46
|
build(:smell_warning, smell_detector: duplication_detector, context: 'second')
|
|
@@ -49,7 +49,7 @@ RSpec.describe Reek::SmellWarning do
|
|
|
49
49
|
it_behaves_like 'first sorts ahead of second'
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
context 'smells
|
|
52
|
+
context 'when smells differ only by message' do
|
|
53
53
|
let(:first) do
|
|
54
54
|
build(:smell_warning, smell_detector: duplication_detector,
|
|
55
55
|
context: 'ctx', message: 'first message')
|
|
@@ -62,7 +62,7 @@ RSpec.describe Reek::SmellWarning do
|
|
|
62
62
|
it_behaves_like 'first sorts ahead of second'
|
|
63
63
|
end
|
|
64
64
|
|
|
65
|
-
context '
|
|
65
|
+
context 'when smells differ by name and message' do
|
|
66
66
|
let(:first) do
|
|
67
67
|
build(:smell_warning, smell_detector: feature_envy_detector, message: 'second message')
|
|
68
68
|
end
|
|
@@ -73,7 +73,7 @@ RSpec.describe Reek::SmellWarning do
|
|
|
73
73
|
it_behaves_like 'first sorts ahead of second'
|
|
74
74
|
end
|
|
75
75
|
|
|
76
|
-
context 'smells
|
|
76
|
+
context 'when smells differ everywhere' do
|
|
77
77
|
let(:first) do
|
|
78
78
|
build(:smell_warning, smell_detector: duplication_detector,
|
|
79
79
|
context: 'Dirty#a',
|
|
@@ -97,7 +97,7 @@ RSpec.describe Reek::SmellWarning do
|
|
|
97
97
|
end
|
|
98
98
|
end
|
|
99
99
|
|
|
100
|
-
|
|
100
|
+
describe '#yaml_hash' do
|
|
101
101
|
let(:context_name) { 'Module::Class#method/block' }
|
|
102
102
|
let(:lines) { [24, 513] }
|
|
103
103
|
let(:message) { 'test message' }
|
|
@@ -135,6 +135,10 @@ RSpec.describe Reek::SmellWarning do
|
|
|
135
135
|
expect(yaml['source']).to eq source
|
|
136
136
|
end
|
|
137
137
|
|
|
138
|
+
it 'includes the documentation link' do
|
|
139
|
+
expect(yaml['documentation_link']).to eq Reek::DocumentationLink.build('FeatureEnvy')
|
|
140
|
+
end
|
|
141
|
+
|
|
138
142
|
it 'includes the parameters' do
|
|
139
143
|
parameters.each do |key, value|
|
|
140
144
|
expect(yaml[key]).to eq value
|
|
@@ -6,71 +6,60 @@ RSpec.describe Reek::Source::SourceCode do
|
|
|
6
6
|
describe '#syntax_tree' do
|
|
7
7
|
it 'associates comments with the AST' do
|
|
8
8
|
source = "# this is\n# a comment\ndef foo; end"
|
|
9
|
-
source_code = described_class.new(
|
|
9
|
+
source_code = described_class.new(source: source, origin: '(string)')
|
|
10
10
|
result = source_code.syntax_tree
|
|
11
11
|
expect(result.leading_comment).to eq "# this is\n# a comment"
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
it 'cleanly processes empty source' do
|
|
15
|
-
source_code = described_class.new(
|
|
15
|
+
source_code = described_class.new(source: '', origin: '(string)')
|
|
16
16
|
result = source_code.syntax_tree
|
|
17
|
-
expect(result).to
|
|
17
|
+
expect(result.type).to eq :empty
|
|
18
18
|
end
|
|
19
19
|
|
|
20
20
|
it 'cleanly processes empty source with comments' do
|
|
21
21
|
source = "# this is\n# a comment\n"
|
|
22
|
-
source_code = described_class.new(
|
|
22
|
+
source_code = described_class.new(source: source, origin: '(string)')
|
|
23
23
|
result = source_code.syntax_tree
|
|
24
|
-
expect(result).to
|
|
24
|
+
expect(result.type).to eq :empty
|
|
25
25
|
end
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
context 'when the parser fails' do
|
|
29
|
-
let(:source_name) { 'Test source' }
|
|
30
|
-
let(:error_message) { 'Error message' }
|
|
31
|
-
let(:parser) { class_double(Parser::Ruby23) }
|
|
32
|
-
let(:src) { described_class.new(code: '', origin: source_name, parser: parser) }
|
|
33
26
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
27
|
+
it 'does not crash with sequences incompatible with UTF-8' do
|
|
28
|
+
source = '"\xFF"'
|
|
29
|
+
source_code = described_class.new(source: source, origin: '(string)')
|
|
30
|
+
result = source_code.syntax_tree
|
|
31
|
+
expect(result.children.first).to eq "\xFF"
|
|
39
32
|
end
|
|
40
33
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
allow(parser).to receive(:parse_with_comments).
|
|
47
|
-
and_raise error_class.new(diagnostic)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
it_behaves_like 'handling and recording the error'
|
|
34
|
+
it 'returns a :lambda node for lambda expressions' do
|
|
35
|
+
source = '->() { }'
|
|
36
|
+
source_code = described_class.new(source: source, origin: '(string)')
|
|
37
|
+
result = source_code.syntax_tree
|
|
38
|
+
expect(result.children.first.type).to eq :lambda
|
|
51
39
|
end
|
|
52
40
|
|
|
53
|
-
context 'with a
|
|
54
|
-
let(:
|
|
41
|
+
context 'when the parser fails with a Parser::SyntaxError' do
|
|
42
|
+
let(:src) { described_class.new(source: code) }
|
|
43
|
+
let(:code) { '== Invalid Syntax ==' }
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
and_raise(error_class.new(error_message))
|
|
45
|
+
it 'raises the error' do
|
|
46
|
+
expect { src.syntax_tree }.to raise_error Parser::SyntaxError
|
|
59
47
|
end
|
|
60
|
-
|
|
61
|
-
it_behaves_like 'handling and recording the error'
|
|
62
48
|
end
|
|
63
49
|
|
|
64
|
-
context 'with a generic error' do
|
|
50
|
+
context 'when the parser fails with a generic error' do
|
|
51
|
+
let(:code) { '' }
|
|
52
|
+
let(:parser) { instance_double('Parser::Ruby25') }
|
|
53
|
+
let(:src) { described_class.new(source: code, parser: parser) }
|
|
65
54
|
let(:error_class) { RuntimeError }
|
|
55
|
+
let(:error_message) { 'An error' }
|
|
66
56
|
|
|
67
57
|
before do
|
|
68
|
-
allow(parser).to receive(:parse_with_comments).
|
|
69
|
-
and_raise(error_class.new(error_message))
|
|
58
|
+
allow(parser).to receive(:parse_with_comments).and_raise(error_class, error_message)
|
|
70
59
|
end
|
|
71
60
|
|
|
72
61
|
it 'raises the error' do
|
|
73
|
-
expect { src.syntax_tree }.to raise_error error_class
|
|
62
|
+
expect { src.syntax_tree }.to raise_error error_class, error_message
|
|
74
63
|
end
|
|
75
64
|
end
|
|
76
65
|
end
|
|
@@ -5,15 +5,15 @@ require_lib 'reek/source/source_locator'
|
|
|
5
5
|
|
|
6
6
|
RSpec.describe Reek::Source::SourceLocator do
|
|
7
7
|
describe '#sources' do
|
|
8
|
-
context 'applied to hidden directories' do
|
|
9
|
-
let(:path) {
|
|
8
|
+
context 'when applied to hidden directories' do
|
|
9
|
+
let(:path) { SAMPLES_DIR.join('source_with_hidden_directories') }
|
|
10
10
|
|
|
11
11
|
let(:expected_paths) do
|
|
12
|
-
[path.join('
|
|
12
|
+
[path.join('not_hidden.rb')]
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
let(:paths_that_are_expected_to_be_ignored) do
|
|
16
|
-
[path.join('.hidden/
|
|
16
|
+
[path.join('.hidden/hidden.rb')]
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
it 'does not scan hidden directories' do
|
|
@@ -30,15 +30,45 @@ RSpec.describe Reek::Source::SourceLocator do
|
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
# rubocop:disable RSpec/NestedGroups
|
|
33
|
-
context '
|
|
33
|
+
context 'with excluded paths' do
|
|
34
34
|
let(:configuration) do
|
|
35
|
-
test_configuration_for(
|
|
35
|
+
test_configuration_for(CONFIGURATION_DIR.join('with_excluded_paths.reek'))
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
let(:options) { instance_double('Reek::CLI::Options', force_exclusion?: false) }
|
|
39
39
|
|
|
40
|
+
context 'when the path is absolute' do
|
|
41
|
+
let(:path) do
|
|
42
|
+
SAMPLES_DIR.join('source_with_exclude_paths',
|
|
43
|
+
'ignore_me',
|
|
44
|
+
'uncommunicative_method_name.rb').expand_path
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context 'when options.force_exclusion? is true' do
|
|
48
|
+
before do
|
|
49
|
+
allow(options).to receive(:force_exclusion?).and_return(true)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'excludes this file' do
|
|
53
|
+
sources = described_class.new([path], configuration: configuration, options: options).sources
|
|
54
|
+
expect(sources).not_to include(path)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context 'when options.force_exclusion? is false' do
|
|
59
|
+
before do
|
|
60
|
+
allow(options).to receive(:force_exclusion?).and_return(false)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'includes this file' do
|
|
64
|
+
sources = described_class.new([path], configuration: configuration, options: options).sources
|
|
65
|
+
expect(sources).to include(path)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
40
70
|
context 'when the path is a file name in an excluded directory' do
|
|
41
|
-
let(:path) {
|
|
71
|
+
let(:path) { SAMPLES_DIR.join('source_with_exclude_paths', 'ignore_me', 'uncommunicative_method_name.rb') }
|
|
42
72
|
|
|
43
73
|
context 'when options.force_exclusion? is true' do
|
|
44
74
|
before do
|
|
@@ -64,7 +94,7 @@ RSpec.describe Reek::Source::SourceLocator do
|
|
|
64
94
|
end
|
|
65
95
|
|
|
66
96
|
context 'when path is a directory' do
|
|
67
|
-
let(:path) {
|
|
97
|
+
let(:path) { SAMPLES_DIR.join('source_with_exclude_paths') }
|
|
68
98
|
|
|
69
99
|
let(:expected_paths) do
|
|
70
100
|
[path.join('nested/uncommunicative_parameter_name.rb')]
|
|
@@ -90,10 +120,10 @@ RSpec.describe Reek::Source::SourceLocator do
|
|
|
90
120
|
end
|
|
91
121
|
# rubocop:enable RSpec/NestedGroups
|
|
92
122
|
|
|
93
|
-
context 'non-Ruby paths' do
|
|
94
|
-
let(:path) {
|
|
123
|
+
context 'with non-Ruby paths' do
|
|
124
|
+
let(:path) { SAMPLES_DIR.join('source_with_non_ruby_files') }
|
|
95
125
|
let(:expected_sources) do
|
|
96
|
-
[path.join('
|
|
126
|
+
[path.join('ruby.rb')]
|
|
97
127
|
end
|
|
98
128
|
let(:paths_that_are_expected_to_be_ignored) do
|
|
99
129
|
[
|
|
@@ -115,7 +145,7 @@ RSpec.describe Reek::Source::SourceLocator do
|
|
|
115
145
|
end
|
|
116
146
|
end
|
|
117
147
|
|
|
118
|
-
context 'passing "." or "./" as argument' do
|
|
148
|
+
context 'when passing "." or "./" as argument' do
|
|
119
149
|
let(:expected_sources) do
|
|
120
150
|
[Pathname.new('spec/spec_helper.rb'), Pathname.new('lib/reek.rb')]
|
|
121
151
|
end
|