reek 4.7.3 → 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 +18 -3
- data/.simplecov +1 -0
- data/.travis.yml +3 -4
- data/.yardopts +1 -1
- data/CHANGELOG.md +45 -0
- data/Gemfile +4 -4
- data/README.md +134 -104
- data/Rakefile +16 -3
- data/bin/reek +1 -3
- data/docs/API.md +2 -9
- data/docs/Basic-Smell-Options.md +51 -11
- data/docs/Code-Smells.md +1 -1
- data/docs/Command-Line-Options.md +14 -4
- data/docs/Duplicate-Method-Call.md +49 -1
- data/docs/Feature-Envy.md +44 -0
- data/docs/How-To-Write-New-Detectors.md +2 -3
- data/docs/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 +2 -2
- 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 +30 -8
- data/features/configuration_files/accept_setting.feature +45 -28
- data/features/configuration_files/directory_specific_directives.feature +78 -73
- 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 +2 -2
- data/features/configuration_via_source_comments/well_formed_source_comments.feature +2 -2
- data/features/locales.feature +2 -2
- data/features/rake_task/rake_task.feature +15 -15
- 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 +9 -1
- data/features/samples.feature +287 -287
- data/features/step_definitions/reek_steps.rb +4 -0
- data/features/step_definitions/sample_file_steps.rb +9 -4
- data/features/support/env.rb +2 -2
- data/features/todo_list.feature +26 -23
- data/lib/reek/ast/node.rb +40 -55
- data/lib/reek/ast/object_refs.rb +1 -1
- data/lib/reek/ast/reference_collector.rb +2 -4
- data/lib/reek/ast/sexp_extensions/case.rb +1 -1
- data/lib/reek/ast/sexp_extensions/if.rb +8 -1
- data/lib/reek/ast/sexp_extensions/logical_operators.rb +1 -1
- data/lib/reek/ast/sexp_extensions/methods.rb +4 -6
- data/lib/reek/cli/application.rb +4 -3
- data/lib/reek/cli/command/report_command.rb +1 -2
- data/lib/reek/cli/command/todo_list_command.rb +8 -8
- data/lib/reek/cli/options.rb +29 -14
- data/lib/reek/cli/silencer.rb +14 -3
- data/lib/reek/code_comment.rb +14 -16
- data/lib/reek/configuration/app_configuration.rb +32 -28
- data/lib/reek/configuration/configuration_converter.rb +110 -0
- data/lib/reek/configuration/configuration_file_finder.rb +15 -40
- data/lib/reek/configuration/configuration_validator.rb +12 -23
- data/lib/reek/configuration/default_directive.rb +17 -3
- data/lib/reek/configuration/directory_directives.rb +17 -11
- data/lib/reek/configuration/excluded_paths.rb +1 -1
- data/lib/reek/configuration/rake_task_converter.rb +29 -0
- data/lib/reek/configuration/schema.yml +210 -0
- data/lib/reek/configuration/schema_validator.rb +38 -0
- data/lib/reek/context/attribute_context.rb +1 -1
- data/lib/reek/context/code_context.rb +8 -11
- data/lib/reek/context/method_context.rb +7 -12
- data/lib/reek/context/module_context.rb +4 -4
- data/lib/reek/context_builder.rb +11 -11
- data/lib/reek/detector_repository.rb +6 -0
- data/lib/reek/documentation_link.rb +28 -0
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +13 -12
- data/lib/reek/errors/bad_detector_in_comment_error.rb +11 -10
- 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 +16 -11
- data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +11 -10
- data/lib/reek/errors/incomprehensible_source_error.rb +20 -22
- data/lib/reek/errors/syntax_error.rb +41 -0
- data/lib/reek/examiner.rb +19 -25
- data/lib/reek/logging_error_handler.rb +7 -5
- data/lib/reek/rake/task.rb +3 -3
- data/lib/reek/report/base_report.rb +8 -12
- data/lib/reek/report/code_climate/code_climate_configuration.rb +1 -1
- data/lib/reek/report/code_climate/code_climate_configuration.yml +6 -10
- data/lib/reek/report/documentation_link_warning_formatter.rb +17 -0
- data/lib/reek/report/heading_formatter.rb +54 -0
- data/lib/reek/report/json_report.rb +1 -1
- data/lib/reek/report/location_formatter.rb +40 -0
- data/lib/reek/report/progress_formatter.rb +79 -0
- data/lib/reek/report/simple_warning_formatter.rb +34 -0
- data/lib/reek/report/text_report.rb +1 -2
- data/lib/reek/report/xml_report.rb +3 -3
- data/lib/reek/report/yaml_report.rb +1 -1
- data/lib/reek/report.rb +15 -10
- data/lib/reek/smell_configuration.rb +2 -2
- data/lib/reek/smell_detectors/attribute.rb +0 -1
- data/lib/reek/smell_detectors/base_detector.rb +9 -12
- data/lib/reek/smell_detectors/boolean_parameter.rb +0 -1
- data/lib/reek/smell_detectors/class_variable.rb +3 -11
- data/lib/reek/smell_detectors/control_parameter.rb +17 -32
- data/lib/reek/smell_detectors/data_clump.rb +3 -4
- data/lib/reek/smell_detectors/duplicate_method_call.rb +6 -7
- data/lib/reek/smell_detectors/feature_envy.rb +1 -1
- data/lib/reek/smell_detectors/instance_variable_assumption.rb +1 -10
- data/lib/reek/smell_detectors/irresponsible_module.rb +0 -1
- data/lib/reek/smell_detectors/long_parameter_list.rb +1 -2
- data/lib/reek/smell_detectors/long_yield_list.rb +2 -3
- data/lib/reek/smell_detectors/manual_dispatch.rb +3 -3
- data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +6 -7
- data/lib/reek/smell_detectors/module_initialize.rb +1 -2
- data/lib/reek/smell_detectors/nested_iterators.rb +6 -6
- data/lib/reek/smell_detectors/nil_check.rb +0 -1
- data/lib/reek/smell_detectors/repeated_conditional.rb +3 -4
- data/lib/reek/smell_detectors/subclassed_from_core_class.rb +0 -1
- data/lib/reek/smell_detectors/too_many_constants.rb +2 -3
- data/lib/reek/smell_detectors/too_many_instance_variables.rb +1 -2
- data/lib/reek/smell_detectors/too_many_methods.rb +1 -2
- data/lib/reek/smell_detectors/too_many_statements.rb +1 -2
- data/lib/reek/smell_detectors/uncommunicative_method_name.rb +2 -3
- data/lib/reek/smell_detectors/uncommunicative_module_name.rb +2 -3
- data/lib/reek/smell_detectors/uncommunicative_parameter_name.rb +2 -3
- data/lib/reek/smell_detectors/uncommunicative_variable_name.rb +6 -7
- data/lib/reek/smell_detectors/unused_parameters.rb +0 -1
- data/lib/reek/smell_detectors/unused_private_method.rb +0 -1
- data/lib/reek/smell_detectors/utility_function.rb +2 -3
- data/lib/reek/smell_detectors.rb +1 -2
- data/lib/reek/smell_warning.rb +15 -8
- data/lib/reek/source/source_code.rb +50 -72
- data/lib/reek/source/source_locator.rb +7 -7
- data/lib/reek/spec/should_reek.rb +2 -2
- data/lib/reek/spec/should_reek_of.rb +9 -16
- data/lib/reek/spec/should_reek_only_of.rb +4 -4
- data/lib/reek/spec.rb +6 -6
- data/lib/reek/tree_dresser.rb +5 -5
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +5 -5
- 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 +2 -2
- data/spec/reek/cli/application_spec.rb +50 -38
- 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 -49
- 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 +60 -96
- data/spec/reek/context/ghost_context_spec.rb +1 -1
- data/spec/reek/context/root_context_spec.rb +1 -1
- 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 +100 -30
- data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +82 -80
- data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +6 -6
- 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 +9 -38
- data/spec/reek/report_spec.rb +3 -3
- 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/{prima_donna_method_spec.rb → missing_safe_method_spec.rb} +9 -9
- 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 +6 -4
- 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 +10 -10
- data/spec/reek/smell_detectors/utility_function_spec.rb +5 -5
- data/spec/reek/smell_warning_spec.rb +12 -8
- data/spec/reek/source/source_code_spec.rb +17 -43
- data/spec/reek/source/source_locator_spec.rb +17 -17
- data/spec/reek/spec/should_reek_of_spec.rb +7 -11
- data/spec/reek/spec/should_reek_only_of_spec.rb +2 -2
- data/spec/reek/spec/should_reek_spec.rb +3 -3
- data/spec/reek/spec/smell_matcher_spec.rb +3 -3
- data/spec/reek/tree_dresser_spec.rb +12 -17
- data/spec/spec_helper.rb +6 -17
- data/tasks/configuration.rake +8 -5
- metadata +71 -41
- data/defaults.reek +0 -131
- data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
- data/lib/reek/report/formatter/heading_formatter.rb +0 -52
- data/lib/reek/report/formatter/location_formatter.rb +0 -42
- data/lib/reek/report/formatter/progress_formatter.rb +0 -81
- data/lib/reek/report/formatter/simple_warning_formatter.rb +0 -35
- data/lib/reek/report/formatter/wiki_link_warning_formatter.rb +0 -36
- data/lib/reek/report/formatter.rb +0 -33
- data/lib/reek/smell_detectors/syntax.rb +0 -37
- data/samples/configuration/non_public_modifiers_mask.reek +0 -3
- data/samples/smelly_with_inline_mask.rb +0 -8
- data/samples/smelly_with_modifiers.rb +0 -12
- data/samples/source_with_hidden_directories/.hidden/uncommunicative_method_name.rb +0 -5
- data/samples/source_with_non_ruby_files/uncommunicative_parameter_name.rb +0 -6
- data/spec/reek/smell_detectors/syntax_spec.rb +0 -17
- /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
data/reek.gemspec
CHANGED
|
@@ -5,7 +5,6 @@ Gem::Specification.new do |s|
|
|
|
5
5
|
s.version = Reek::Version::STRING
|
|
6
6
|
|
|
7
7
|
s.authors = ['Kevin Rutherford', 'Timo Roessner', 'Matijs van Zuijlen', 'Piotr Szotkowski']
|
|
8
|
-
s.default_executable = 'reek'
|
|
9
8
|
s.description =
|
|
10
9
|
'Reek is a tool that examines Ruby classes, modules and methods and reports ' \
|
|
11
10
|
'any code smells it finds.'
|
|
@@ -15,12 +14,13 @@ Gem::Specification.new do |s|
|
|
|
15
14
|
s.extra_rdoc_files = ['CHANGELOG.md', 'License.txt']
|
|
16
15
|
s.files = `git ls-files -z`.split("\0")
|
|
17
16
|
s.executables = s.files.grep(%r{^bin/}).map { |path| File.basename(path) }
|
|
18
|
-
s.homepage = 'https://github.com/troessner/reek
|
|
17
|
+
s.homepage = 'https://github.com/troessner/reek'
|
|
19
18
|
s.rdoc_options = %w(--main README.md -x assets/|bin/|config/|features/|spec/|tasks/)
|
|
20
|
-
s.required_ruby_version = '>= 2.
|
|
19
|
+
s.required_ruby_version = '>= 2.3.0'
|
|
21
20
|
s.summary = 'Code smell detector for Ruby'
|
|
22
21
|
|
|
23
22
|
s.add_runtime_dependency 'codeclimate-engine-rb', '~> 0.4.0'
|
|
24
|
-
s.add_runtime_dependency '
|
|
25
|
-
s.add_runtime_dependency '
|
|
23
|
+
s.add_runtime_dependency 'kwalify', '~> 0.7.0'
|
|
24
|
+
s.add_runtime_dependency 'parser', '< 2.6', '>= 2.5.0.0'
|
|
25
|
+
s.add_runtime_dependency 'rainbow', '>= 2.0', '< 4.0'
|
|
26
26
|
end
|
data/samples/checkstyle.xml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<?xml version='1.0'?>
|
|
2
2
|
<checkstyle>
|
|
3
|
-
<file name='samples/smelly.rb'>
|
|
3
|
+
<file name='samples/smelly_source/smelly.rb'>
|
|
4
4
|
<error column='0' line='4' message='has the name 'x'' severity='warning' source='UncommunicativeMethodName'/>
|
|
5
5
|
<error column='0' line='5' message='has the variable name 'y'' severity='warning' source='UncommunicativeVariableName'/>
|
|
6
6
|
</file>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
detectors:
|
|
3
|
+
UnusedPrivateMethod:
|
|
4
|
+
exclude:
|
|
5
|
+
- "/exclude regexp/"
|
|
6
|
+
UncommunicativeMethodName:
|
|
7
|
+
reject:
|
|
8
|
+
- "reject name"
|
|
9
|
+
accept:
|
|
10
|
+
- "accept name"
|
|
11
|
+
UncommunicativeModuleName:
|
|
12
|
+
reject:
|
|
13
|
+
- "reject name 1"
|
|
14
|
+
- "reject name 2"
|
|
15
|
+
accept:
|
|
16
|
+
- "accept name 1"
|
|
17
|
+
- "accept name 2"
|
|
18
|
+
UncommunicativeParameterName:
|
|
19
|
+
reject:
|
|
20
|
+
- "reject name"
|
|
21
|
+
- "/reject regexp/"
|
|
22
|
+
accept:
|
|
23
|
+
- "accept name"
|
|
24
|
+
- "/accept regexp/"
|
|
25
|
+
UncommunicativeVariableName:
|
|
26
|
+
reject:
|
|
27
|
+
- "/^reject regexp$/"
|
|
28
|
+
accept:
|
|
29
|
+
- "/accept(.*)regexp/"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
directories:
|
|
3
|
+
"app/controllers":
|
|
4
|
+
UnusedPrivateMethod:
|
|
5
|
+
exclude:
|
|
6
|
+
- "/exclude regexp/"
|
|
7
|
+
UncommunicativeMethodName:
|
|
8
|
+
reject:
|
|
9
|
+
- "reject name"
|
|
10
|
+
accept:
|
|
11
|
+
- "accept name"
|
|
12
|
+
UncommunicativeModuleName:
|
|
13
|
+
reject:
|
|
14
|
+
- "reject name 1"
|
|
15
|
+
- "reject name 2"
|
|
16
|
+
accept:
|
|
17
|
+
- "accept name 1"
|
|
18
|
+
- "accept name 2"
|
|
19
|
+
UncommunicativeParameterName:
|
|
20
|
+
reject:
|
|
21
|
+
- "reject name"
|
|
22
|
+
- "/reject regexp/"
|
|
23
|
+
accept:
|
|
24
|
+
- "accept name"
|
|
25
|
+
- "/accept regexp/"
|
|
26
|
+
UncommunicativeVariableName:
|
|
27
|
+
reject:
|
|
28
|
+
- "/^reject regexp$/"
|
|
29
|
+
accept:
|
|
30
|
+
- "/accept(.*)regexp/"
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
"samples/three_clean_files/":
|
|
5
|
-
UtilityFunction:
|
|
2
|
+
detectors:
|
|
3
|
+
IrresponsibleModule:
|
|
6
4
|
enabled: false
|
|
5
|
+
|
|
6
|
+
directories:
|
|
7
|
+
"samples/three_clean_files/":
|
|
8
|
+
UtilityFunction:
|
|
9
|
+
enabled: false
|
|
10
|
+
|
|
7
11
|
exclude_paths:
|
|
8
12
|
- "samples/two_smelly_files/"
|
|
9
13
|
- "samples/source_with_non_ruby_files/"
|
data/samples/paths.rb
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
CLEAN_FILE =
|
|
4
|
-
SMELLY_FILE =
|
|
1
|
+
SAMPLES_DIR = Pathname.new(__dir__).relative_path_from(Pathname.pwd)
|
|
2
|
+
CONFIGURATION_DIR = SAMPLES_DIR.join('configuration')
|
|
3
|
+
CLEAN_FILE = SAMPLES_DIR.join('clean_source').join('clean.rb')
|
|
4
|
+
SMELLY_FILE = SAMPLES_DIR.join('smelly_source').join('smelly.rb')
|
|
5
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
data/spec/factories/factories.rb
CHANGED
|
@@ -3,18 +3,7 @@ require_relative '../../lib/reek/smell_detectors/base_detector'
|
|
|
3
3
|
require_relative '../../lib/reek/smell_warning'
|
|
4
4
|
require_relative '../../lib/reek/cli/options'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
factory :method_context, class: Reek::Context::MethodContext do
|
|
8
|
-
skip_create
|
|
9
|
-
transient do
|
|
10
|
-
source 'def foo; end'
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
initialize_with do
|
|
14
|
-
new(nil, Reek::Source::SourceCode.from(source).syntax_tree)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
6
|
+
FactoryBot.define do
|
|
18
7
|
factory :smell_detector, class: Reek::SmellDetectors::BaseDetector do
|
|
19
8
|
skip_create
|
|
20
9
|
transient do
|
|
@@ -33,7 +22,7 @@ FactoryGirl.define do
|
|
|
33
22
|
source 'dummy_file'
|
|
34
23
|
lines [42]
|
|
35
24
|
message 'smell warning message'
|
|
36
|
-
parameters
|
|
25
|
+
parameters({})
|
|
37
26
|
|
|
38
27
|
initialize_with do
|
|
39
28
|
new(smell_detector,
|
data/spec/reek/ast/node_spec.rb
CHANGED
|
@@ -2,6 +2,92 @@ require_relative '../../spec_helper'
|
|
|
2
2
|
require_lib 'reek/ast/node'
|
|
3
3
|
|
|
4
4
|
RSpec.describe Reek::AST::Node do
|
|
5
|
+
describe '#each_node' do
|
|
6
|
+
context 'with an empty module' do
|
|
7
|
+
let(:ast) do
|
|
8
|
+
src = 'module Emptiness; end'
|
|
9
|
+
Reek::Source::SourceCode.from(src).syntax_tree
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it 'yields no calls' do
|
|
13
|
+
ast.each_node(:send, []) { |exp| raise "#{exp} yielded by empty module!" }
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it 'yields one module' do
|
|
17
|
+
mods = 0
|
|
18
|
+
ast.each_node(:module, []) { |_exp| mods += 1 }
|
|
19
|
+
expect(mods).to eq(1)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "yields the module's full AST" do
|
|
23
|
+
ast.each_node(:module, []) do |exp|
|
|
24
|
+
expect(exp).to eq(sexp(:module, sexp(:const, nil, :Emptiness), nil))
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'returns an enumerator when no block is passed' do
|
|
29
|
+
expect(ast.each_node(:if)).to be_instance_of Enumerator
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context 'with a nested element' do
|
|
34
|
+
let(:ast) do
|
|
35
|
+
src = "module Loneliness; def calloo; puts('hello') end; end"
|
|
36
|
+
Reek::Source::SourceCode.from(src).syntax_tree
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'yields no ifs' do
|
|
40
|
+
ast.each_node(:if) { |exp| raise "#{exp} yielded by empty module!" }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it 'yields one module' do
|
|
44
|
+
expect(ast.each_node(:module).to_a.length).to eq(1)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "yields the module's full AST" do
|
|
48
|
+
ast.each_node(:module) do |exp|
|
|
49
|
+
expect(exp).to eq sexp(:module,
|
|
50
|
+
sexp(:const, nil, :Loneliness),
|
|
51
|
+
sexp(:def, :calloo,
|
|
52
|
+
sexp(:args),
|
|
53
|
+
sexp(:send, nil, :puts, sexp(:str, 'hello'))))
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'yields one method' do
|
|
58
|
+
expect(ast.each_node(:def).to_a.length).to eq(1)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it "yields the method's full AST" do
|
|
62
|
+
ast.each_node(:def, []) { |exp| expect(exp.children.first).to eq(:calloo) }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'ignores the call inside the method if the traversal is pruned' do
|
|
66
|
+
expect(ast.each_node(:send, [:def]).to_a).to be_empty
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'finds 3 ifs in a class' do
|
|
71
|
+
src = <<-EOS
|
|
72
|
+
class Scrunch
|
|
73
|
+
def first
|
|
74
|
+
return @field == :sym ? 0 : 3;
|
|
75
|
+
end
|
|
76
|
+
def second
|
|
77
|
+
if @field == :sym
|
|
78
|
+
@other += " quarts"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
def third
|
|
82
|
+
raise 'flu!' unless @field == :sym
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
EOS
|
|
86
|
+
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
|
87
|
+
expect(ast.each_node(:if).to_a.length).to eq(3)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
5
91
|
describe '#format_to_ruby' do
|
|
6
92
|
it 'returns #to_s if location is not present' do
|
|
7
93
|
ast = sexp(:self)
|
|
@@ -56,7 +142,7 @@ RSpec.describe Reek::AST::Node do
|
|
|
56
142
|
end
|
|
57
143
|
end
|
|
58
144
|
|
|
59
|
-
|
|
145
|
+
describe '#hash' do
|
|
60
146
|
it 'hashes equal for equal sexps' do
|
|
61
147
|
node1 = sexp(:def, :jim, sexp(:args), sexp(:send, sexp(:int, 4), :+, sexp(:send, nil, :fred)))
|
|
62
148
|
node2 = sexp(:def, :jim, sexp(:args), sexp(:send, sexp(:int, 4), :+, sexp(:send, nil, :fred)))
|
|
@@ -77,8 +163,8 @@ RSpec.describe Reek::AST::Node do
|
|
|
77
163
|
end
|
|
78
164
|
|
|
79
165
|
describe '#line' do
|
|
80
|
-
context 'source from file' do
|
|
81
|
-
let(:file) {
|
|
166
|
+
context 'with source from a file' do
|
|
167
|
+
let(:file) { SMELLY_FILE }
|
|
82
168
|
let(:ast) { Reek::Source::SourceCode.from(file).syntax_tree }
|
|
83
169
|
|
|
84
170
|
it 'returns the right line number' do
|
|
@@ -86,8 +172,8 @@ RSpec.describe Reek::AST::Node do
|
|
|
86
172
|
end
|
|
87
173
|
end
|
|
88
174
|
|
|
89
|
-
context 'source from string' do
|
|
90
|
-
let(:source) { File.read(
|
|
175
|
+
context 'with source from a string' do
|
|
176
|
+
let(:source) { File.read(SMELLY_FILE) }
|
|
91
177
|
let(:ast) { Reek::Source::SourceCode.from(source).syntax_tree }
|
|
92
178
|
|
|
93
179
|
it 'returns the right line number' do
|
|
@@ -97,17 +183,17 @@ RSpec.describe Reek::AST::Node do
|
|
|
97
183
|
end
|
|
98
184
|
|
|
99
185
|
describe '#source' do
|
|
100
|
-
context 'source from file' do
|
|
101
|
-
let(:file) {
|
|
186
|
+
context 'with source from a file' do
|
|
187
|
+
let(:file) { SMELLY_FILE }
|
|
102
188
|
let(:ast) { Reek::Source::SourceCode.from(file).syntax_tree }
|
|
103
189
|
|
|
104
190
|
it 'returns the file name' do
|
|
105
|
-
expect(ast.source).to eq(
|
|
191
|
+
expect(ast.source).to eq(SMELLY_FILE.to_s)
|
|
106
192
|
end
|
|
107
193
|
end
|
|
108
194
|
|
|
109
|
-
context 'source from string' do
|
|
110
|
-
let(:source) { File.read
|
|
195
|
+
context 'with source from a string' do
|
|
196
|
+
let(:source) { File.read SMELLY_FILE }
|
|
111
197
|
let(:ast) { Reek::Source::SourceCode.from(source).syntax_tree }
|
|
112
198
|
|
|
113
199
|
it 'returns "string"' do
|
|
@@ -115,4 +201,11 @@ RSpec.describe Reek::AST::Node do
|
|
|
115
201
|
end
|
|
116
202
|
end
|
|
117
203
|
end
|
|
204
|
+
|
|
205
|
+
describe '#name' do
|
|
206
|
+
it 'returns #to_s if no override is present' do
|
|
207
|
+
ast = sexp(:foo)
|
|
208
|
+
expect(ast.name).to eq ast.to_s
|
|
209
|
+
end
|
|
210
|
+
end
|
|
118
211
|
end
|
|
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
|
|
|
2
2
|
require_lib 'reek/ast/reference_collector'
|
|
3
3
|
|
|
4
4
|
RSpec.describe Reek::AST::ReferenceCollector do
|
|
5
|
-
|
|
5
|
+
describe '#num_refs_to_self' do
|
|
6
6
|
def refs_to_self(src)
|
|
7
7
|
syntax_tree = Reek::Source::SourceCode.from(src).syntax_tree
|
|
8
8
|
described_class.new(syntax_tree).num_refs_to_self
|
|
@@ -107,7 +107,7 @@ RSpec.describe Reek::AST::SexpExtensions::DefNode do
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
it 'finds nodes in the body with #body_nodes' do
|
|
110
|
-
expect(node.body_nodes([:first])).to eq [sexp(:first)]
|
|
110
|
+
expect(node.body_nodes([:first]).to_a).to eq [sexp(:first)]
|
|
111
111
|
end
|
|
112
112
|
end
|
|
113
113
|
|
|
@@ -374,7 +374,7 @@ end
|
|
|
374
374
|
RSpec.describe Reek::AST::SexpExtensions::LambdaNode do
|
|
375
375
|
let(:node) { sexp(:lambda) }
|
|
376
376
|
|
|
377
|
-
|
|
377
|
+
describe '#name' do
|
|
378
378
|
it 'returns :lambda' do
|
|
379
379
|
expect(node.name).to eq 'lambda'
|
|
380
380
|
end
|
|
@@ -17,9 +17,9 @@ RSpec.describe Reek::CLI::Application do
|
|
|
17
17
|
|
|
18
18
|
describe '#execute' do
|
|
19
19
|
let(:path_excluded_in_configuration) do
|
|
20
|
-
|
|
20
|
+
SAMPLES_DIR.join('source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb')
|
|
21
21
|
end
|
|
22
|
-
let(:configuration) { test_configuration_for(
|
|
22
|
+
let(:configuration) { test_configuration_for(CONFIGURATION_DIR.join('with_excluded_paths.reek')) }
|
|
23
23
|
let(:command) { instance_double 'Reek::CLI::Command::ReportCommand' }
|
|
24
24
|
let(:app) { described_class.new [] }
|
|
25
25
|
|
|
@@ -32,57 +32,69 @@ RSpec.describe Reek::CLI::Application do
|
|
|
32
32
|
expect(app.execute).to eq 'foo'
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
context 'when no source files given' do
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
end
|
|
35
|
+
context 'when no source files given and input was piped' do
|
|
36
|
+
before do
|
|
37
|
+
allow_any_instance_of(IO).to receive(:tty?).and_return(false)
|
|
38
|
+
end
|
|
40
39
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
40
|
+
it 'uses source from pipe' do
|
|
41
|
+
expected_sources = a_collection_containing_exactly(have_attributes(origin: 'STDIN'))
|
|
42
|
+
app.execute
|
|
43
|
+
expect(Reek::CLI::Command::ReportCommand).to have_received(:new).
|
|
44
|
+
with(sources: expected_sources,
|
|
45
|
+
configuration: Reek::Configuration::AppConfiguration,
|
|
46
|
+
options: Reek::CLI::Options)
|
|
48
47
|
end
|
|
49
48
|
|
|
50
|
-
context '
|
|
51
|
-
|
|
52
|
-
allow_any_instance_of(IO).to receive(:tty?).and_return(true)
|
|
53
|
-
end
|
|
49
|
+
context 'when a stdin filename is provided' do
|
|
50
|
+
let(:app) { described_class.new ['--stdin-filename', 'foo.rb'] }
|
|
54
51
|
|
|
55
|
-
it '
|
|
56
|
-
expected_sources =
|
|
52
|
+
it 'assumes that filename' do
|
|
53
|
+
expected_sources = a_collection_containing_exactly(have_attributes(origin: 'foo.rb'))
|
|
57
54
|
app.execute
|
|
58
55
|
expect(Reek::CLI::Command::ReportCommand).to have_received(:new).
|
|
59
56
|
with(sources: expected_sources,
|
|
60
57
|
configuration: Reek::Configuration::AppConfiguration,
|
|
61
58
|
options: Reek::CLI::Options)
|
|
62
59
|
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
63
62
|
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
context 'when no source files given and no input was piped' do
|
|
64
|
+
before do
|
|
65
|
+
allow_any_instance_of(IO).to receive(:tty?).and_return(true)
|
|
66
|
+
end
|
|
66
67
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
68
|
+
it 'uses working directory as source' do
|
|
69
|
+
expected_sources = Reek::Source::SourceLocator.new(['.']).sources
|
|
70
|
+
app.execute
|
|
71
|
+
expect(Reek::CLI::Command::ReportCommand).to have_received(:new).
|
|
72
|
+
with(sources: expected_sources,
|
|
73
|
+
configuration: Reek::Configuration::AppConfiguration,
|
|
74
|
+
options: Reek::CLI::Options)
|
|
75
|
+
end
|
|
73
76
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
new(['.'], configuration: configuration).sources
|
|
77
|
-
expect(expected_sources).not_to include(path_excluded_in_configuration)
|
|
77
|
+
context 'when source files are excluded through configuration' do
|
|
78
|
+
let(:app) { described_class.new ['--config', 'some_file.reek'] }
|
|
78
79
|
|
|
79
|
-
|
|
80
|
+
before do
|
|
81
|
+
allow(Reek::Configuration::AppConfiguration).
|
|
82
|
+
to receive(:from_path).
|
|
83
|
+
with(Pathname.new('some_file.reek')).
|
|
84
|
+
and_return configuration
|
|
85
|
+
end
|
|
80
86
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
it 'uses configuration for excluded paths' do
|
|
88
|
+
expected_sources = Reek::Source::SourceLocator.
|
|
89
|
+
new(['.'], configuration: configuration).sources
|
|
90
|
+
expect(expected_sources).not_to include(path_excluded_in_configuration)
|
|
91
|
+
|
|
92
|
+
app.execute
|
|
93
|
+
|
|
94
|
+
expect(Reek::CLI::Command::ReportCommand).to have_received(:new).
|
|
95
|
+
with(sources: expected_sources,
|
|
96
|
+
configuration: configuration,
|
|
97
|
+
options: Reek::CLI::Options)
|
|
86
98
|
end
|
|
87
99
|
end
|
|
88
100
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
require_relative '../../../spec_helper'
|
|
2
2
|
require_lib 'reek/cli/command/todo_list_command'
|
|
3
3
|
require_lib 'reek/cli/options'
|
|
4
|
+
require_lib 'reek/configuration/app_configuration'
|
|
4
5
|
|
|
5
6
|
RSpec.describe Reek::CLI::Command::TodoListCommand do
|
|
6
7
|
let(:nil_check) { build :smell_detector, smell_type: :NilCheck }
|
|
@@ -21,7 +22,7 @@ RSpec.describe Reek::CLI::Command::TodoListCommand do
|
|
|
21
22
|
allow(File).to receive(:write).with(described_class::FILE_NAME, String)
|
|
22
23
|
end
|
|
23
24
|
|
|
24
|
-
context 'smells found' do
|
|
25
|
+
context 'when smells are found' do
|
|
25
26
|
let(:source_file) { SMELLY_FILE }
|
|
26
27
|
|
|
27
28
|
it 'shows a proper message' do
|
|
@@ -37,14 +38,15 @@ RSpec.describe Reek::CLI::Command::TodoListCommand do
|
|
|
37
38
|
it 'writes a todo file with exclusions for each smell' do
|
|
38
39
|
Reek::CLI::Silencer.silently { command.execute }
|
|
39
40
|
expected_yaml = {
|
|
40
|
-
|
|
41
|
-
'
|
|
41
|
+
Reek::Configuration::AppConfiguration::DETECTORS_KEY =>
|
|
42
|
+
{ 'UncommunicativeMethodName' => { 'exclude' => ['Smelly#x'] },
|
|
43
|
+
'UncommunicativeVariableName' => { 'exclude' => ['Smelly#x'] } }
|
|
42
44
|
}.to_yaml
|
|
43
45
|
expect(File).to have_received(:write).with(described_class::FILE_NAME, expected_yaml)
|
|
44
46
|
end
|
|
45
47
|
end
|
|
46
48
|
|
|
47
|
-
context 'no smells found' do
|
|
49
|
+
context 'when no smells re found' do
|
|
48
50
|
let(:source_file) { CLEAN_FILE }
|
|
49
51
|
|
|
50
52
|
it 'shows a proper message' do
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_lib 'reek/cli/silencer'
|
|
3
|
+
|
|
4
|
+
RSpec.describe Reek::CLI::Silencer do
|
|
5
|
+
describe '.silently' do
|
|
6
|
+
it 'blocks output from the block on $stdout' do
|
|
7
|
+
expect { described_class.silently { puts 'Hi!' } }.not_to output.to_stdout
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'blocks output from the block on $stderr' do
|
|
11
|
+
expect { described_class.silently { warn 'Hi!' } }.not_to output.to_stderr
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'restores output on $stdout after the block' do
|
|
15
|
+
expect do
|
|
16
|
+
described_class.silently { puts 'Hi!' }
|
|
17
|
+
puts 'there!'
|
|
18
|
+
end.to output("there!\n").to_stdout
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'restores output on $stderr after the block' do
|
|
22
|
+
expect do
|
|
23
|
+
described_class.silently { warn 'Hi!' }
|
|
24
|
+
warn 'there!'
|
|
25
|
+
end.to output("there!\n").to_stderr
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|