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
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_lib 'reek/configuration/rake_task_converter'
|
|
3
|
+
|
|
4
|
+
RSpec.describe Reek::Configuration::RakeTaskConverter do
|
|
5
|
+
describe 'convert' do
|
|
6
|
+
let(:configuration_for_smell_detector) do
|
|
7
|
+
{
|
|
8
|
+
'exclude' => [/Klass#foobar$/, /^Klass#omg$/],
|
|
9
|
+
'reject' => [/^[a-z]$/, /[0-9]$/, /[A-Z]/],
|
|
10
|
+
'accept' => [/^_$/]
|
|
11
|
+
}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
let(:expected_exclude) { ['/Klass#foobar$/', '/^Klass#omg$/'] }
|
|
15
|
+
let(:expected_reject) { ['/^[a-z]$/', '/[0-9]$/', '/[A-Z]/'] }
|
|
16
|
+
let(:expected_accept) { ['/^_$/'] }
|
|
17
|
+
|
|
18
|
+
it 'converts exclude regexes to strings' do
|
|
19
|
+
converted_configuration = described_class.convert configuration_for_smell_detector
|
|
20
|
+
expect(converted_configuration['exclude']).to eq(expected_exclude)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'converts reject regexes to strings' do
|
|
24
|
+
converted_configuration = described_class.convert configuration_for_smell_detector
|
|
25
|
+
expect(converted_configuration['reject']).to eq(expected_reject)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'converts accept regexes to strings' do
|
|
29
|
+
converted_configuration = described_class.convert configuration_for_smell_detector
|
|
30
|
+
expect(converted_configuration['accept']).to eq(expected_accept)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_lib 'reek/configuration/schema_validator'
|
|
3
|
+
require_lib 'reek/errors/config_file_error'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Reek::Configuration::SchemaValidator do
|
|
6
|
+
describe 'validate' do
|
|
7
|
+
subject(:validator) { described_class.new configuration }
|
|
8
|
+
|
|
9
|
+
context 'when configuration is valid' do
|
|
10
|
+
let(:configuration) do
|
|
11
|
+
{
|
|
12
|
+
Reek::Configuration::AppConfiguration::DETECTORS_KEY => {
|
|
13
|
+
'UncommunicativeVariableName' => { 'enabled' => false },
|
|
14
|
+
'UncommunicativeMethodName' => { 'enabled' => false }
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'returns nil' do
|
|
20
|
+
expect(validator.validate).to eq(nil)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
context 'when detector is invalid' do
|
|
25
|
+
let(:configuration) do
|
|
26
|
+
{
|
|
27
|
+
Reek::Configuration::AppConfiguration::DETECTORS_KEY => {
|
|
28
|
+
'DoesNotExist' => { 'enabled' => false }
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'raises an error' do
|
|
34
|
+
message = %r{\[/detectors/DoesNotExist\] key 'DoesNotExist:' is undefined}
|
|
35
|
+
expect { validator.validate }.to raise_error(Reek::Errors::ConfigFileError, message)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
context 'when `enabled` has a non-boolean value' do
|
|
40
|
+
let(:configuration) do
|
|
41
|
+
{
|
|
42
|
+
Reek::Configuration::AppConfiguration::DETECTORS_KEY => {
|
|
43
|
+
'FeatureEnvy' => { 'enabled' => 'foo' }
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it 'raises an error' do
|
|
49
|
+
message = %r{\[/detectors/FeatureEnvy/enabled\] 'foo': not a boolean}
|
|
50
|
+
expect { validator.validate }.to raise_error(Reek::Errors::ConfigFileError, message)
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'when detector has an unknown option' do
|
|
55
|
+
let(:configuration) do
|
|
56
|
+
{
|
|
57
|
+
Reek::Configuration::AppConfiguration::DETECTORS_KEY => {
|
|
58
|
+
'DataClump' => { 'does_not_exist' => 42 }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'raises an error' do
|
|
64
|
+
message = %r{\[/detectors/DataClump/does_not_exist\] key 'does_not_exist:' is undefined}
|
|
65
|
+
expect { validator.validate }.to raise_error(Reek::Errors::ConfigFileError, message)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
context 'when `exclude`, `reject` and `accept`' do
|
|
70
|
+
%w(exclude reject accept).each do |attribute|
|
|
71
|
+
context 'when a scalar' do
|
|
72
|
+
let(:configuration) do
|
|
73
|
+
{
|
|
74
|
+
Reek::Configuration::AppConfiguration::DETECTORS_KEY => {
|
|
75
|
+
'UncommunicativeMethodName' => { attribute => 42 }
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'raises an error' do
|
|
81
|
+
message = %r{\[/detectors/UncommunicativeMethodName/#{attribute}\] '42': not a sequence}
|
|
82
|
+
expect { validator.validate }.to raise_error(Reek::Errors::ConfigFileError, message)
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
context 'when types are mixed' do
|
|
87
|
+
let(:configuration) do
|
|
88
|
+
{
|
|
89
|
+
Reek::Configuration::AppConfiguration::DETECTORS_KEY => {
|
|
90
|
+
'UncommunicativeMethodName' => { attribute => [42, 'foo'] }
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'raises an error' do
|
|
96
|
+
message = %r{\[/detectors/UncommunicativeMethodName/#{attribute}/0\] '42': not a string}
|
|
97
|
+
expect { validator.validate }.to raise_error(Reek::Errors::ConfigFileError, message)
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
context 'when `exclude_paths` is a scalar' do
|
|
104
|
+
let(:configuration) do
|
|
105
|
+
{
|
|
106
|
+
Reek::Configuration::AppConfiguration::EXCLUDE_PATHS_KEY => 42
|
|
107
|
+
}
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it 'raises an error' do
|
|
111
|
+
message = %r{\[/exclude_paths\] '42': not a sequence}
|
|
112
|
+
expect { validator.validate }.to raise_error(Reek::Errors::ConfigFileError, message)
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
context 'when `exclude_paths` mixes types' do
|
|
117
|
+
let(:configuration) do
|
|
118
|
+
{
|
|
119
|
+
Reek::Configuration::AppConfiguration::EXCLUDE_PATHS_KEY => [42, 'foo']
|
|
120
|
+
}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'raises an error' do
|
|
124
|
+
message = %r{\[/exclude_paths/0\] '42': not a string}
|
|
125
|
+
expect { validator.validate }.to raise_error(Reek::Errors::ConfigFileError, message)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
context 'with directory directives' do
|
|
130
|
+
context 'when bad detector' do
|
|
131
|
+
let(:configuration) do
|
|
132
|
+
{
|
|
133
|
+
Reek::Configuration::AppConfiguration::DIRECTORIES_KEY => {
|
|
134
|
+
'web_app/app/helpers' => {
|
|
135
|
+
'Bar' => { 'enabled' => false }
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it 'raises an error' do
|
|
142
|
+
message = %r{\[/directories/web_app/app/helpers/Bar\] key 'Bar:' is undefined}
|
|
143
|
+
expect { validator.validate }.to raise_error(Reek::Errors::ConfigFileError, message)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
context 'when unknown attribute' do
|
|
148
|
+
let(:configuration) do
|
|
149
|
+
{
|
|
150
|
+
Reek::Configuration::AppConfiguration::DIRECTORIES_KEY => {
|
|
151
|
+
'web_app/app/controllers' => {
|
|
152
|
+
'NestedIterators' => { 'foo' => false }
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
it 'raises an error' do
|
|
159
|
+
message = %r{\[/directories/web_app/app/controllers/NestedIterators/foo\] key 'foo:' is undefined}
|
|
160
|
+
expect { validator.validate }.to raise_error(Reek::Errors::ConfigFileError, message)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
end
|
|
165
|
+
end
|
|
@@ -3,7 +3,7 @@ require_lib 'reek/context/method_context'
|
|
|
3
3
|
require_lib 'reek/context/module_context'
|
|
4
4
|
|
|
5
5
|
RSpec.describe Reek::Context::CodeContext do
|
|
6
|
-
|
|
6
|
+
describe '#full_name' do
|
|
7
7
|
let(:ctx) { described_class.new(exp) }
|
|
8
8
|
let(:exp) { instance_double('Reek::AST::SexpExtensions::ModuleNode') }
|
|
9
9
|
let(:exp_name) { 'random_name' }
|
|
@@ -14,9 +14,54 @@ RSpec.describe Reek::Context::CodeContext do
|
|
|
14
14
|
allow(exp).to receive(:full_name).and_return(full_name)
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
+
it 'creates the correct full name' do
|
|
18
|
+
expect(ctx.full_name).to eq(full_name)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
context 'when there is an outer' do
|
|
22
|
+
let(:outer_name) { 'another_random sting' }
|
|
23
|
+
let(:outer) { described_class.new(instance_double('Reek::AST::Node')) }
|
|
24
|
+
|
|
25
|
+
before do
|
|
26
|
+
ctx.register_with_parent outer
|
|
27
|
+
allow(outer).to receive(:full_name).at_least(:once).and_return(outer_name)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
it 'creates the correct full name' do
|
|
31
|
+
expect(ctx.full_name).to eq(full_name)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'passes the outer name to exp#full_name' do
|
|
35
|
+
ctx.full_name
|
|
36
|
+
expect(exp).to have_received(:full_name).with outer_name
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe '#name' do
|
|
42
|
+
let(:ctx) { described_class.new(exp) }
|
|
43
|
+
let(:exp) { instance_double('Reek::AST::SexpExtensions::ModuleNode') }
|
|
44
|
+
let(:exp_name) { 'random_name' }
|
|
45
|
+
|
|
46
|
+
before do
|
|
47
|
+
allow(exp).to receive(:name).and_return(exp_name)
|
|
48
|
+
end
|
|
49
|
+
|
|
17
50
|
it 'gets its short name from the exp' do
|
|
18
51
|
expect(ctx.name).to eq(exp_name)
|
|
19
52
|
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
describe '#matches?' do
|
|
56
|
+
let(:ctx) { described_class.new(exp) }
|
|
57
|
+
let(:exp) { instance_double('Reek::AST::SexpExtensions::ModuleNode') }
|
|
58
|
+
let(:exp_name) { 'random_name' }
|
|
59
|
+
let(:full_name) { "::::::::::::::::::::#{exp_name}" }
|
|
60
|
+
|
|
61
|
+
before do
|
|
62
|
+
allow(exp).to receive(:name).and_return(exp_name)
|
|
63
|
+
allow(exp).to receive(:full_name).and_return(full_name)
|
|
64
|
+
end
|
|
20
65
|
|
|
21
66
|
it 'does not match an empty list' do
|
|
22
67
|
expect(ctx.matches?([])).to eq(false)
|
|
@@ -31,19 +76,30 @@ RSpec.describe Reek::Context::CodeContext do
|
|
|
31
76
|
end
|
|
32
77
|
|
|
33
78
|
it 'recognises its own short name' do
|
|
79
|
+
expect(ctx.matches?([exp_name])).to eq(true)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it 'recognises its own short name in a list' do
|
|
34
83
|
expect(ctx.matches?(['banana', exp_name])).to eq(true)
|
|
35
84
|
end
|
|
36
85
|
|
|
37
86
|
it 'recognises its short name as a regex' do
|
|
38
|
-
expect(ctx.matches?([
|
|
87
|
+
expect(ctx.matches?([/#{exp_name}/])).to eq(true)
|
|
39
88
|
end
|
|
40
89
|
|
|
41
90
|
it 'does not blow up on []-ended Strings' do
|
|
42
91
|
expect(ctx.matches?(['banana[]', exp_name])).to eq(true)
|
|
43
92
|
end
|
|
44
93
|
|
|
94
|
+
it 'recognises its own full name' do
|
|
95
|
+
expect(ctx.matches?(['banana', full_name])).to eq(true)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it 'recognises its full name as a regex' do
|
|
99
|
+
expect(ctx.matches?([/banana/, /#{full_name}/])).to eq(true)
|
|
100
|
+
end
|
|
101
|
+
|
|
45
102
|
context 'when there is an outer' do
|
|
46
|
-
let(:ctx) { described_class.new(exp) }
|
|
47
103
|
let(:outer_name) { 'another_random sting' }
|
|
48
104
|
let(:outer) { described_class.new(instance_double('Reek::AST::Node')) }
|
|
49
105
|
|
|
@@ -52,10 +108,6 @@ RSpec.describe Reek::Context::CodeContext do
|
|
|
52
108
|
allow(outer).to receive(:full_name).at_least(:once).and_return(outer_name)
|
|
53
109
|
end
|
|
54
110
|
|
|
55
|
-
it 'creates the correct full name' do
|
|
56
|
-
expect(ctx.full_name).to eq(full_name)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
111
|
it 'recognises its own full name' do
|
|
60
112
|
expect(ctx.matches?(['banana', full_name])).to eq(true)
|
|
61
113
|
end
|
|
@@ -66,98 +118,10 @@ RSpec.describe Reek::Context::CodeContext do
|
|
|
66
118
|
end
|
|
67
119
|
end
|
|
68
120
|
|
|
69
|
-
context 'enumerating syntax elements' do
|
|
70
|
-
context 'in an empty module' do
|
|
71
|
-
let(:ctx) do
|
|
72
|
-
src = 'module Emptiness; end'
|
|
73
|
-
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
|
74
|
-
described_class.new(ast)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it 'yields no calls' do
|
|
78
|
-
ctx.each_node(:send, []) { |exp| raise "#{exp} yielded by empty module!" }
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
it 'yields one module' do
|
|
82
|
-
mods = 0
|
|
83
|
-
ctx.each_node(:module, []) { |_exp| mods += 1 }
|
|
84
|
-
expect(mods).to eq(1)
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
it "yields the module's full AST" do
|
|
88
|
-
ctx.each_node(:module, []) do |exp|
|
|
89
|
-
expect(exp).to eq(sexp(:module, sexp(:const, nil, :Emptiness), nil))
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it 'returns an empty array of ifs when no block is passed' do
|
|
94
|
-
expect(ctx.each_node(:if, [])).to be_empty
|
|
95
|
-
end
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
context 'with a nested element' do
|
|
99
|
-
let(:ctx) do
|
|
100
|
-
src = "module Loneliness; def calloo; puts('hello') end; end"
|
|
101
|
-
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
|
102
|
-
described_class.new(ast)
|
|
103
|
-
end
|
|
104
|
-
|
|
105
|
-
it 'yields no ifs' do
|
|
106
|
-
ctx.each_node(:if, []) { |exp| raise "#{exp} yielded by empty module!" }
|
|
107
|
-
end
|
|
108
|
-
it 'yields one module' do
|
|
109
|
-
expect(ctx.each_node(:module, []).length).to eq(1)
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
it "yields the module's full AST" do
|
|
113
|
-
ctx.each_node(:module, []) do |exp|
|
|
114
|
-
expect(exp).to eq sexp(:module,
|
|
115
|
-
sexp(:const, nil, :Loneliness),
|
|
116
|
-
sexp(:def, :calloo,
|
|
117
|
-
sexp(:args),
|
|
118
|
-
sexp(:send, nil, :puts, sexp(:str, 'hello'))))
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
it 'yields one method' do
|
|
123
|
-
expect(ctx.each_node(:def, []).length).to eq(1)
|
|
124
|
-
end
|
|
125
|
-
|
|
126
|
-
it "yields the method's full AST" do
|
|
127
|
-
ctx.each_node(:def, []) { |exp| expect(exp.children.first).to eq(:calloo) }
|
|
128
|
-
end
|
|
129
|
-
|
|
130
|
-
it 'ignores the call inside the method if the traversal is pruned' do
|
|
131
|
-
expect(ctx.each_node(:send, [:def])).to be_empty
|
|
132
|
-
end
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
it 'finds 3 ifs in a class' do
|
|
136
|
-
src = <<-EOS
|
|
137
|
-
class Scrunch
|
|
138
|
-
def first
|
|
139
|
-
return @field == :sym ? 0 : 3;
|
|
140
|
-
end
|
|
141
|
-
def second
|
|
142
|
-
if @field == :sym
|
|
143
|
-
@other += " quarts"
|
|
144
|
-
end
|
|
145
|
-
end
|
|
146
|
-
def third
|
|
147
|
-
raise 'flu!' unless @field == :sym
|
|
148
|
-
end
|
|
149
|
-
end
|
|
150
|
-
EOS
|
|
151
|
-
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
|
152
|
-
ctx = described_class.new(ast)
|
|
153
|
-
expect(ctx.each_node(:if, []).length).to eq(3)
|
|
154
|
-
end
|
|
155
|
-
end
|
|
156
|
-
|
|
157
121
|
describe '#config_for' do
|
|
158
122
|
let(:src) do
|
|
159
123
|
<<-EOS
|
|
160
|
-
# :reek:DuplicateMethodCall
|
|
124
|
+
# :reek:DuplicateMethodCall { allow_calls: [ puts ] }')
|
|
161
125
|
def repeated_greeting
|
|
162
126
|
puts 'Hello!'
|
|
163
127
|
puts 'Hello!'
|
|
@@ -42,7 +42,7 @@ RSpec.describe Reek::Context::GhostContext do
|
|
|
42
42
|
expect(ghost.children).to include child
|
|
43
43
|
end
|
|
44
44
|
|
|
45
|
-
context '
|
|
45
|
+
context 'when the grandparent is also a ghost' do
|
|
46
46
|
let(:child_ghost) { described_class.new(nil) }
|
|
47
47
|
|
|
48
48
|
before do
|
|
@@ -2,7 +2,7 @@ require_relative '../../spec_helper'
|
|
|
2
2
|
require_lib 'reek/context/root_context'
|
|
3
3
|
|
|
4
4
|
RSpec.describe Reek::Context::RootContext do
|
|
5
|
-
|
|
5
|
+
describe '#full_name' do
|
|
6
6
|
it 'reports full context' do
|
|
7
7
|
ast = Reek::Source::SourceCode.from('foo = 1').syntax_tree
|
|
8
8
|
root = described_class.new(ast)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require_relative '../spec_helper'
|
|
2
|
+
|
|
3
|
+
RSpec.describe Reek::DocumentationLink do
|
|
4
|
+
describe '.build' do
|
|
5
|
+
it 'returns the correct link for a smell type' do
|
|
6
|
+
expect(described_class.build('FeatureEnvy')).
|
|
7
|
+
to eq "https://github.com/troessner/reek/blob/v#{Reek::Version::STRING}/docs/Feature-Envy.md"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
it 'returns the correct link for general documentation' do
|
|
11
|
+
expect(described_class.build('Rake Task')).
|
|
12
|
+
to eq "https://github.com/troessner/reek/blob/v#{Reek::Version::STRING}/docs/Rake-Task.md"
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it 'returns the correct link for subjects with abbreviations' do
|
|
16
|
+
expect(described_class.build('YAML Report')).
|
|
17
|
+
to eq "https://github.com/troessner/reek/blob/v#{Reek::Version::STRING}/docs/YAML-Report.md"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
|
|
3
|
+
require_lib 'reek/errors/base_error'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Reek::Errors::BaseError do
|
|
6
|
+
let(:error) { described_class.new }
|
|
7
|
+
|
|
8
|
+
describe '#long_message' do
|
|
9
|
+
it 'returns the message' do
|
|
10
|
+
expect(error.long_message).to eq error.message
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
data/spec/reek/examiner_spec.rb
CHANGED
|
@@ -46,7 +46,7 @@ RSpec.describe Reek::Examiner do
|
|
|
46
46
|
filter_by_smells: [],
|
|
47
47
|
configuration: configuration)
|
|
48
48
|
end
|
|
49
|
-
let(:path) {
|
|
49
|
+
let(:path) { CONFIGURATION_DIR.join('partial_mask.reek') }
|
|
50
50
|
let(:expected_first_smell) { 'UncommunicativeVariableName' }
|
|
51
51
|
|
|
52
52
|
it_behaves_like 'one smell found'
|
|
@@ -58,27 +58,12 @@ RSpec.describe Reek::Examiner do
|
|
|
58
58
|
it_behaves_like 'no smells found'
|
|
59
59
|
end
|
|
60
60
|
|
|
61
|
-
describe '
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
let(:examiner) do
|
|
65
|
-
described_class.new(source)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
it 'has been run on the given source' do
|
|
69
|
-
expect(examiner.origin).to eq('string')
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
it 'has the right smells' do
|
|
73
|
-
smells = examiner.smells
|
|
74
|
-
expect(smells[0].message).to eq('has no descriptive comment')
|
|
75
|
-
expect(smells[1].message).to eq("has the name 'f'")
|
|
76
|
-
expect(smells[2].message).to eq("has the name 'C'")
|
|
77
|
-
end
|
|
61
|
+
describe '#origin' do
|
|
62
|
+
let(:source) { 'class C; def f; end; end' }
|
|
63
|
+
let(:examiner) { described_class.new(source) }
|
|
78
64
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
end
|
|
65
|
+
it 'returns "string" for a string source' do
|
|
66
|
+
expect(examiner.origin).to eq('string')
|
|
82
67
|
end
|
|
83
68
|
end
|
|
84
69
|
|
|
@@ -92,7 +77,20 @@ RSpec.describe Reek::Examiner do
|
|
|
92
77
|
expect(smell.message).to eq("calls 'bar.call_me()' 2 times")
|
|
93
78
|
end
|
|
94
79
|
|
|
95
|
-
context 'source
|
|
80
|
+
context 'with a source with three smells' do
|
|
81
|
+
let(:source) { 'class C; def f; end; end' }
|
|
82
|
+
let(:examiner) { described_class.new(source) }
|
|
83
|
+
|
|
84
|
+
it 'has the right smells' do
|
|
85
|
+
smells = examiner.smells
|
|
86
|
+
expect(smells.map(&:message)).
|
|
87
|
+
to eq ['has no descriptive comment',
|
|
88
|
+
"has the name 'f'",
|
|
89
|
+
"has the name 'C'"]
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context 'when source only contains comments' do
|
|
96
94
|
let(:source) do
|
|
97
95
|
<<-EOS
|
|
98
96
|
# Just a comment
|
|
@@ -129,21 +127,38 @@ RSpec.describe Reek::Examiner do
|
|
|
129
127
|
|
|
130
128
|
it 'explains the origin of the error' do
|
|
131
129
|
origin = 'string'
|
|
132
|
-
expect { examiner.smells }.
|
|
130
|
+
expect { examiner.smells }.
|
|
131
|
+
to raise_error.with_message("Source #{origin} cannot be processed by Reek.")
|
|
133
132
|
end
|
|
134
133
|
|
|
135
134
|
it 'explains what to do' do
|
|
136
|
-
explanation = '
|
|
137
|
-
expect { examiner.smells }.
|
|
135
|
+
explanation = 'It would be great if you could report this back to the Reek team'
|
|
136
|
+
expect { examiner.smells }.
|
|
137
|
+
to raise_error { |it| expect(it.long_message).to match(/#{explanation}/) }
|
|
138
138
|
end
|
|
139
139
|
|
|
140
140
|
it 'contains the original error message' do
|
|
141
141
|
original = 'Looks like bad source'
|
|
142
|
-
expect { examiner.smells }.
|
|
142
|
+
expect { examiner.smells }.
|
|
143
|
+
to raise_error { |it| expect(it.long_message).to match(/#{original}/) }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
it 'shows the original exception class' do
|
|
147
|
+
expect { examiner.smells }.
|
|
148
|
+
to raise_error { |it| expect(it.long_message).to match(/ArgumentError/) }
|
|
143
149
|
end
|
|
144
150
|
end
|
|
145
151
|
end
|
|
146
152
|
|
|
153
|
+
describe '#smells_count' do
|
|
154
|
+
let(:source) { 'class C; def f; end; end' }
|
|
155
|
+
let(:examiner) { described_class.new(source) }
|
|
156
|
+
|
|
157
|
+
it 'has the right smell count' do
|
|
158
|
+
expect(examiner.smells_count).to eq(3)
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
147
162
|
context 'when the source causes the source buffer to crash' do
|
|
148
163
|
let(:source) { 'I make the buffer crash' }
|
|
149
164
|
|
|
@@ -153,7 +168,7 @@ RSpec.describe Reek::Examiner do
|
|
|
153
168
|
allow(Parser::Source::Buffer).to receive(:new).and_return(buffer)
|
|
154
169
|
end
|
|
155
170
|
|
|
156
|
-
context '
|
|
171
|
+
context 'when the error handler does not handle the error' do
|
|
157
172
|
let(:examiner) { described_class.new(source) }
|
|
158
173
|
|
|
159
174
|
it 'does not raise an error during initialization' do
|
|
@@ -165,7 +180,7 @@ RSpec.describe Reek::Examiner do
|
|
|
165
180
|
end
|
|
166
181
|
end
|
|
167
182
|
|
|
168
|
-
context '
|
|
183
|
+
context 'when the error handler handles the error' do
|
|
169
184
|
let(:handler) { instance_double(Reek::LoggingErrorHandler, handle: true) }
|
|
170
185
|
let(:examiner) { described_class.new(source, error_handler: handler) }
|
|
171
186
|
|
|
@@ -180,10 +195,65 @@ RSpec.describe Reek::Examiner do
|
|
|
180
195
|
end
|
|
181
196
|
end
|
|
182
197
|
|
|
198
|
+
context 'with a source that triggers a syntax error' do
|
|
199
|
+
let(:examiner) { described_class.new(source) }
|
|
200
|
+
let(:source) do
|
|
201
|
+
<<-SRC.strip_heredoc
|
|
202
|
+
1 2 3
|
|
203
|
+
SRC
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it 'does not raise an error during initialization' do
|
|
207
|
+
expect { examiner }.not_to raise_error
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it 'raises an encoding error when asked for smells' do
|
|
211
|
+
expect { examiner.smells }.to raise_error Reek::Errors::SyntaxError
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it 'explains the origin of the error' do
|
|
215
|
+
message = "Source 'string' cannot be processed by Reek due to a syntax error in the source file."
|
|
216
|
+
expect { examiner.smells }.to raise_error.with_message(/#{message}/)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it 'shows the original exception class' do
|
|
220
|
+
expect { examiner.smells }.
|
|
221
|
+
to raise_error { |it| expect(it.long_message).to match(/Parser::SyntaxError/) }
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
context 'with a source that triggers an encoding error' do
|
|
226
|
+
let(:examiner) { described_class.new(source) }
|
|
227
|
+
let(:source) do
|
|
228
|
+
<<-SRC.strip_heredoc
|
|
229
|
+
# encoding: US-ASCII
|
|
230
|
+
puts 'こんにちは世界'
|
|
231
|
+
SRC
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
it 'does not raise an error during initialization' do
|
|
235
|
+
expect { examiner }.not_to raise_error
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
it 'raises an encoding error when asked for smells' do
|
|
239
|
+
expect { examiner.smells }.to raise_error Reek::Errors::EncodingError
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it 'explains the origin of the error' do
|
|
243
|
+
message = "Source 'string' cannot be processed by Reek due to an encoding error in the source file."
|
|
244
|
+
expect { examiner.smells }.to raise_error.with_message(/#{message}/)
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
it 'shows the original exception class' do
|
|
248
|
+
expect { examiner.smells }.
|
|
249
|
+
to raise_error { |it| expect(it.long_message).to match(/InvalidByteSequenceError/) }
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
183
253
|
describe 'bad comment config' do
|
|
184
254
|
let(:examiner) { described_class.new(source) }
|
|
185
255
|
|
|
186
|
-
context 'unknown smell detector' do
|
|
256
|
+
context 'with an unknown smell detector' do
|
|
187
257
|
let(:source) do
|
|
188
258
|
<<-EOS
|
|
189
259
|
# :reek:DoesNotExist
|
|
@@ -209,7 +279,7 @@ RSpec.describe Reek::Examiner do
|
|
|
209
279
|
end
|
|
210
280
|
end
|
|
211
281
|
|
|
212
|
-
context 'garbage in detector config' do
|
|
282
|
+
context 'with garbage in detector config' do
|
|
213
283
|
let(:source) do
|
|
214
284
|
<<-EOS
|
|
215
285
|
# :reek:UncommunicativeMethodName { thats: a: bad: config }
|