reek 4.8.2 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{samples/configuration/more_than_one_configuration_file/regular.reek → .reek.yml} +0 -0
- data/.rubocop.yml +17 -3
- data/.simplecov +1 -0
- data/.travis.yml +0 -5
- data/.yardopts +1 -1
- data/CHANGELOG.md +28 -0
- data/Gemfile +1 -1
- data/README.md +113 -98
- 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/{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 +43 -4
- data/docs/Uncommunicative-Module-Name.md +48 -6
- data/docs/Uncommunicative-Parameter-Name.md +42 -4
- data/docs/Uncommunicative-Variable-Name.md +73 -2
- data/docs/Unused-Private-Method.md +1 -1
- data/docs/defaults.reek.yml +129 -0
- data/docs/yard_plugin.rb +1 -0
- data/features/command_line_interface/options.feature +46 -4
- data/features/command_line_interface/stdin.feature +27 -5
- data/features/configuration_files/accept_setting.feature +39 -22
- data/features/configuration_files/directory_specific_directives.feature +58 -53
- data/features/configuration_files/exclude_directives.feature +8 -7
- data/features/configuration_files/masking_smells.feature +35 -6
- data/features/configuration_files/mix_accept_reject_setting.feature +24 -21
- data/features/configuration_files/reject_setting.feature +45 -34
- data/features/configuration_files/schema_validation.feature +59 -0
- data/features/configuration_files/unused_private_method.feature +14 -12
- data/features/configuration_loading.feature +50 -7
- data/features/rake_task/rake_task.feature +5 -5
- data/features/reports/json.feature +4 -1
- data/features/reports/reports.feature +12 -12
- data/features/reports/yaml.feature +3 -0
- data/features/rspec_matcher.feature +9 -1
- 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 +16 -13
- data/lib/reek/ast/node.rb +3 -6
- data/lib/reek/ast/object_refs.rb +1 -1
- data/lib/reek/ast/sexp_extensions/if.rb +1 -1
- data/lib/reek/ast/sexp_extensions/methods.rb +1 -1
- 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 +4 -2
- data/lib/reek/cli/options.rb +27 -13
- 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 +4 -4
- data/lib/reek/context/method_context.rb +2 -2
- data/lib/reek/context/module_context.rb +1 -1
- data/lib/reek/context_builder.rb +9 -9
- data/lib/reek/detector_repository.rb +6 -0
- data/lib/reek/documentation_link.rb +2 -2
- data/lib/reek/errors/bad_detector_configuration_key_in_comment_error.rb +1 -1
- data/lib/reek/errors/bad_detector_in_comment_error.rb +1 -1
- data/lib/reek/errors/config_file_error.rb +11 -0
- data/lib/reek/errors/encoding_error.rb +2 -2
- data/lib/reek/errors/garbage_detector_configuration_in_comment_error.rb +1 -1
- data/lib/reek/errors/incomprehensible_source_error.rb +2 -2
- data/lib/reek/errors/syntax_error.rb +41 -0
- data/lib/reek/examiner.rb +9 -19
- data/lib/reek/rake/task.rb +3 -3
- data/lib/reek/report.rb +15 -10
- data/lib/reek/report/base_report.rb +8 -12
- data/lib/reek/report/code_climate/code_climate_configuration.yml +5 -9
- 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/smell_configuration.rb +2 -2
- data/lib/reek/smell_detectors.rb +1 -2
- data/lib/reek/smell_detectors/attribute.rb +0 -1
- data/lib/reek/smell_detectors/base_detector.rb +8 -11
- data/lib/reek/smell_detectors/boolean_parameter.rb +0 -1
- data/lib/reek/smell_detectors/class_variable.rb +0 -1
- 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 +5 -6
- data/lib/reek/smell_detectors/feature_envy.rb +0 -1
- data/lib/reek/smell_detectors/instance_variable_assumption.rb +0 -1
- 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 +2 -2
- data/lib/reek/smell_detectors/{prima_donna_method.rb → missing_safe_method.rb} +6 -7
- data/lib/reek/smell_detectors/module_initialize.rb +0 -1
- data/lib/reek/smell_detectors/nested_iterators.rb +4 -5
- 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 +1 -2
- 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 +4 -5
- 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 +1 -2
- data/lib/reek/smell_warning.rb +10 -8
- data/lib/reek/source/source_code.rb +40 -55
- data/lib/reek/source/source_locator.rb +7 -7
- data/lib/reek/spec.rb +6 -6
- 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/tree_dresser.rb +5 -5
- data/lib/reek/version.rb +1 -1
- data/reek.gemspec +3 -3
- data/samples/checkstyle.xml +1 -1
- data/samples/{clean.rb → clean_source/clean.rb} +0 -0
- 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/{exceptions.reek → configuration/home/home.reek.yml} +0 -0
- data/samples/configuration/partial_mask.reek +3 -2
- data/samples/configuration/regular_configuration/.reek.yml +4 -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/paths.rb +5 -4
- 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/.hidden/hidden.rb +1 -0
- data/samples/source_with_hidden_directories/not_hidden.rb +1 -0
- data/samples/{source_with_hidden_directories/uncommunicative_parameter_name.rb → source_with_non_ruby_files/ruby.rb} +0 -0
- data/spec/reek/ast/node_spec.rb +5 -5
- data/spec/reek/cli/application_spec.rb +18 -4
- data/spec/reek/cli/command/todo_list_command_spec.rb +4 -2
- data/spec/reek/cli/silencer_spec.rb +28 -0
- data/spec/reek/code_comment_spec.rb +0 -7
- data/spec/reek/configuration/app_configuration_spec.rb +44 -31
- 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 +3 -4
- data/spec/reek/configuration/excluded_paths_spec.rb +5 -5
- 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 +1 -1
- data/spec/reek/examiner_spec.rb +28 -1
- 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 +1 -1
- data/spec/reek/report/yaml_report_spec.rb +9 -38
- data/spec/reek/report_spec.rb +3 -3
- data/spec/reek/smell_detectors/feature_envy_spec.rb +2 -2
- data/spec/reek/smell_detectors/{prima_donna_method_spec.rb → missing_safe_method_spec.rb} +9 -9
- 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 +6 -6
- data/spec/reek/smell_detectors/unused_private_method_spec.rb +1 -1
- data/spec/reek/smell_warning_spec.rb +4 -0
- data/spec/reek/source/source_code_spec.rb +16 -22
- data/spec/reek/source/source_locator_spec.rb +11 -11
- data/spec/reek/spec/should_reek_of_spec.rb +0 -4
- data/spec/reek/spec/should_reek_only_of_spec.rb +2 -2
- data/spec/reek/spec/should_reek_spec.rb +1 -1
- data/spec/reek/tree_dresser_spec.rb +2 -6
- data/spec/spec_helper.rb +3 -5
- data/tasks/configuration.rake +8 -5
- metadata +56 -35
- data/defaults.reek +0 -131
- data/features/configuration_files/warn_about_multiple_configuration_files.feature +0 -44
- data/lib/reek/report/formatter.rb +0 -33
- 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 -23
- 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
@@ -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/"
|
File without changes
|
File without changes
|
File without changes
|
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
|
+
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
|
File without changes
|
data/spec/reek/ast/node_spec.rb
CHANGED
@@ -164,7 +164,7 @@ RSpec.describe Reek::AST::Node do
|
|
164
164
|
|
165
165
|
describe '#line' do
|
166
166
|
context 'with source from a file' do
|
167
|
-
let(:file) {
|
167
|
+
let(:file) { SMELLY_FILE }
|
168
168
|
let(:ast) { Reek::Source::SourceCode.from(file).syntax_tree }
|
169
169
|
|
170
170
|
it 'returns the right line number' do
|
@@ -173,7 +173,7 @@ RSpec.describe Reek::AST::Node do
|
|
173
173
|
end
|
174
174
|
|
175
175
|
context 'with source from a string' do
|
176
|
-
let(:source) { File.read(
|
176
|
+
let(:source) { File.read(SMELLY_FILE) }
|
177
177
|
let(:ast) { Reek::Source::SourceCode.from(source).syntax_tree }
|
178
178
|
|
179
179
|
it 'returns the right line number' do
|
@@ -184,16 +184,16 @@ RSpec.describe Reek::AST::Node do
|
|
184
184
|
|
185
185
|
describe '#source' do
|
186
186
|
context 'with source from a file' do
|
187
|
-
let(:file) {
|
187
|
+
let(:file) { SMELLY_FILE }
|
188
188
|
let(:ast) { Reek::Source::SourceCode.from(file).syntax_tree }
|
189
189
|
|
190
190
|
it 'returns the file name' do
|
191
|
-
expect(ast.source).to eq(
|
191
|
+
expect(ast.source).to eq(SMELLY_FILE.to_s)
|
192
192
|
end
|
193
193
|
end
|
194
194
|
|
195
195
|
context 'with source from a string' do
|
196
|
-
let(:source) { File.read
|
196
|
+
let(:source) { File.read SMELLY_FILE }
|
197
197
|
let(:ast) { Reek::Source::SourceCode.from(source).syntax_tree }
|
198
198
|
|
199
199
|
it 'returns "string"' do
|
@@ -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
|
|
@@ -37,13 +37,27 @@ RSpec.describe Reek::CLI::Application do
|
|
37
37
|
allow_any_instance_of(IO).to receive(:tty?).and_return(false)
|
38
38
|
end
|
39
39
|
|
40
|
-
it 'uses source
|
40
|
+
it 'uses source from pipe' do
|
41
|
+
expected_sources = a_collection_containing_exactly(have_attributes(origin: 'STDIN'))
|
41
42
|
app.execute
|
42
43
|
expect(Reek::CLI::Command::ReportCommand).to have_received(:new).
|
43
|
-
with(sources:
|
44
|
+
with(sources: expected_sources,
|
44
45
|
configuration: Reek::Configuration::AppConfiguration,
|
45
46
|
options: Reek::CLI::Options)
|
46
47
|
end
|
48
|
+
|
49
|
+
context 'when a stdin filename is provided' do
|
50
|
+
let(:app) { described_class.new ['--stdin-filename', 'foo.rb'] }
|
51
|
+
|
52
|
+
it 'assumes that filename' do
|
53
|
+
expected_sources = a_collection_containing_exactly(have_attributes(origin: 'foo.rb'))
|
54
|
+
app.execute
|
55
|
+
expect(Reek::CLI::Command::ReportCommand).to have_received(:new).
|
56
|
+
with(sources: expected_sources,
|
57
|
+
configuration: Reek::Configuration::AppConfiguration,
|
58
|
+
options: Reek::CLI::Options)
|
59
|
+
end
|
60
|
+
end
|
47
61
|
end
|
48
62
|
|
49
63
|
context 'when no source files given and no input was piped' do
|
@@ -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 }
|
@@ -37,8 +38,9 @@ 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
|
@@ -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
|
@@ -161,13 +161,6 @@ RSpec.describe Reek::CodeComment::CodeCommentValidator do
|
|
161
161
|
build(:code_comment, comment: comment)
|
162
162
|
end.not_to raise_error
|
163
163
|
end
|
164
|
-
|
165
|
-
it 'does not raise on regexps' do
|
166
|
-
expect do
|
167
|
-
comment = '# :reek:UncommunicativeMethodName { exclude: !ruby/regexp /alfa/ }'
|
168
|
-
build(:code_comment, comment: comment)
|
169
|
-
end.not_to raise_error
|
170
|
-
end
|
171
164
|
end
|
172
165
|
|
173
166
|
context 'when unknown custom options are specified' do
|
@@ -8,8 +8,8 @@ require_lib 'reek/configuration/excluded_paths'
|
|
8
8
|
RSpec.describe Reek::Configuration::AppConfiguration do
|
9
9
|
describe 'factory methods' do
|
10
10
|
let(:expected_excluded_paths) do
|
11
|
-
[
|
12
|
-
|
11
|
+
[SAMPLES_DIR.join('two_smelly_files'),
|
12
|
+
SAMPLES_DIR.join('source_with_non_ruby_files')]
|
13
13
|
end
|
14
14
|
|
15
15
|
let(:expected_default_directive) do
|
@@ -17,32 +17,35 @@ RSpec.describe Reek::Configuration::AppConfiguration do
|
|
17
17
|
end
|
18
18
|
|
19
19
|
let(:expected_directory_directives) do
|
20
|
-
{
|
20
|
+
{ SAMPLES_DIR.join('three_clean_files') =>
|
21
21
|
{ Reek::SmellDetectors::UtilityFunction => { 'enabled' => false } } }
|
22
22
|
end
|
23
23
|
|
24
24
|
let(:default_directive_value) do
|
25
|
-
{
|
25
|
+
{ described_class::DETECTORS_KEY =>
|
26
|
+
{ 'IrresponsibleModule' => { 'enabled' => false } } }
|
26
27
|
end
|
27
28
|
|
28
29
|
let(:directory_directives_value) do
|
29
|
-
{
|
30
|
-
{ '
|
30
|
+
{ described_class::DIRECTORIES_KEY =>
|
31
|
+
{ 'samples/three_clean_files' =>
|
32
|
+
{ 'UtilityFunction' => { 'enabled' => false } } } }
|
31
33
|
end
|
32
34
|
|
33
35
|
let(:exclude_paths_value) do
|
34
|
-
|
35
|
-
|
36
|
+
{ described_class::EXCLUDE_PATHS_KEY =>
|
37
|
+
['samples/two_smelly_files',
|
38
|
+
'samples/source_with_non_ruby_files'] }
|
36
39
|
end
|
37
40
|
|
38
41
|
let(:combined_value) do
|
39
42
|
directory_directives_value.
|
40
43
|
merge(default_directive_value).
|
41
|
-
merge(
|
44
|
+
merge(exclude_paths_value)
|
42
45
|
end
|
43
46
|
|
44
47
|
describe '#from_path' do
|
45
|
-
let(:full_configuration_path) {
|
48
|
+
let(:full_configuration_path) { CONFIGURATION_DIR.join('full_configuration.reek') }
|
46
49
|
|
47
50
|
it 'properly loads configuration and processes it' do
|
48
51
|
config = described_class.from_path full_configuration_path
|
@@ -77,34 +80,38 @@ RSpec.describe Reek::Configuration::AppConfiguration do
|
|
77
80
|
describe '#directive_for' do
|
78
81
|
context 'with multiple directory directives and no default directive present' do
|
79
82
|
let(:source_via) { 'samples/three_clean_files/dummy.rb' }
|
80
|
-
let(:baz_config) { {
|
81
|
-
let(:bang_config) { {
|
83
|
+
let(:baz_config) { { IrresponsibleModule: { enabled: false } } }
|
84
|
+
let(:bang_config) { { Attribute: { enabled: true } } }
|
85
|
+
let(:expected_result) { { Reek::SmellDetectors::Attribute => { enabled: true } } }
|
82
86
|
|
83
87
|
let(:directory_directives) do
|
84
|
-
{
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
+
{ described_class::DIRECTORIES_KEY =>
|
89
|
+
{
|
90
|
+
'samples/two_smelly_files' => baz_config,
|
91
|
+
'samples/three_clean_files' => bang_config
|
92
|
+
} }
|
88
93
|
end
|
89
94
|
|
90
95
|
it 'returns the corresponding directive' do
|
91
96
|
configuration = described_class.from_hash directory_directives
|
92
|
-
expect(configuration.directive_for(source_via)).to eq
|
97
|
+
expect(configuration.directive_for(source_via)).to eq expected_result
|
93
98
|
end
|
94
99
|
end
|
95
100
|
|
96
101
|
context 'with directory directive and default directive present' do
|
97
102
|
let(:directory) { 'spec/samples/two_smelly_files/' }
|
98
|
-
let(:
|
99
|
-
|
100
|
-
let(:
|
103
|
+
let(:source_via) { "#{directory}/dummy.rb" }
|
104
|
+
|
105
|
+
let(:configuration_as_hash) do
|
101
106
|
{
|
102
|
-
|
103
|
-
|
107
|
+
described_class::DIRECTORIES_KEY =>
|
108
|
+
{ directory => { TooManyStatements: { max_statements: 8 } } },
|
109
|
+
described_class::DETECTORS_KEY => {
|
110
|
+
IrresponsibleModule: { enabled: false },
|
111
|
+
TooManyStatements: { max_statements: 15 }
|
112
|
+
}
|
104
113
|
}
|
105
114
|
end
|
106
|
-
let(:source_via) { "#{directory}/dummy.rb" }
|
107
|
-
let(:configuration_as_hash) { directory_directives.merge(default_directive) }
|
108
115
|
|
109
116
|
it 'returns the directory directive with the default directive reverse-merged' do
|
110
117
|
configuration = described_class.from_hash configuration_as_hash
|
@@ -116,18 +123,24 @@ RSpec.describe Reek::Configuration::AppConfiguration do
|
|
116
123
|
end
|
117
124
|
end
|
118
125
|
|
119
|
-
context 'with
|
126
|
+
context 'with a path not covered by a directory directive but a default directive present' do
|
120
127
|
let(:source_via) { 'spec/samples/three_clean_files/dummy.rb' }
|
121
|
-
|
122
|
-
let(:
|
123
|
-
|
124
|
-
|
128
|
+
|
129
|
+
let(:configuration_as_hash) do
|
130
|
+
{
|
131
|
+
described_class::DETECTORS_KEY => {
|
132
|
+
IrresponsibleModule: { enabled: false }
|
133
|
+
},
|
134
|
+
described_class::DIRECTORIES_KEY =>
|
135
|
+
{ 'spec/samples/two_smelly_files' => { Attribute: { enabled: false } } }
|
136
|
+
}
|
125
137
|
end
|
126
|
-
|
138
|
+
|
139
|
+
let(:expected_result) { { Reek::SmellDetectors::IrresponsibleModule => { enabled: false } } }
|
127
140
|
|
128
141
|
it 'returns the default directive' do
|
129
142
|
configuration = described_class.from_hash configuration_as_hash
|
130
|
-
expect(configuration.directive_for(source_via)).to eq
|
143
|
+
expect(configuration.directive_for(source_via)).to eq expected_result
|
131
144
|
end
|
132
145
|
end
|
133
146
|
end
|
@@ -2,9 +2,13 @@ require 'fileutils'
|
|
2
2
|
require 'pathname'
|
3
3
|
require 'tmpdir'
|
4
4
|
require_relative '../../spec_helper'
|
5
|
+
require_lib 'reek/configuration/app_configuration'
|
5
6
|
|
6
7
|
RSpec.describe Reek::Configuration::ConfigurationFileFinder do
|
7
8
|
describe '.find' do
|
9
|
+
let(:regular_configuration_dir) { CONFIGURATION_DIR.join('regular_configuration') }
|
10
|
+
let(:regular_configuration_file) { regular_configuration_dir.join('.reek.yml') }
|
11
|
+
|
8
12
|
it 'returns any explicitely passed path' do
|
9
13
|
path = Pathname.new 'foo/bar'
|
10
14
|
found = described_class.find(path: path)
|
@@ -13,42 +17,44 @@ RSpec.describe Reek::Configuration::ConfigurationFileFinder do
|
|
13
17
|
|
14
18
|
it 'prefers an explicitely passed path over a file in current dir' do
|
15
19
|
path = Pathname.new 'foo/bar'
|
16
|
-
found = described_class.find(path: path, current:
|
20
|
+
found = described_class.find(path: path, current: regular_configuration_dir)
|
17
21
|
expect(found).to eq(path)
|
18
22
|
end
|
19
23
|
|
20
24
|
it 'returns the file in current dir if path is not set' do
|
21
|
-
found = described_class.find(current:
|
22
|
-
expect(found).to eq(
|
25
|
+
found = described_class.find(current: regular_configuration_dir)
|
26
|
+
expect(found).to eq(regular_configuration_file)
|
23
27
|
end
|
24
28
|
|
25
29
|
it 'returns the file in a parent dir if none in current dir' do
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
30
|
+
empty_sub_directory = CONFIGURATION_DIR.join('regular_configuration').join('empty_sub_directory')
|
31
|
+
found = described_class.find(current: empty_sub_directory)
|
32
|
+
expect(found).to eq(regular_configuration_file)
|
30
33
|
end
|
31
34
|
|
32
|
-
it '
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
it 'skips files ending in .reek.yml in current dir' do
|
36
|
+
Dir.mktmpdir(nil, regular_configuration_dir) do |tempdir|
|
37
|
+
current = Pathname.new(tempdir)
|
38
|
+
bad_config = current.join('ignoreme.reek.yml')
|
39
|
+
FileUtils.touch bad_config
|
40
|
+
found = described_class.find(current: Pathname.new(tempdir))
|
41
|
+
expect(found).to eq(regular_configuration_file)
|
42
|
+
end
|
36
43
|
end
|
37
44
|
|
38
45
|
it 'returns the file in home if traversing from the current dir fails' do
|
39
46
|
skip_if_a_config_in_tempdir
|
40
47
|
|
41
|
-
Dir.mktmpdir
|
42
|
-
found = described_class.find(current: Pathname.new(tempdir))
|
43
|
-
expect(found).to eq(
|
48
|
+
Dir.mktmpdir do |tempdir|
|
49
|
+
found = described_class.find(current: Pathname.new(tempdir), home: regular_configuration_dir)
|
50
|
+
expect(found).to eq(regular_configuration_file)
|
44
51
|
end
|
45
52
|
end
|
46
53
|
|
47
54
|
it 'prefers the file in :current over one in :home' do
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
expect(found).to eq(file_in_current)
|
55
|
+
home_dir = CONFIGURATION_DIR.join('home')
|
56
|
+
found = described_class.find(current: regular_configuration_dir, home: home_dir)
|
57
|
+
expect(found).to eq(regular_configuration_file)
|
52
58
|
end
|
53
59
|
|
54
60
|
it 'returns nil when there are no files to find' do
|
@@ -68,12 +74,10 @@ RSpec.describe Reek::Configuration::ConfigurationFileFinder do
|
|
68
74
|
skip_if_a_config_in_tempdir
|
69
75
|
|
70
76
|
Dir.mktmpdir do |tempdir|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
FileUtils.mkdir(subdir)
|
77
|
+
current = Pathname.new(tempdir)
|
78
|
+
home = SAMPLES_DIR.join('no_config_file')
|
75
79
|
|
76
|
-
found = described_class.find(current:
|
80
|
+
found = described_class.find(current: current, home: home)
|
77
81
|
|
78
82
|
expect(found).to be_nil
|
79
83
|
end
|
@@ -81,7 +85,7 @@ RSpec.describe Reek::Configuration::ConfigurationFileFinder do
|
|
81
85
|
|
82
86
|
it 'works with paths that need escaping' do
|
83
87
|
Dir.mktmpdir("ma\ngic d*r") do |tempdir|
|
84
|
-
config = Pathname.new("#{tempdir}
|
88
|
+
config = Pathname.new("#{tempdir}/.reek.yml")
|
85
89
|
subdir = Pathname.new("#{tempdir}/ma\ngic subd*r")
|
86
90
|
FileUtils.touch config
|
87
91
|
FileUtils.mkdir subdir
|
@@ -89,42 +93,122 @@ RSpec.describe Reek::Configuration::ConfigurationFileFinder do
|
|
89
93
|
expect(found).to eq(config)
|
90
94
|
end
|
91
95
|
end
|
92
|
-
|
93
|
-
context 'with more than one configuration file' do
|
94
|
-
let(:path) { CONFIG_PATH.join('more_than_one_configuration_file') }
|
95
|
-
|
96
|
-
it 'prints a message on STDERR' do
|
97
|
-
expected_message = "Error: Found multiple configuration files 'regular.reek', 'todo.reek'"
|
98
|
-
expect do
|
99
|
-
begin
|
100
|
-
described_class.find(current: path)
|
101
|
-
rescue SystemExit
|
102
|
-
end
|
103
|
-
end.to output(/#{expected_message}/).to_stderr
|
104
|
-
end
|
105
|
-
|
106
|
-
it 'exits' do
|
107
|
-
Reek::CLI::Silencer.silently do
|
108
|
-
expect do
|
109
|
-
described_class.find(current: path)
|
110
|
-
end.to raise_error(SystemExit)
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
96
|
end
|
115
97
|
|
116
98
|
describe '.load_from_file' do
|
117
99
|
let(:sample_configuration_loaded) do
|
118
100
|
{
|
119
|
-
|
120
|
-
|
101
|
+
Reek::Configuration::AppConfiguration::DETECTORS_KEY => {
|
102
|
+
'UncommunicativeVariableName' => { 'enabled' => false },
|
103
|
+
'UncommunicativeMethodName' => { 'enabled' => false }
|
104
|
+
}
|
121
105
|
}
|
122
106
|
end
|
123
107
|
|
124
108
|
it 'loads the configuration from given file' do
|
125
|
-
configuration = described_class.load_from_file(
|
109
|
+
configuration = described_class.load_from_file(CONFIGURATION_DIR.join('full_mask.reek'))
|
126
110
|
expect(configuration).to eq(sample_configuration_loaded)
|
127
111
|
end
|
112
|
+
|
113
|
+
context 'with exclude, accept and reject settings' do
|
114
|
+
context 'when configuring top level detectors' do
|
115
|
+
let(:configuration) do
|
116
|
+
described_class.
|
117
|
+
load_from_file(CONFIGURATION_DIR.join('accepts_rejects_and_excludes_for_detectors.reek.yml')).
|
118
|
+
fetch(Reek::Configuration::AppConfiguration::DETECTORS_KEY)
|
119
|
+
end
|
120
|
+
|
121
|
+
let(:expected) do
|
122
|
+
{
|
123
|
+
'UnusedPrivateMethod' => { 'exclude' => [/exclude regexp/] },
|
124
|
+
'UncommunicativeMethodName' => { 'reject' => ['reject name'],
|
125
|
+
'accept' => ['accept name'] },
|
126
|
+
'UncommunicativeModuleName' => { 'reject' => ['reject name 1', 'reject name 2'],
|
127
|
+
'accept' => ['accept name 1', 'accept name 2'] },
|
128
|
+
'UncommunicativeParameterName' => { 'reject' => ['reject name', /reject regexp/],
|
129
|
+
'accept' => ['accept name', /accept regexp/] },
|
130
|
+
'UncommunicativeVariableName' => { 'reject' => [/^reject regexp$/],
|
131
|
+
'accept' => [/accept(.*)regexp/] }
|
132
|
+
}
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'converts marked strings to regexes' do
|
136
|
+
expect(configuration['UnusedPrivateMethod']).to eq(expected['UnusedPrivateMethod'])
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'leaves regular single strings untouched' do
|
140
|
+
expect(configuration['UncommunicativeMethodName']).to eq(expected['UncommunicativeMethodName'])
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'leaves regular multiple strings untouched' do
|
144
|
+
expect(configuration['UncommunicativeModuleName']).to eq(expected['UncommunicativeModuleName'])
|
145
|
+
end
|
146
|
+
|
147
|
+
it 'allows mixing of regular strings and marked strings' do
|
148
|
+
expect(configuration['UncommunicativeParameterName']).to eq(expected['UncommunicativeParameterName'])
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'converts more complex marked strings correctly to regexes' do
|
152
|
+
expect(configuration['UncommunicativeVariableName']).to eq(expected['UncommunicativeVariableName'])
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context 'when configuring directory directives' do
|
157
|
+
let(:directory_name) { 'app/controllers' }
|
158
|
+
let(:configuration) do
|
159
|
+
described_class.
|
160
|
+
load_from_file(CONFIGURATION_DIR.join('accepts_rejects_and_excludes_for_directory_directives.reek.yml')).
|
161
|
+
fetch(Reek::Configuration::AppConfiguration::DIRECTORIES_KEY)
|
162
|
+
end
|
163
|
+
|
164
|
+
let(:expected) do
|
165
|
+
{
|
166
|
+
directory_name => {
|
167
|
+
'UnusedPrivateMethod' => { 'exclude' => [/exclude regexp/] },
|
168
|
+
'UncommunicativeMethodName' => { 'reject' => ['reject name'],
|
169
|
+
'accept' => ['accept name'] },
|
170
|
+
'UncommunicativeModuleName' => { 'reject' => ['reject name 1', 'reject name 2'],
|
171
|
+
'accept' => ['accept name 1', 'accept name 2'] },
|
172
|
+
'UncommunicativeParameterName' => { 'reject' => ['reject name', /reject regexp/],
|
173
|
+
'accept' => ['accept name', /accept regexp/] },
|
174
|
+
'UncommunicativeVariableName' => { 'reject' => [/^reject regexp$/],
|
175
|
+
'accept' => [/accept(.*)regexp/] }
|
176
|
+
}
|
177
|
+
}
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'converts marked strings to regexes' do
|
181
|
+
expect(configuration[directory_name]['UnusedPrivateMethod']).
|
182
|
+
to eq(expected[directory_name]['UnusedPrivateMethod'])
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'leaves regular single strings untouched' do
|
186
|
+
expect(configuration[directory_name]['UncommunicativeMethodName']).
|
187
|
+
to eq(expected[directory_name]['UncommunicativeMethodName'])
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'leaves regular multiple strings untouched' do
|
191
|
+
expect(configuration[directory_name]['UncommunicativeModuleName']).
|
192
|
+
to eq(expected[directory_name]['UncommunicativeModuleName'])
|
193
|
+
end
|
194
|
+
|
195
|
+
it 'allows mixing of regular strings and marked strings' do
|
196
|
+
expect(configuration[directory_name]['UncommunicativeParameterName']).
|
197
|
+
to eq(expected[directory_name]['UncommunicativeParameterName'])
|
198
|
+
end
|
199
|
+
|
200
|
+
it 'converts more complex marked strings correctly to regexes' do
|
201
|
+
expect(configuration[directory_name]['UncommunicativeVariableName']).
|
202
|
+
to eq(expected[directory_name]['UncommunicativeVariableName'])
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
it 'returns blank hash when no file is found' do
|
208
|
+
config = described_class.load_from_file(nil)
|
209
|
+
|
210
|
+
expect(config).to eq({})
|
211
|
+
end
|
128
212
|
end
|
129
213
|
|
130
214
|
private
|