reek 2.0.4 → 3.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/.gitignore +13 -0
- data/.rubocop.yml +47 -0
- data/.travis.yml +31 -0
- data/.yardopts +3 -6
- data/CHANGELOG +24 -0
- data/CONTRIBUTING.md +111 -0
- data/Gemfile +16 -0
- data/README.md +112 -59
- data/bin/reek +2 -2
- data/config/cucumber.yml +3 -0
- data/config/defaults.reek +0 -1
- data/docs/API.md +79 -0
- data/docs/Attribute.md +43 -0
- data/docs/Basic-Smell-Options.md +44 -0
- data/docs/Boolean-Parameter.md +52 -0
- data/docs/Class-Variable.md +40 -0
- data/docs/Code-Smells.md +34 -0
- data/docs/Command-Line-Options.md +84 -0
- data/docs/Configuration-Files.md +49 -0
- data/docs/Control-Couple.md +22 -0
- data/docs/Control-Parameter.md +29 -0
- data/docs/Data-Clump.md +44 -0
- data/docs/Duplicate-Method-Call.md +49 -0
- data/docs/Feature-Envy.md +49 -0
- data/docs/How-reek-works-internally.md +114 -0
- data/docs/Irresponsible-Module.md +39 -0
- data/docs/Large-Class.md +20 -0
- data/docs/Long-Parameter-List.md +38 -0
- data/docs/Long-Yield-List.md +36 -0
- data/docs/Module-Initialize.md +62 -0
- data/docs/Nested-Iterators.md +38 -0
- data/docs/Nil-Check.md +39 -0
- data/docs/Prima-Donna-Method.md +53 -0
- data/docs/RSpec-matchers.md +137 -0
- data/docs/Rake-Task.md +58 -0
- data/docs/Reek-Driven-Development.md +37 -0
- data/docs/Repeated-Conditional.md +44 -0
- data/docs/Simulated-Polymorphism.md +16 -0
- data/docs/Smell-Suppression.md +32 -0
- data/docs/Too-Many-Instance-Variables.md +43 -0
- data/docs/Too-Many-Methods.md +55 -0
- data/docs/Too-Many-Statements.md +50 -0
- data/docs/Uncommunicative-Method-Name.md +24 -0
- data/docs/Uncommunicative-Module-Name.md +23 -0
- data/docs/Uncommunicative-Name.md +16 -0
- data/docs/Uncommunicative-Parameter-Name.md +24 -0
- data/docs/Uncommunicative-Variable-Name.md +24 -0
- data/docs/Unused-Parameters.md +27 -0
- data/docs/Utility-Function.md +44 -0
- data/docs/Versioning-Policy.md +7 -0
- data/docs/YAML-Reports.md +111 -0
- data/docs/yard_plugin.rb +14 -0
- data/features/{ruby_api/api.feature → command_line_interface/basic_usage.feature} +6 -5
- data/features/command_line_interface/options.feature +1 -0
- data/features/command_line_interface/smell_selection.feature +4 -8
- data/features/command_line_interface/smells_count.feature +25 -32
- data/features/command_line_interface/stdin.feature +2 -2
- data/features/configuration_files/masking_smells.feature +30 -41
- data/features/configuration_files/overrides_defaults.feature +5 -3
- data/features/configuration_loading.feature +26 -23
- data/features/programmatic_access.feature +43 -0
- data/features/rake_task/rake_task.feature +25 -22
- data/features/reports/json.feature +24 -26
- data/features/reports/reports.feature +77 -103
- data/features/reports/yaml.feature +26 -20
- data/features/samples.feature +26 -31
- data/features/step_definitions/.rubocop.yml +5 -0
- data/features/step_definitions/reek_steps.rb +16 -28
- data/features/step_definitions/sample_file_steps.rb +158 -0
- data/features/support/env.rb +16 -27
- data/lib/reek/{source → ast}/ast_node_class_map.rb +11 -12
- data/lib/reek/ast/node.rb +132 -0
- data/lib/reek/{core → ast}/object_refs.rb +2 -1
- data/lib/reek/ast/reference_collector.rb +32 -0
- data/lib/reek/{source → ast}/sexp_extensions.rb +43 -7
- data/lib/reek/ast/sexp_formatter.rb +31 -0
- data/lib/reek/cli/application.rb +5 -4
- data/lib/reek/cli/command.rb +2 -1
- data/lib/reek/cli/input.rb +6 -5
- data/lib/reek/cli/option_interpreter.rb +13 -9
- data/lib/reek/cli/options.rb +16 -8
- data/lib/reek/cli/reek_command.rb +4 -3
- data/lib/reek/cli/silencer.rb +14 -0
- data/lib/reek/{core → cli}/warning_collector.rb +2 -1
- data/lib/reek/code_comment.rb +36 -0
- data/lib/reek/configuration/app_configuration.rb +18 -3
- data/lib/reek/configuration/configuration_file_finder.rb +18 -32
- data/lib/reek/{core → context}/code_context.rb +8 -6
- data/lib/reek/{core → context}/method_context.rb +11 -5
- data/lib/reek/{core → context}/module_context.rb +9 -4
- data/lib/reek/{core/stop_context.rb → context/root_context.rb} +4 -2
- data/lib/reek/{core → context}/singleton_method_context.rb +3 -6
- data/lib/reek/examiner.rb +32 -29
- data/lib/reek/report/formatter.rb +70 -0
- data/lib/reek/report/heading_formatter.rb +45 -0
- data/lib/reek/report/location_formatter.rb +35 -0
- data/lib/reek/report/report.rb +198 -0
- data/lib/reek/smells/attribute.rb +41 -11
- data/lib/reek/smells/boolean_parameter.rb +4 -2
- data/lib/reek/smells/class_variable.rb +4 -2
- data/lib/reek/smells/control_parameter.rb +4 -2
- data/lib/reek/smells/data_clump.rb +4 -3
- data/lib/reek/smells/duplicate_method_call.rb +15 -5
- data/lib/reek/smells/feature_envy.rb +8 -2
- data/lib/reek/smells/irresponsible_module.rb +13 -8
- data/lib/reek/smells/long_parameter_list.rb +6 -4
- data/lib/reek/smells/long_yield_list.rb +4 -2
- data/lib/reek/smells/module_initialize.rb +4 -2
- data/lib/reek/smells/nested_iterators.rb +4 -2
- data/lib/reek/smells/nil_check.rb +6 -3
- data/lib/reek/smells/prima_donna_method.rb +21 -12
- data/lib/reek/smells/repeated_conditional.rb +7 -4
- data/lib/reek/{core → smells}/smell_configuration.rb +3 -1
- data/lib/reek/smells/smell_detector.rb +11 -5
- data/lib/reek/{core → smells}/smell_repository.rb +9 -5
- data/lib/reek/smells/smell_warning.rb +101 -0
- data/lib/reek/smells/too_many_instance_variables.rb +4 -2
- data/lib/reek/smells/too_many_methods.rb +4 -2
- data/lib/reek/smells/too_many_statements.rb +4 -2
- data/lib/reek/smells/uncommunicative_method_name.rb +4 -2
- data/lib/reek/smells/uncommunicative_module_name.rb +4 -2
- data/lib/reek/smells/uncommunicative_parameter_name.rb +4 -2
- data/lib/reek/smells/uncommunicative_variable_name.rb +4 -2
- data/lib/reek/smells/unused_parameters.rb +4 -2
- data/lib/reek/smells/utility_function.rb +11 -22
- data/lib/reek/smells.rb +24 -11
- data/lib/reek/source/source_code.rb +69 -12
- data/lib/reek/source/source_locator.rb +34 -19
- data/lib/reek/spec/should_reek.rb +4 -3
- data/lib/reek/spec/should_reek_of.rb +2 -1
- data/lib/reek/spec/should_reek_only_of.rb +4 -3
- data/lib/reek/spec.rb +3 -3
- data/lib/reek/tree_dresser.rb +32 -0
- data/lib/reek/tree_walker.rb +182 -0
- data/lib/reek/version.rb +1 -1
- data/lib/reek.rb +3 -3
- data/reek.gemspec +18 -25
- data/spec/factories/factories.rb +4 -2
- data/spec/gem/updates_spec.rb +1 -1
- data/spec/gem/yard_spec.rb +2 -2
- data/spec/quality/reek_source_spec.rb +3 -3
- data/spec/reek/{source/sexp_node_spec.rb → ast/node_spec.rb} +4 -6
- data/spec/reek/{core → ast}/object_refs_spec.rb +4 -6
- data/spec/reek/{source → ast}/reference_collector_spec.rb +27 -19
- data/spec/reek/{source → ast}/sexp_extensions_spec.rb +7 -19
- data/spec/reek/{source → ast}/sexp_formatter_spec.rb +13 -8
- data/spec/reek/cli/option_interpreter_spec.rb +15 -0
- data/spec/reek/cli/options_spec.rb +19 -0
- data/spec/reek/cli/warning_collector_spec.rb +28 -0
- data/spec/reek/{source/code_comment_spec.rb → code_comment_spec.rb} +19 -17
- data/spec/reek/configuration/app_configuration_spec.rb +37 -26
- data/spec/reek/configuration/configuration_file_finder_spec.rb +67 -21
- data/spec/reek/{core → context}/code_context_spec.rb +18 -21
- data/spec/reek/{core → context}/method_context_spec.rb +33 -27
- data/spec/reek/{core → context}/module_context_spec.rb +5 -7
- data/spec/reek/context/root_context_spec.rb +14 -0
- data/spec/reek/context/singleton_method_context_spec.rb +17 -0
- data/spec/reek/examiner_spec.rb +9 -50
- data/spec/reek/{cli → report}/html_report_spec.rb +6 -9
- data/spec/reek/report/json_report_spec.rb +20 -0
- data/spec/reek/{cli → report}/text_report_spec.rb +16 -19
- data/spec/reek/report/xml_report_spec.rb +34 -0
- data/spec/reek/report/yaml_report_spec.rb +20 -0
- data/spec/reek/smells/attribute_spec.rb +93 -88
- data/spec/reek/smells/behaves_like_variable_detector.rb +1 -1
- data/spec/reek/smells/boolean_parameter_spec.rb +31 -5
- data/spec/reek/smells/class_variable_spec.rb +10 -10
- data/spec/reek/smells/control_parameter_spec.rb +5 -5
- data/spec/reek/smells/data_clump_spec.rb +6 -6
- data/spec/reek/smells/duplicate_method_call_spec.rb +7 -7
- data/spec/reek/smells/feature_envy_spec.rb +12 -13
- data/spec/reek/smells/irresponsible_module_spec.rb +28 -32
- data/spec/reek/smells/long_parameter_list_spec.rb +7 -7
- data/spec/reek/smells/long_yield_list_spec.rb +6 -6
- data/spec/reek/smells/module_initialize_spec.rb +4 -4
- data/spec/reek/smells/nested_iterators_spec.rb +6 -6
- data/spec/reek/smells/nil_check_spec.rb +6 -6
- data/spec/reek/smells/prima_donna_method_spec.rb +8 -5
- data/spec/reek/smells/repeated_conditional_spec.rb +18 -17
- data/spec/reek/{core → smells}/smell_configuration_spec.rb +5 -7
- data/spec/reek/smells/smell_detector_shared.rb +6 -7
- data/spec/reek/smells/smell_repository_spec.rb +29 -0
- data/spec/reek/{smell_warning_spec.rb → smells/smell_warning_spec.rb} +7 -9
- data/spec/reek/smells/too_many_instance_variables_spec.rb +5 -5
- data/spec/reek/smells/too_many_methods_spec.rb +12 -8
- data/spec/reek/smells/too_many_statements_spec.rb +10 -9
- data/spec/reek/smells/uncommunicative_method_name_spec.rb +5 -5
- data/spec/reek/smells/uncommunicative_module_name_spec.rb +8 -8
- data/spec/reek/smells/uncommunicative_parameter_name_spec.rb +18 -6
- data/spec/reek/smells/uncommunicative_variable_name_spec.rb +10 -7
- data/spec/reek/smells/unused_parameters_spec.rb +4 -4
- data/spec/reek/smells/utility_function_spec.rb +65 -39
- data/spec/reek/source/source_code_spec.rb +10 -10
- data/spec/reek/source/source_locator_spec.rb +30 -0
- data/spec/reek/spec/should_reek_of_spec.rb +9 -25
- data/spec/reek/spec/should_reek_only_of_spec.rb +4 -7
- data/spec/reek/spec/should_reek_spec.rb +4 -32
- data/spec/reek/tree_dresser_spec.rb +16 -0
- data/spec/reek/{core/tree_walker_spec.rb → tree_walker_spec.rb} +5 -7
- data/spec/samples/checkstyle.xml +2 -0
- data/spec/samples/configuration/with_excluded_paths.reek +4 -0
- data/spec/samples/{overrides/masked/lower.reek → masked_by_dotfile/.reek} +3 -1
- data/spec/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +5 -0
- data/spec/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +2 -0
- data/spec/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +6 -0
- data/spec/samples/{ruby20_syntax.rb → unusual_syntax.rb} +8 -0
- data/spec/spec_helper.rb +21 -10
- data/tasks/develop.rake +2 -2
- data/tasks/reek.rake +1 -1
- metadata +158 -141
- data/features/support/hooks.rb +0 -15
- data/lib/reek/cli/report/formatter.rb +0 -69
- data/lib/reek/cli/report/heading_formatter.rb +0 -45
- data/lib/reek/cli/report/location_formatter.rb +0 -34
- data/lib/reek/cli/report/report.rb +0 -131
- data/lib/reek/core/tree_walker.rb +0 -180
- data/lib/reek/smell_warning.rb +0 -87
- data/lib/reek/source/ast_node.rb +0 -38
- data/lib/reek/source/code_comment.rb +0 -37
- data/lib/reek/source/core_extras.rb +0 -46
- data/lib/reek/source/reference_collector.rb +0 -27
- data/lib/reek/source/sexp_formatter.rb +0 -22
- data/lib/reek/source/sexp_node.rb +0 -79
- data/lib/reek/source/source_file.rb +0 -16
- data/lib/reek/source/source_repository.rb +0 -45
- data/lib/reek/source/tree_dresser.rb +0 -24
- data/lib/reek/source.rb +0 -16
- data/spec/reek/cli/json_report_spec.rb +0 -20
- data/spec/reek/cli/option_interperter_spec.rb +0 -14
- data/spec/reek/cli/yaml_report_spec.rb +0 -23
- data/spec/reek/core/singleton_method_context_spec.rb +0 -9
- data/spec/reek/core/smell_repository_spec.rb +0 -17
- data/spec/reek/core/stop_context_spec.rb +0 -17
- data/spec/reek/core/warning_collector_spec.rb +0 -30
- data/spec/reek/source/object_source_spec.rb +0 -20
- data/spec/reek/source/tree_dresser_spec.rb +0 -18
- data/spec/samples/config/allow_duplication.reek +0 -3
- data/spec/samples/config/deeper_nested_iterators.reek +0 -3
- data/spec/samples/configuration_loading/minimal_dirty.rb +0 -4
- data/spec/samples/configuration_loading/reek-test-run-disable_smells.reek +0 -7
- data/spec/samples/configuration_loading/reek-test-run-enable_smells.reek +0 -7
- data/spec/samples/corrupt_config_file/corrupt.reek +0 -1
- data/spec/samples/corrupt_config_file/dirty.rb +0 -8
- data/spec/samples/demo/demo.rb +0 -8
- data/spec/samples/empty_config_file/dirty.rb +0 -8
- data/spec/samples/empty_config_file/empty.reek +0 -0
- data/spec/samples/inline_config/dirty.rb +0 -16
- data/spec/samples/inline_config/masked.reek +0 -7
- data/spec/samples/mask_some/dirty.rb +0 -8
- data/spec/samples/mask_some/some.reek +0 -8
- data/spec/samples/masked/dirty.rb +0 -8
- data/spec/samples/masked/masked.reek +0 -5
- data/spec/samples/minimal_smelly_and_masked/config.reek +0 -7
- data/spec/samples/minimal_smelly_and_masked/minimal_dirty.rb +0 -4
- data/spec/samples/mixed_results/clean_one.rb +0 -7
- data/spec/samples/mixed_results/clean_three.rb +0 -7
- data/spec/samples/mixed_results/clean_two.rb +0 -7
- data/spec/samples/mixed_results/dirty_one.rb +0 -8
- data/spec/samples/mixed_results/dirty_two.rb +0 -8
- data/spec/samples/not_quite_masked/dirty.rb +0 -8
- data/spec/samples/not_quite_masked/masked.reek +0 -5
- data/spec/samples/not_quite_masked/smelly.rb +0 -3
- data/spec/samples/one_smelly_file/dirty.rb +0 -3
- data/spec/samples/overrides/masked/dirty.rb +0 -8
- data/spec/samples/overrides/upper.reek +0 -5
- data/spec/samples/overrides_defaults/camel_case.rb +0 -14
- data/spec/samples/overrides_defaults/config.reek +0 -6
- data/spec/samples/ruby21_syntax.rb +0 -5
- data/spec/samples/standard_smelly/dirty.rb +0 -8
- data/spec/samples/standard_smelly/minimal_dirty.rb +0 -4
- data/spec/samples/three_smelly_files/dirty_one.rb +0 -3
- data/spec/samples/three_smelly_files/dirty_three.rb +0 -5
- data/spec/samples/three_smelly_files/dirty_two.rb +0 -4
- /data/spec/samples/{simple_configuration.reek → configuration/simple_configuration.reek} +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
|
|
3
|
+
require_relative '../../../lib/reek/cli/options'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Reek::CLI::Options do
|
|
6
|
+
describe '#initialize' do
|
|
7
|
+
it 'should enable colors when stdout is a TTY' do
|
|
8
|
+
allow($stdout).to receive_messages(tty?: false)
|
|
9
|
+
options = Reek::CLI::Options.new.parse
|
|
10
|
+
expect(options.colored).to be false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'should not enable colors when stdout is not a TTY' do
|
|
14
|
+
allow($stdout).to receive_messages(tty?: true)
|
|
15
|
+
options = Reek::CLI::Options.new.parse
|
|
16
|
+
expect(options.colored).to be true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_relative '../../../lib/reek/cli/warning_collector'
|
|
3
|
+
require_relative '../../../lib/reek/smells/smell_warning'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Reek::CLI::WarningCollector do
|
|
6
|
+
before(:each) do
|
|
7
|
+
@collector = described_class.new
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
context 'when empty' do
|
|
11
|
+
it 'reports no warnings' do
|
|
12
|
+
expect(@collector.warnings).to eq([])
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
context 'with one warning' do
|
|
17
|
+
before :each do
|
|
18
|
+
@warning = Reek::Smells::SmellWarning.new(Reek::Smells::FeatureEnvy.new(''),
|
|
19
|
+
context: 'fred',
|
|
20
|
+
lines: [1, 2, 3],
|
|
21
|
+
message: 'hello')
|
|
22
|
+
@collector.found_smell(@warning)
|
|
23
|
+
end
|
|
24
|
+
it 'reports that warning' do
|
|
25
|
+
expect(@collector.warnings).to eq([@warning])
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
require_relative '../spec_helper'
|
|
2
|
+
require_relative '../../lib/reek/code_comment'
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
describe CodeComment do
|
|
4
|
+
RSpec.describe Reek::CodeComment do
|
|
7
5
|
context 'with an empty comment' do
|
|
8
6
|
before :each do
|
|
9
|
-
@comment =
|
|
7
|
+
@comment = described_class.new('')
|
|
10
8
|
end
|
|
11
9
|
it 'is not descriptive' do
|
|
12
10
|
expect(@comment).not_to be_descriptive
|
|
@@ -18,34 +16,37 @@ describe CodeComment do
|
|
|
18
16
|
|
|
19
17
|
context 'comment checks' do
|
|
20
18
|
it 'rejects an empty comment' do
|
|
21
|
-
expect(
|
|
19
|
+
expect(described_class.new('#')).not_to be_descriptive
|
|
22
20
|
end
|
|
23
21
|
it 'rejects a 1-word comment' do
|
|
24
|
-
expect(
|
|
22
|
+
expect(described_class.new("# fred\n# ")).not_to be_descriptive
|
|
25
23
|
end
|
|
26
24
|
it 'accepts a 2-word comment' do
|
|
27
|
-
expect(
|
|
25
|
+
expect(described_class.new('# fred here ')).to be_descriptive
|
|
28
26
|
end
|
|
29
27
|
it 'accepts a multi-word comment' do
|
|
30
|
-
|
|
28
|
+
comment = "# fred here \n# with \n # biscuits "
|
|
29
|
+
expect(described_class.new(comment)).to be_descriptive
|
|
31
30
|
end
|
|
32
31
|
end
|
|
33
32
|
|
|
34
33
|
context 'comment config' do
|
|
35
34
|
it 'parses hashed options' do
|
|
36
|
-
|
|
35
|
+
comment = '# :reek:Duplication: { enabled: false }'
|
|
36
|
+
config = described_class.new(comment).config
|
|
37
37
|
expect(config).to include('Duplication')
|
|
38
38
|
expect(config['Duplication']).to include('enabled')
|
|
39
39
|
expect(config['Duplication']['enabled']).to be_falsey
|
|
40
40
|
end
|
|
41
41
|
it 'parses hashed options with ruby names' do
|
|
42
|
-
|
|
42
|
+
comment = '# :reek:nested_iterators: { enabled: true }'
|
|
43
|
+
config = described_class.new(comment).config
|
|
43
44
|
expect(config).to include('NestedIterators')
|
|
44
45
|
expect(config['NestedIterators']).to include('enabled')
|
|
45
46
|
expect(config['NestedIterators']['enabled']).to be_truthy
|
|
46
47
|
end
|
|
47
48
|
it 'parses multiple hashed options' do
|
|
48
|
-
config =
|
|
49
|
+
config = described_class.new('
|
|
49
50
|
# :reek:Duplication: { enabled: false }
|
|
50
51
|
:reek:nested_iterators: { enabled: true }
|
|
51
52
|
').config
|
|
@@ -56,7 +57,7 @@ describe CodeComment do
|
|
|
56
57
|
expect(config['NestedIterators']['enabled']).to be_truthy
|
|
57
58
|
end
|
|
58
59
|
it 'parses multiple hashed options on the same line' do
|
|
59
|
-
config =
|
|
60
|
+
config = described_class.new('
|
|
60
61
|
#:reek:Duplication: { enabled: false } and :reek:nested_iterators: { enabled: true }
|
|
61
62
|
').config
|
|
62
63
|
expect(config).to include('Duplication', 'NestedIterators')
|
|
@@ -66,7 +67,8 @@ describe CodeComment do
|
|
|
66
67
|
expect(config['NestedIterators']['enabled']).to be_truthy
|
|
67
68
|
end
|
|
68
69
|
it 'parses multiple unhashed options on the same line' do
|
|
69
|
-
|
|
70
|
+
comment = '# :reek:Duplication and :reek:nested_iterators'
|
|
71
|
+
config = described_class.new(comment).config
|
|
70
72
|
expect(config).to include('Duplication', 'NestedIterators')
|
|
71
73
|
expect(config['Duplication']).to include('enabled')
|
|
72
74
|
expect(config['Duplication']['enabled']).to be_falsey
|
|
@@ -74,13 +76,13 @@ describe CodeComment do
|
|
|
74
76
|
expect(config['NestedIterators']['enabled']).to be_falsey
|
|
75
77
|
end
|
|
76
78
|
it 'disables the smell if no options are specifed' do
|
|
77
|
-
config =
|
|
79
|
+
config = described_class.new('# :reek:Duplication').config
|
|
78
80
|
expect(config).to include('Duplication')
|
|
79
81
|
expect(config['Duplication']).to include('enabled')
|
|
80
82
|
expect(config['Duplication']['enabled']).to be_falsey
|
|
81
83
|
end
|
|
82
84
|
it 'ignores smells after a space' do
|
|
83
|
-
config =
|
|
85
|
+
config = described_class.new('# :reek: Duplication').config
|
|
84
86
|
expect(config).not_to include('Duplication')
|
|
85
87
|
end
|
|
86
88
|
end
|
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_relative '../../../lib/reek/configuration/app_configuration'
|
|
3
|
+
require_relative '../../../lib/reek/smells/smell_repository'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
describe AppConfiguration do
|
|
9
|
-
let(:sample_configuration_path) { 'spec/samples/simple_configuration.reek' }
|
|
5
|
+
RSpec.describe Reek::Configuration::AppConfiguration do
|
|
6
|
+
let(:sample_configuration_path) { 'spec/samples/configuration/simple_configuration.reek' }
|
|
10
7
|
let(:sample_configuration_loaded) do
|
|
11
8
|
{
|
|
12
9
|
'UncommunicativeVariableName' => { 'enabled' => false },
|
|
@@ -15,31 +12,32 @@ describe AppConfiguration do
|
|
|
15
12
|
end
|
|
16
13
|
let(:default_configuration) { Hash.new }
|
|
17
14
|
|
|
18
|
-
after(:each) {
|
|
15
|
+
after(:each) { described_class.reset }
|
|
19
16
|
|
|
20
17
|
describe '.initialize_with' do
|
|
21
18
|
it 'loads a configuration file if it can find one' do
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
finder = Reek::Configuration::ConfigurationFileFinder
|
|
20
|
+
allow(finder).to receive(:find).and_return sample_configuration_path
|
|
21
|
+
expect(described_class.configuration).to eq(default_configuration)
|
|
24
22
|
|
|
25
|
-
|
|
26
|
-
expect(
|
|
23
|
+
described_class.initialize_with(nil)
|
|
24
|
+
expect(described_class.configuration).to eq(sample_configuration_loaded)
|
|
27
25
|
end
|
|
28
26
|
|
|
29
27
|
it 'leaves the default configuration untouched if it can\'t find one' do
|
|
30
|
-
allow(ConfigurationFileFinder).to receive(:find).and_return nil
|
|
31
|
-
expect(
|
|
28
|
+
allow(Reek::Configuration::ConfigurationFileFinder).to receive(:find).and_return nil
|
|
29
|
+
expect(described_class.configuration).to eq(default_configuration)
|
|
32
30
|
|
|
33
|
-
|
|
34
|
-
expect(
|
|
31
|
+
described_class.initialize_with(nil)
|
|
32
|
+
expect(described_class.configuration).to eq(default_configuration)
|
|
35
33
|
end
|
|
36
34
|
end
|
|
37
35
|
|
|
38
36
|
describe '.configure_smell_repository' do
|
|
39
37
|
it 'should configure a given smell_repository' do
|
|
40
|
-
|
|
41
|
-
smell_repository = SmellRepository.new('def m; end')
|
|
42
|
-
|
|
38
|
+
described_class.load_from_file(sample_configuration_path)
|
|
39
|
+
smell_repository = Reek::Smells::SmellRepository.new('def m; end')
|
|
40
|
+
described_class.configure_smell_repository smell_repository
|
|
43
41
|
|
|
44
42
|
expect(smell_repository.detectors[Reek::Smells::DataClump]).to be_enabled
|
|
45
43
|
expect(smell_repository.detectors[Reek::Smells::UncommunicativeVariableName]).
|
|
@@ -48,20 +46,33 @@ describe AppConfiguration do
|
|
|
48
46
|
end
|
|
49
47
|
end
|
|
50
48
|
|
|
49
|
+
describe '.exclude_paths' do
|
|
50
|
+
let(:config_path) { 'spec/samples/configuration/with_excluded_paths.reek' }
|
|
51
|
+
|
|
52
|
+
it 'should return all paths to exclude' do
|
|
53
|
+
with_test_config(config_path) do
|
|
54
|
+
expect(described_class.exclude_paths).to eq [
|
|
55
|
+
'spec/samples/source_with_exclude_paths/ignore_me',
|
|
56
|
+
'spec/samples/source_with_exclude_paths/nested/ignore_me_as_well'
|
|
57
|
+
]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
51
62
|
describe '.load_from_file' do
|
|
52
63
|
it 'loads the configuration from given file' do
|
|
53
|
-
|
|
54
|
-
expect(
|
|
64
|
+
described_class.load_from_file(sample_configuration_path)
|
|
65
|
+
expect(described_class.configuration).to eq(sample_configuration_loaded)
|
|
55
66
|
end
|
|
56
67
|
end
|
|
57
68
|
|
|
58
69
|
describe '.reset' do
|
|
59
70
|
it 'resets the configuration' do
|
|
60
|
-
|
|
71
|
+
described_class.load_from_file(sample_configuration_path)
|
|
61
72
|
|
|
62
|
-
expect(
|
|
63
|
-
|
|
64
|
-
expect(
|
|
73
|
+
expect(described_class.configuration).to eq(sample_configuration_loaded)
|
|
74
|
+
described_class.reset
|
|
75
|
+
expect(described_class.configuration).to eq(default_configuration)
|
|
65
76
|
end
|
|
66
77
|
end
|
|
67
78
|
end
|
|
@@ -1,34 +1,80 @@
|
|
|
1
|
-
|
|
2
|
-
require 'reek/cli/application'
|
|
1
|
+
# encoding: UTF-8
|
|
3
2
|
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
require 'fileutils'
|
|
4
|
+
require 'pathname'
|
|
5
|
+
require 'tmpdir'
|
|
6
|
+
require_relative '../../spec_helper'
|
|
6
7
|
|
|
7
|
-
describe ConfigurationFileFinder do
|
|
8
|
+
RSpec.describe Reek::Configuration::ConfigurationFileFinder do
|
|
8
9
|
describe '.find' do
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
it 'returns the config_file if it’s set' do
|
|
11
|
+
config_file = double
|
|
12
|
+
options = double(config_file: config_file)
|
|
13
|
+
found = described_class.find(options: options)
|
|
14
|
+
expect(found).to eq(config_file)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'returns the file in current dir if config_file is nil' do
|
|
18
|
+
options = double(config_file: nil)
|
|
19
|
+
current = Pathname.new('spec/samples')
|
|
20
|
+
found = described_class.find(options: options, current: current)
|
|
21
|
+
expect(found).to eq(Pathname.new('spec/samples/exceptions.reek'))
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it 'returns the file in current dir if options is nil' do
|
|
25
|
+
current = Pathname.new('spec/samples')
|
|
26
|
+
found = described_class.find(current: current)
|
|
27
|
+
expect(found).to eq(Pathname.new('spec/samples/exceptions.reek'))
|
|
28
|
+
end
|
|
13
29
|
|
|
14
|
-
it '
|
|
15
|
-
|
|
30
|
+
it 'returns the file in a parent dir if none in current dir' do
|
|
31
|
+
current = Pathname.new('spec/samples/no_config_file')
|
|
32
|
+
found = described_class.find(current: current)
|
|
33
|
+
expect(found).to eq(Pathname.new('spec/samples/exceptions.reek'))
|
|
16
34
|
end
|
|
17
35
|
|
|
18
|
-
it '
|
|
19
|
-
|
|
20
|
-
|
|
36
|
+
it 'returns the file even if it’s just ‘.reek’' do
|
|
37
|
+
current = Pathname.new('spec/samples/masked_by_dotfile')
|
|
38
|
+
found = described_class.find(current: current)
|
|
39
|
+
expect(found).to eq(Pathname.new('spec/samples/masked_by_dotfile/.reek'))
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'returns the file in home if traversing from the current dir fails' do
|
|
43
|
+
skip_if_a_config_in_tempdir
|
|
44
|
+
Dir.mktmpdir do |tempdir|
|
|
45
|
+
current = Pathname.new(tempdir)
|
|
46
|
+
home = Pathname.new('spec/samples')
|
|
47
|
+
found = described_class.find(current: current, home: home)
|
|
48
|
+
expect(found).to eq(Pathname.new('spec/samples/exceptions.reek'))
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'returns nil when there are no files to find' do
|
|
53
|
+
skip_if_a_config_in_tempdir
|
|
54
|
+
Dir.mktmpdir do |tempdir|
|
|
55
|
+
current = Pathname.new(tempdir)
|
|
56
|
+
home = Pathname.new(tempdir)
|
|
57
|
+
found = described_class.find(current: current, home: home)
|
|
58
|
+
expect(found).to be_nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
21
61
|
|
|
22
|
-
|
|
23
|
-
|
|
62
|
+
it 'works with paths that need escaping' do
|
|
63
|
+
Dir.mktmpdir("ma\ngic d*r") do |tempdir|
|
|
64
|
+
config = Pathname.new("#{tempdir}/ma\ngic f*le.reek")
|
|
65
|
+
subdir = Pathname.new("#{tempdir}/ma\ngic subd*r")
|
|
66
|
+
FileUtils.touch config
|
|
67
|
+
FileUtils.mkdir subdir
|
|
68
|
+
found = described_class.find(current: subdir)
|
|
69
|
+
expect(found).to eq(config)
|
|
70
|
+
end
|
|
24
71
|
end
|
|
25
72
|
|
|
26
|
-
|
|
27
|
-
allow(ConfigurationFileFinder).to receive(:configuration_by_cli).and_return nil
|
|
28
|
-
allow(ConfigurationFileFinder).to receive(:configuration_in_file_system).and_return nil
|
|
29
|
-
expect(ConfigurationFileFinder).to receive(:configuration_in_home_directory).once
|
|
73
|
+
private
|
|
30
74
|
|
|
31
|
-
|
|
75
|
+
def skip_if_a_config_in_tempdir
|
|
76
|
+
found = described_class.find(current: Pathname.new(Dir.tmpdir))
|
|
77
|
+
skip "skipped: #{found} exists and would fail this test" if found
|
|
32
78
|
end
|
|
33
79
|
end
|
|
34
80
|
end
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_relative '../../../lib/reek/context/method_context'
|
|
3
|
+
require_relative '../../../lib/reek/context/module_context'
|
|
4
|
+
require_relative '../../../lib/reek/context/root_context'
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
describe CodeContext do
|
|
6
|
+
RSpec.describe Reek::Context::CodeContext do
|
|
9
7
|
context 'name recognition' do
|
|
10
8
|
before :each do
|
|
11
9
|
@exp_name = 'random_name' # SMELL: could use a String.random here
|
|
@@ -13,8 +11,7 @@ describe CodeContext do
|
|
|
13
11
|
@exp = double('exp')
|
|
14
12
|
allow(@exp).to receive(:name).and_return(@exp_name)
|
|
15
13
|
allow(@exp).to receive(:full_name).and_return(@full_name)
|
|
16
|
-
|
|
17
|
-
@ctx = CodeContext.new(nil, @exp)
|
|
14
|
+
@ctx = Reek::Context::CodeContext.new(nil, @exp)
|
|
18
15
|
end
|
|
19
16
|
it 'gets its short name from the exp' do
|
|
20
17
|
expect(@ctx.name).to eq(@exp_name)
|
|
@@ -44,7 +41,7 @@ describe CodeContext do
|
|
|
44
41
|
@outer_name = 'another_random sting'
|
|
45
42
|
allow(outer).to receive(:full_name).at_least(:once).and_return(@outer_name)
|
|
46
43
|
allow(outer).to receive(:config).and_return({})
|
|
47
|
-
@ctx = CodeContext.new(outer, @exp)
|
|
44
|
+
@ctx = Reek::Context::CodeContext.new(outer, @exp)
|
|
48
45
|
end
|
|
49
46
|
it 'creates the correct full name' do
|
|
50
47
|
expect(@ctx.full_name).to eq("#{@full_name}")
|
|
@@ -60,10 +57,10 @@ describe CodeContext do
|
|
|
60
57
|
|
|
61
58
|
context 'generics' do
|
|
62
59
|
it 'should pass unknown method calls down the stack' do
|
|
63
|
-
stop =
|
|
60
|
+
stop = Reek::Context::RootContext.new
|
|
64
61
|
def stop.bananas(arg1, arg2) arg1 + arg2 + 43 end
|
|
65
|
-
element = ModuleContext.new(stop, s(:module, :mod, nil))
|
|
66
|
-
element = MethodContext.new(element, s(:def, :bad, s(:args), nil))
|
|
62
|
+
element = Reek::Context::ModuleContext.new(stop, s(:module, :mod, nil))
|
|
63
|
+
element = Reek::Context::MethodContext.new(element, s(:def, :bad, s(:args), nil))
|
|
67
64
|
expect(element.bananas(17, -5)).to eq(55)
|
|
68
65
|
end
|
|
69
66
|
end
|
|
@@ -73,8 +70,8 @@ describe CodeContext do
|
|
|
73
70
|
before :each do
|
|
74
71
|
@module_name = 'Emptiness'
|
|
75
72
|
src = "module #{@module_name}; end"
|
|
76
|
-
ast = src.
|
|
77
|
-
@ctx = CodeContext.new(nil, ast)
|
|
73
|
+
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
|
74
|
+
@ctx = Reek::Context::CodeContext.new(nil, ast)
|
|
78
75
|
end
|
|
79
76
|
|
|
80
77
|
it 'yields no calls' do
|
|
@@ -105,8 +102,8 @@ describe CodeContext do
|
|
|
105
102
|
@module_name = 'Loneliness'
|
|
106
103
|
@method_name = 'calloo'
|
|
107
104
|
src = "module #{@module_name}; def #{@method_name}; puts('hello') end; end"
|
|
108
|
-
ast = src.
|
|
109
|
-
@ctx = CodeContext.new(nil, ast)
|
|
105
|
+
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
|
106
|
+
@ctx = Reek::Context::CodeContext.new(nil, ast)
|
|
110
107
|
end
|
|
111
108
|
it 'yields no ifs' do
|
|
112
109
|
@ctx.each_node(:if, []) { |exp| raise "#{exp} yielded by empty module!" }
|
|
@@ -157,8 +154,8 @@ class Scrunch
|
|
|
157
154
|
end
|
|
158
155
|
EOS
|
|
159
156
|
|
|
160
|
-
ast = src.
|
|
161
|
-
ctx = CodeContext.new(nil, ast)
|
|
157
|
+
ast = Reek::Source::SourceCode.from(src).syntax_tree
|
|
158
|
+
ctx = Reek::Context::CodeContext.new(nil, ast)
|
|
162
159
|
expect(ctx.each_node(:if, []).length).to eq(3)
|
|
163
160
|
end
|
|
164
161
|
end
|
|
@@ -166,12 +163,12 @@ EOS
|
|
|
166
163
|
describe '#config_for' do
|
|
167
164
|
let(:expression) { double('exp') }
|
|
168
165
|
let(:outer) { nil }
|
|
169
|
-
let(:context) { CodeContext.new(outer, expression) }
|
|
166
|
+
let(:context) { Reek::Context::CodeContext.new(outer, expression) }
|
|
170
167
|
let(:sniffer) { double('sniffer') }
|
|
171
168
|
|
|
172
169
|
before :each do
|
|
173
170
|
allow(sniffer).to receive(:smell_type).and_return('DuplicateMethodCall')
|
|
174
|
-
allow(expression).to receive(:
|
|
171
|
+
allow(expression).to receive(:full_comment).and_return(
|
|
175
172
|
':reek:DuplicateMethodCall: { allow_calls: [ puts ] }')
|
|
176
173
|
end
|
|
177
174
|
|
|
@@ -1,14 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_relative '../../../lib/reek/context/method_context'
|
|
3
|
+
require_relative '../../../lib/reek/context/root_context'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
describe MethodContext, 'matching' do
|
|
5
|
+
RSpec.describe Reek::Context::MethodContext, 'matching' do
|
|
8
6
|
before :each do
|
|
9
7
|
exp = double('exp').as_null_object
|
|
10
8
|
expect(exp).to receive(:full_name).at_least(:once).and_return('mod')
|
|
11
|
-
@element = MethodContext.new(
|
|
9
|
+
@element = Reek::Context::MethodContext.new(Reek::Context::RootContext.new, exp)
|
|
12
10
|
end
|
|
13
11
|
|
|
14
12
|
it 'should recognise itself in a collection of names' do
|
|
@@ -22,33 +20,41 @@ describe MethodContext, 'matching' do
|
|
|
22
20
|
end
|
|
23
21
|
end
|
|
24
22
|
|
|
25
|
-
describe MethodContext do
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
mctx.record_call_to(s(:send, s(:ivar, :@cow), :feed_to))
|
|
30
|
-
expect(mctx.envious_receivers).to eq([])
|
|
23
|
+
RSpec.describe Reek::Context::MethodContext do
|
|
24
|
+
let(:mc) do
|
|
25
|
+
sexp = s(:def, :foo, s(:args, s(:arg, :bar)), nil)
|
|
26
|
+
Reek::Context::MethodContext.new(Reek::Context::RootContext.new, sexp)
|
|
31
27
|
end
|
|
32
28
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
29
|
+
describe '#envious_receivers' do
|
|
30
|
+
it 'should ignore ivars as refs to self' do
|
|
31
|
+
mc.record_call_to s(:send, s(:ivar, :@cow), :feed_to)
|
|
32
|
+
expect(mc.envious_receivers).to be_empty
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it 'should ignore explicit calls to self' do
|
|
36
|
+
mc.refs.record_reference_to [:lvar, :other]
|
|
37
|
+
mc.record_call_to s(:send, s(:self), :thing)
|
|
38
|
+
expect(mc.envious_receivers).to be_empty
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'should ignore implicit calls to self' do
|
|
42
|
+
mc.record_call_to s(:send, s(:lvar, :text), :each, s(:arglist))
|
|
43
|
+
mc.record_call_to s(:send, nil, :shelve, s(:arglist))
|
|
44
|
+
expect(mc.envious_receivers).to be_empty
|
|
45
|
+
end
|
|
39
46
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
expect(mc.envious_receivers).to be_empty
|
|
47
|
+
it 'should record envious calls' do
|
|
48
|
+
mc.record_call_to s(:send, s(:lvar, :bar), :baz)
|
|
49
|
+
expect(mc.envious_receivers).to eq(bar: 1)
|
|
50
|
+
end
|
|
45
51
|
end
|
|
46
52
|
end
|
|
47
53
|
|
|
48
|
-
describe MethodParameters, 'default assignments' do
|
|
54
|
+
RSpec.describe Reek::Context::MethodParameters, 'default assignments' do
|
|
49
55
|
def assignments_from(src)
|
|
50
|
-
exp = src.
|
|
51
|
-
ctx = MethodContext.new(
|
|
56
|
+
exp = Reek::Source::SourceCode.from(src).syntax_tree
|
|
57
|
+
ctx = Reek::Context::MethodContext.new(Reek::Context::RootContext.new, exp)
|
|
52
58
|
ctx.parameters.default_assignments
|
|
53
59
|
end
|
|
54
60
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_relative '../../../lib/reek/context/module_context'
|
|
3
|
+
require_relative '../../../lib/reek/context/root_context'
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
describe ModuleContext do
|
|
5
|
+
RSpec.describe Reek::Context::ModuleContext do
|
|
8
6
|
it 'should report module name for smell in method' do
|
|
9
7
|
expect('
|
|
10
8
|
module Fred
|
|
@@ -21,7 +19,7 @@ module Fred
|
|
|
21
19
|
end
|
|
22
20
|
end
|
|
23
21
|
|
|
24
|
-
describe ModuleContext do
|
|
22
|
+
RSpec.describe Reek::Context::ModuleContext do
|
|
25
23
|
it 'should recognise global constant' do
|
|
26
24
|
expect('# module for test
|
|
27
25
|
module ::Global
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_relative '../../../lib/reek/context/root_context'
|
|
3
|
+
|
|
4
|
+
RSpec.describe Reek::Context::RootContext do
|
|
5
|
+
before :each do
|
|
6
|
+
@root = Reek::Context::RootContext.new
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
context 'full_name' do
|
|
10
|
+
it 'reports full context' do
|
|
11
|
+
expect(@root.full_name).to eq('')
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
require_relative '../../spec_helper'
|
|
2
|
+
require_relative '../../../lib/reek/context/singleton_method_context'
|
|
3
|
+
require_relative '../../../lib/reek/context/root_context'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Reek::Context::SingletonMethodContext do
|
|
6
|
+
let(:smc) do
|
|
7
|
+
sexp = s(:def, :foo, s(:args, s(:arg, :bar)), nil)
|
|
8
|
+
Reek::Context::SingletonMethodContext.new(Reek::Context::RootContext.new, sexp)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe '#envious_receivers' do
|
|
12
|
+
it 'should not record envious calls' do
|
|
13
|
+
smc.record_call_to s(:send, s(:lvar, :bar), :baz)
|
|
14
|
+
expect(smc.envious_receivers).to be_empty
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|