reek 6.0.2 → 6.1.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/.github/dependabot.yml +9 -0
- data/.github/workflows/ruby.yml +57 -0
- data/.rubocop.yml +5 -3
- data/.rubocop_todo.yml +6 -4
- data/CHANGELOG.md +26 -0
- data/CONTRIBUTING.md +3 -0
- data/Dockerfile +1 -1
- data/Gemfile +7 -7
- data/README.md +1 -1
- data/bin/code_climate_reek +2 -3
- data/lib/reek/ast/ast_node_class_map.rb +1 -1
- data/lib/reek/ast/node.rb +1 -1
- data/lib/reek/ast/sexp_extensions/arguments.rb +11 -0
- data/lib/reek/ast/sexp_extensions/case.rb +1 -1
- data/lib/reek/ast/sexp_extensions/if.rb +1 -1
- data/lib/reek/ast/sexp_extensions/send.rb +1 -1
- data/lib/reek/cli/command/todo_list_command.rb +1 -1
- data/lib/reek/cli/options.rb +1 -1
- data/lib/reek/code_comment.rb +22 -17
- data/lib/reek/configuration/excluded_paths.rb +2 -1
- data/lib/reek/context/code_context.rb +1 -1
- data/lib/reek/context/refinement_context.rb +16 -0
- data/lib/reek/context_builder.rb +17 -3
- data/lib/reek/rake/task.rb +1 -1
- data/lib/reek/report/code_climate/code_climate_formatter.rb +1 -3
- data/lib/reek/smell_detectors/base_detector.rb +1 -1
- data/lib/reek/smell_warning.rb +1 -1
- data/lib/reek/source/source_locator.rb +1 -3
- data/lib/reek/spec/should_reek_of.rb +6 -4
- data/lib/reek/version.rb +2 -2
- data/reek.gemspec +28 -25
- metadata +13 -240
- data/.travis.yml +0 -40
- data/docs/API.md +0 -174
- data/docs/Attribute.md +0 -39
- data/docs/Basic-Smell-Options.md +0 -85
- data/docs/Boolean-Parameter.md +0 -54
- data/docs/Class-Variable.md +0 -40
- data/docs/Code-Smells.md +0 -39
- data/docs/Command-Line-Options.md +0 -119
- data/docs/Control-Couple.md +0 -26
- data/docs/Control-Parameter.md +0 -32
- data/docs/Data-Clump.md +0 -46
- data/docs/Duplicate-Method-Call.md +0 -264
- data/docs/Feature-Envy.md +0 -93
- data/docs/How-To-Write-New-Detectors.md +0 -132
- data/docs/How-reek-works-internally.md +0 -114
- data/docs/Instance-Variable-Assumption.md +0 -163
- data/docs/Irresponsible-Module.md +0 -47
- data/docs/Large-Class.md +0 -16
- data/docs/Long-Parameter-List.md +0 -39
- data/docs/Long-Yield-List.md +0 -37
- data/docs/Manual-Dispatch.md +0 -30
- data/docs/Missing-Safe-Method.md +0 -92
- data/docs/Module-Initialize.md +0 -62
- data/docs/Nested-Iterators.md +0 -59
- data/docs/Nil-Check.md +0 -47
- data/docs/RSpec-matchers.md +0 -129
- data/docs/Rake-Task.md +0 -66
- data/docs/Reek-4-to-Reek-5-migration.md +0 -188
- data/docs/Reek-Driven-Development.md +0 -46
- data/docs/Repeated-Conditional.md +0 -47
- data/docs/Simulated-Polymorphism.md +0 -16
- data/docs/Smell-Suppression.md +0 -96
- data/docs/Style-Guide.md +0 -19
- data/docs/Subclassed-From-Core-Class.md +0 -79
- data/docs/Too-Many-Constants.md +0 -37
- data/docs/Too-Many-Instance-Variables.md +0 -43
- data/docs/Too-Many-Methods.md +0 -56
- data/docs/Too-Many-Statements.md +0 -54
- data/docs/Uncommunicative-Method-Name.md +0 -94
- data/docs/Uncommunicative-Module-Name.md +0 -92
- data/docs/Uncommunicative-Name.md +0 -18
- data/docs/Uncommunicative-Parameter-Name.md +0 -90
- data/docs/Uncommunicative-Variable-Name.md +0 -96
- data/docs/Unused-Parameters.md +0 -28
- data/docs/Unused-Private-Method.md +0 -101
- data/docs/Utility-Function.md +0 -56
- data/docs/Versioning-Policy.md +0 -7
- data/docs/YAML-Reports.md +0 -93
- data/docs/defaults.reek.yml +0 -129
- data/docs/templates/default/docstring/html/public_api_marker.erb +0 -3
- data/docs/templates/default/docstring/setup.rb +0 -37
- data/docs/templates/default/fulldoc/html/css/common.css +0 -1
- data/docs/yard_plugin.rb +0 -17
- data/features/command_line_interface/basic_usage.feature +0 -15
- data/features/command_line_interface/options.feature +0 -123
- data/features/command_line_interface/show_progress.feature +0 -33
- data/features/command_line_interface/smell_selection.feature +0 -15
- data/features/command_line_interface/smells_count.feature +0 -38
- data/features/command_line_interface/stdin.feature +0 -65
- data/features/configuration_files/accept_setting.feature +0 -87
- data/features/configuration_files/directory_specific_directives.feature +0 -274
- data/features/configuration_files/exclude_directives.feature +0 -35
- data/features/configuration_files/exclude_paths_directives.feature +0 -42
- data/features/configuration_files/masking_smells.feature +0 -94
- data/features/configuration_files/mix_accept_reject_setting.feature +0 -84
- data/features/configuration_files/reject_setting.feature +0 -89
- data/features/configuration_files/schema_validation.feature +0 -59
- data/features/configuration_files/show_configuration_file.feature +0 -44
- data/features/configuration_files/unused_private_method.feature +0 -68
- data/features/configuration_loading.feature +0 -91
- data/features/configuration_via_source_comments/erroneous_source_comments.feature +0 -68
- data/features/configuration_via_source_comments/well_formed_source_comments.feature +0 -116
- data/features/locales.feature +0 -32
- data/features/programmatic_access.feature +0 -41
- data/features/rake_task/rake_task.feature +0 -138
- data/features/reports/codeclimate.feature +0 -59
- data/features/reports/json.feature +0 -59
- data/features/reports/reports.feature +0 -219
- data/features/reports/yaml.feature +0 -52
- data/features/rspec_matcher.feature +0 -41
- data/features/samples.feature +0 -305
- data/features/step_definitions/.rubocop.yml +0 -5
- data/features/step_definitions/reek_steps.rb +0 -102
- data/features/step_definitions/sample_file_steps.rb +0 -63
- data/features/support/env.rb +0 -33
- data/features/todo_list.feature +0 -108
- data/samples/checkstyle.xml +0 -7
- data/samples/clean_source/clean.rb +0 -6
- data/samples/configuration/accepts_rejects_and_excludes_for_detectors.reek.yml +0 -29
- data/samples/configuration/accepts_rejects_and_excludes_for_directory_directives.reek.yml +0 -30
- data/samples/configuration/corrupt.reek +0 -1
- data/samples/configuration/empty.reek +0 -0
- data/samples/configuration/full_configuration.reek +0 -13
- data/samples/configuration/full_mask.reek +0 -6
- data/samples/configuration/home/home.reek.yml +0 -4
- data/samples/configuration/partial_mask.reek +0 -4
- data/samples/configuration/regular_configuration/.reek.yml +0 -4
- data/samples/configuration/regular_configuration/empty_sub_directory/.gitignore +0 -0
- data/samples/configuration/with_excluded_paths.reek +0 -5
- data/samples/no_config_file/.keep +0 -0
- data/samples/paths.rb +0 -5
- data/samples/smelly_source/inline.rb +0 -704
- data/samples/smelly_source/optparse.rb +0 -1788
- data/samples/smelly_source/redcloth.rb +0 -1130
- data/samples/smelly_source/ruby.rb +0 -368
- data/samples/smelly_source/smelly.rb +0 -7
- data/samples/source_with_exclude_paths/ignore_me/uncommunicative_method_name.rb +0 -5
- data/samples/source_with_exclude_paths/nested/ignore_me_as_well/irresponsible_module.rb +0 -2
- data/samples/source_with_exclude_paths/nested/uncommunicative_parameter_name.rb +0 -6
- data/samples/source_with_exclude_paths/nested/uncommunicative_variable_name.rb +0 -6
- data/samples/source_with_hidden_directories/.hidden/hidden.rb +0 -1
- data/samples/source_with_hidden_directories/not_hidden.rb +0 -1
- data/samples/source_with_non_ruby_files/gibberish +0 -1
- data/samples/source_with_non_ruby_files/python_source.py +0 -1
- data/samples/source_with_non_ruby_files/ruby.rb +0 -6
- data/spec/performance/reek/smell_detectors/runtime_speed_spec.rb +0 -15
- data/spec/quality/documentation_spec.rb +0 -41
- data/spec/quality/reek_source_spec.rb +0 -11
- data/spec/reek/ast/node_spec.rb +0 -211
- data/spec/reek/ast/object_refs_spec.rb +0 -83
- data/spec/reek/ast/reference_collector_spec.rb +0 -47
- data/spec/reek/ast/sexp_extensions_spec.rb +0 -498
- data/spec/reek/cli/application_spec.rb +0 -168
- data/spec/reek/cli/command/report_command_spec.rb +0 -44
- data/spec/reek/cli/command/todo_list_command_spec.rb +0 -86
- data/spec/reek/cli/options_spec.rb +0 -51
- data/spec/reek/cli/silencer_spec.rb +0 -28
- data/spec/reek/code_comment_spec.rb +0 -184
- data/spec/reek/configuration/app_configuration_spec.rb +0 -195
- data/spec/reek/configuration/configuration_file_finder_spec.rb +0 -230
- data/spec/reek/configuration/default_directive_spec.rb +0 -13
- data/spec/reek/configuration/directory_directives_spec.rb +0 -122
- data/spec/reek/configuration/excluded_paths_spec.rb +0 -16
- data/spec/reek/configuration/rake_task_converter_spec.rb +0 -33
- data/spec/reek/configuration/schema_validator_spec.rb +0 -165
- data/spec/reek/context/code_context_spec.rb +0 -192
- data/spec/reek/context/ghost_context_spec.rb +0 -60
- data/spec/reek/context/method_context_spec.rb +0 -72
- data/spec/reek/context/module_context_spec.rb +0 -55
- data/spec/reek/context/root_context_spec.rb +0 -12
- data/spec/reek/context/statement_counter_spec.rb +0 -24
- data/spec/reek/context_builder_spec.rb +0 -457
- data/spec/reek/detector_repository_spec.rb +0 -22
- data/spec/reek/documentation_link_spec.rb +0 -20
- data/spec/reek/errors/base_error_spec.rb +0 -13
- data/spec/reek/examiner_spec.rb +0 -309
- data/spec/reek/logging_error_handler_spec.rb +0 -24
- data/spec/reek/rake/task_spec.rb +0 -56
- data/spec/reek/report/code_climate/code_climate_configuration_spec.rb +0 -22
- data/spec/reek/report/code_climate/code_climate_fingerprint_spec.rb +0 -126
- data/spec/reek/report/code_climate/code_climate_formatter_spec.rb +0 -51
- data/spec/reek/report/code_climate/code_climate_report_spec.rb +0 -56
- data/spec/reek/report/html_report_spec.rb +0 -19
- data/spec/reek/report/json_report_spec.rb +0 -58
- data/spec/reek/report/location_formatter_spec.rb +0 -32
- data/spec/reek/report/progress_formatter_spec.rb +0 -68
- data/spec/reek/report/text_report_spec.rb +0 -89
- data/spec/reek/report/xml_report_spec.rb +0 -24
- data/spec/reek/report/yaml_report_spec.rb +0 -55
- data/spec/reek/report_spec.rb +0 -28
- data/spec/reek/smell_configuration_spec.rb +0 -56
- data/spec/reek/smell_detectors/attribute_spec.rb +0 -197
- data/spec/reek/smell_detectors/base_detector_spec.rb +0 -50
- data/spec/reek/smell_detectors/boolean_parameter_spec.rb +0 -93
- data/spec/reek/smell_detectors/class_variable_spec.rb +0 -106
- data/spec/reek/smell_detectors/control_parameter_spec.rb +0 -300
- data/spec/reek/smell_detectors/data_clump_spec.rb +0 -134
- data/spec/reek/smell_detectors/duplicate_method_call_spec.rb +0 -211
- data/spec/reek/smell_detectors/feature_envy_spec.rb +0 -295
- data/spec/reek/smell_detectors/instance_variable_assumption_spec.rb +0 -96
- data/spec/reek/smell_detectors/irresponsible_module_spec.rb +0 -226
- data/spec/reek/smell_detectors/long_parameter_list_spec.rb +0 -61
- data/spec/reek/smell_detectors/long_yield_list_spec.rb +0 -49
- data/spec/reek/smell_detectors/manual_dispatch_spec.rb +0 -75
- data/spec/reek/smell_detectors/missing_safe_method_spec.rb +0 -68
- data/spec/reek/smell_detectors/module_initialize_spec.rb +0 -77
- data/spec/reek/smell_detectors/nested_iterators_spec.rb +0 -333
- data/spec/reek/smell_detectors/nil_check_spec.rb +0 -100
- data/spec/reek/smell_detectors/repeated_conditional_spec.rb +0 -100
- data/spec/reek/smell_detectors/subclassed_from_core_class_spec.rb +0 -77
- data/spec/reek/smell_detectors/too_many_constants_spec.rb +0 -144
- data/spec/reek/smell_detectors/too_many_instance_variables_spec.rb +0 -132
- data/spec/reek/smell_detectors/too_many_methods_spec.rb +0 -54
- data/spec/reek/smell_detectors/too_many_statements_spec.rb +0 -90
- data/spec/reek/smell_detectors/uncommunicative_method_name_spec.rb +0 -78
- data/spec/reek/smell_detectors/uncommunicative_module_name_spec.rb +0 -78
- data/spec/reek/smell_detectors/uncommunicative_parameter_name_spec.rb +0 -147
- data/spec/reek/smell_detectors/uncommunicative_variable_name_spec.rb +0 -201
- data/spec/reek/smell_detectors/unused_parameters_spec.rb +0 -114
- data/spec/reek/smell_detectors/unused_private_method_spec.rb +0 -205
- data/spec/reek/smell_detectors/utility_function_spec.rb +0 -293
- data/spec/reek/smell_warning_spec.rb +0 -137
- data/spec/reek/source/source_code_spec.rb +0 -79
- data/spec/reek/source/source_locator_spec.rb +0 -166
- data/spec/reek/spec/should_reek_of_spec.rb +0 -153
- data/spec/reek/spec/should_reek_only_of_spec.rb +0 -91
- data/spec/reek/spec/should_reek_spec.rb +0 -52
- data/spec/reek/spec/smell_matcher_spec.rb +0 -87
- data/spec/reek/tree_dresser_spec.rb +0 -46
- data/spec/spec_helper.rb +0 -110
- data/tasks/configuration.rake +0 -18
- data/tasks/console.rake +0 -5
- data/tasks/reek.rake +0 -6
- data/tasks/rubocop.rake +0 -11
- data/tasks/test.rake +0 -32
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
require 'pathname'
|
|
2
|
-
require_relative '../../spec_helper'
|
|
3
|
-
require_lib 'reek/spec'
|
|
4
|
-
|
|
5
|
-
RSpec.describe Reek::Spec::ShouldReekOf do
|
|
6
|
-
describe 'smell type selection' do
|
|
7
|
-
let(:ruby) { 'def double_thing() @other.thing.foo + @other.thing.foo end' }
|
|
8
|
-
|
|
9
|
-
it 'reports duplicate calls by smell type' do
|
|
10
|
-
expect(ruby).to reek_of(:DuplicateMethodCall)
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
it 'does not report any feature envy' do
|
|
14
|
-
expect(ruby).not_to reek_of(:FeatureEnvy)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
describe 'different sources of input' do
|
|
19
|
-
context 'when checking code in a string' do
|
|
20
|
-
let(:clean_code) { 'def good() true; end' }
|
|
21
|
-
let(:matcher) { described_class.new(:UncommunicativeVariableName, name: 'y') }
|
|
22
|
-
let(:smelly_code) { 'def x() y = 4; end' }
|
|
23
|
-
|
|
24
|
-
it 'matches a smelly String' do
|
|
25
|
-
expect(matcher).to be_matches(smelly_code)
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it 'doesnt match a fragrant String' do
|
|
29
|
-
expect(matcher).not_to be_matches(clean_code)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it 're-calculates matches every time' do
|
|
33
|
-
matcher.matches? smelly_code
|
|
34
|
-
expect(matcher).not_to be_matches(clean_code)
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
|
|
38
|
-
context 'when checking code in a File' do
|
|
39
|
-
let(:matcher) { described_class.new(:UncommunicativeMethodName, name: 'x') }
|
|
40
|
-
|
|
41
|
-
it 'matches a smelly file' do
|
|
42
|
-
expect(matcher).to be_matches(SMELLY_FILE)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
it 'doesnt match a fragrant file' do
|
|
46
|
-
expect(matcher).not_to be_matches(CLEAN_FILE)
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
describe 'smell types and smell details' do
|
|
52
|
-
context 'when passing in smell_details with unknown parameter name' do
|
|
53
|
-
let(:matcher) { described_class.new(:UncommunicativeVariableName, foo: 'y') }
|
|
54
|
-
let(:smelly_code) { 'def x() y = 4; end' }
|
|
55
|
-
|
|
56
|
-
it 'raises ArgumentError' do
|
|
57
|
-
expect { matcher.matches?(smelly_code) }.to raise_error(ArgumentError)
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
context 'when both are matching' do
|
|
62
|
-
let(:matcher) { described_class.new(:UncommunicativeVariableName, name: 'y') }
|
|
63
|
-
let(:smelly_code) { 'def x() y = 4; end' }
|
|
64
|
-
|
|
65
|
-
it 'is truthy' do
|
|
66
|
-
expect(matcher).to be_matches(smelly_code)
|
|
67
|
-
end
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
context 'when no smell_type is matching' do
|
|
71
|
-
let(:smelly_code) { 'def dummy() y = 4; end' }
|
|
72
|
-
|
|
73
|
-
let(:falsey_matcher) { described_class.new(:FeatureEnvy, name: 'y') }
|
|
74
|
-
let(:truthy_matcher) { described_class.new(:UncommunicativeVariableName, name: 'y') }
|
|
75
|
-
|
|
76
|
-
it 'is falsey' do
|
|
77
|
-
expect(falsey_matcher).not_to be_matches(smelly_code)
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
it 'sets the proper error message' do
|
|
81
|
-
falsey_matcher.matches?(smelly_code)
|
|
82
|
-
|
|
83
|
-
expect(falsey_matcher.failure_message).to\
|
|
84
|
-
match('Expected string to reek of FeatureEnvy, but it didn\'t')
|
|
85
|
-
end
|
|
86
|
-
|
|
87
|
-
it 'sets the proper error message when negated' do
|
|
88
|
-
truthy_matcher.matches?(smelly_code)
|
|
89
|
-
|
|
90
|
-
expect(truthy_matcher.failure_message_when_negated).to\
|
|
91
|
-
match('Expected string not to reek of UncommunicativeVariableName, but it did')
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
context 'when smell type is matching but smell details are not' do
|
|
96
|
-
let(:smelly_code) { 'def double_thing() @other.thing.foo + @other.thing.foo end' }
|
|
97
|
-
let(:matcher) { described_class.new(:DuplicateMethodCall, name: 'foo', count: 15) }
|
|
98
|
-
|
|
99
|
-
it 'is falsey' do
|
|
100
|
-
expect(matcher).not_to be_matches(smelly_code)
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
it 'sets the proper error message' do
|
|
104
|
-
matcher.matches?(smelly_code)
|
|
105
|
-
expected = <<~TEXT
|
|
106
|
-
Expected string to reek of DuplicateMethodCall (which it did) with smell details {:name=>"foo", :count=>15}, which it didn't.
|
|
107
|
-
The number of smell details I had to compare with the given one was 2 and here they are:
|
|
108
|
-
1.)
|
|
109
|
-
{"context"=>"double_thing", "lines"=>[1, 1], "message"=>"calls '@other.thing' 2 times", "source"=>"string", "name"=>"@other.thing", "count"=>2}
|
|
110
|
-
2.)
|
|
111
|
-
{"context"=>"double_thing", "lines"=>[1, 1], "message"=>"calls '@other.thing.foo' 2 times", "source"=>"string", "name"=>"@other.thing.foo", "count"=>2}
|
|
112
|
-
TEXT
|
|
113
|
-
|
|
114
|
-
expect(matcher.failure_message).to eq(expected)
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
it 'sets the proper error message when negated' do
|
|
118
|
-
matcher.matches?(smelly_code)
|
|
119
|
-
|
|
120
|
-
expect(matcher.failure_message_when_negated).to\
|
|
121
|
-
match('Expected string not to reek of DuplicateMethodCall with smell '\
|
|
122
|
-
'details {:name=>"foo", :count=>15}, but it did')
|
|
123
|
-
end
|
|
124
|
-
end
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
context 'with a smell that is disabled by default' do
|
|
128
|
-
it 'enables the smell detector to match automatically' do
|
|
129
|
-
default_config = Reek::SmellDetectors::UnusedPrivateMethod.default_config
|
|
130
|
-
src = 'class C; private; def foo; end; end'
|
|
131
|
-
|
|
132
|
-
aggregate_failures do
|
|
133
|
-
expect(default_config[Reek::SmellConfiguration::ENABLED_KEY]).to be_falsy
|
|
134
|
-
expect(src).to reek_of(:UnusedPrivateMethod)
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
describe '#with_config' do
|
|
140
|
-
let(:matcher) { described_class.new(:UncommunicativeVariableName) }
|
|
141
|
-
let(:configured_matcher) { matcher.with_config('accept' => 'x') }
|
|
142
|
-
|
|
143
|
-
it 'uses the passed-in configuration for matching' do
|
|
144
|
-
expect(configured_matcher).to be_matches('def foo; q = 2; end')
|
|
145
|
-
expect(configured_matcher).not_to be_matches('def foo; x = 2; end')
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
it 'leaves the original matcher intact' do
|
|
149
|
-
expect(configured_matcher).not_to be_matches('def foo; x = 2; end')
|
|
150
|
-
expect(matcher).to be_matches('def foo; x = 2; end')
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
end
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
require_relative '../../spec_helper'
|
|
2
|
-
require_lib 'reek/spec'
|
|
3
|
-
|
|
4
|
-
RSpec.describe Reek::Spec::ShouldReekOnlyOf do
|
|
5
|
-
let(:examiner) { instance_double('Reek::Examiner').as_null_object }
|
|
6
|
-
let(:expected_context_name) { 'SmellyClass#big_method' }
|
|
7
|
-
let(:expected_smell_type) { :NestedIterators }
|
|
8
|
-
let(:matcher) { described_class.new(expected_smell_type) }
|
|
9
|
-
let(:matcher_matches) { matcher.matches_examiner?(examiner) }
|
|
10
|
-
|
|
11
|
-
before do
|
|
12
|
-
allow(examiner).to receive(:smells) { smells }
|
|
13
|
-
matcher_matches
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
shared_examples_for 'no match' do
|
|
17
|
-
it 'does not match' do
|
|
18
|
-
expect(matcher_matches).to be_falsey
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
context 'when a match was expected' do
|
|
22
|
-
let(:source) { 'the_path/to_a/source_file.rb' }
|
|
23
|
-
|
|
24
|
-
before { allow(examiner).to receive(:origin).and_return(source) }
|
|
25
|
-
|
|
26
|
-
it 'reports the source' do
|
|
27
|
-
expect(matcher.failure_message).to match(source)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it 'reports the expected smell class' do
|
|
31
|
-
expect(matcher.failure_message).to match(expected_smell_type.to_s)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
context 'with no smells' do
|
|
37
|
-
let(:smells) { [] }
|
|
38
|
-
|
|
39
|
-
it_behaves_like 'no match'
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
context 'with 1 non-matching smell' do
|
|
43
|
-
let(:smells) { [build_smell_warning(smell_type: 'ControlParameter')] }
|
|
44
|
-
|
|
45
|
-
it_behaves_like 'no match'
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
context 'with 2 non-matching smells' do
|
|
49
|
-
let(:smells) do
|
|
50
|
-
[
|
|
51
|
-
build_smell_warning(smell_type: 'ControlParameter'),
|
|
52
|
-
build_smell_warning(smell_type: 'FeatureEnvy')
|
|
53
|
-
]
|
|
54
|
-
end
|
|
55
|
-
|
|
56
|
-
it_behaves_like 'no match'
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
context 'with 1 non-matching and 1 matching smell' do
|
|
60
|
-
let(:smells) do
|
|
61
|
-
[
|
|
62
|
-
build_smell_warning(smell_type: 'ControlParameter'),
|
|
63
|
-
build_smell_warning(smell_type: expected_smell_type.to_s,
|
|
64
|
-
message: "message mentioning #{expected_context_name}")
|
|
65
|
-
]
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
it_behaves_like 'no match'
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
context 'with 1 matching smell' do
|
|
72
|
-
let(:smells) do
|
|
73
|
-
[build_smell_warning(smell_type: expected_smell_type.to_s,
|
|
74
|
-
message: "message mentioning #{expected_context_name}")]
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
it 'matches' do
|
|
78
|
-
expect(matcher_matches).to be_truthy
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
it 'reports the expected smell when no match was expected' do
|
|
82
|
-
expect(matcher.failure_message_when_negated).to match(expected_smell_type.to_s)
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
it 'reports the source when no match was expected' do
|
|
86
|
-
source = 'the_path/to_a/source_file.rb'
|
|
87
|
-
allow(examiner).to receive(:origin).and_return(source)
|
|
88
|
-
expect(matcher.failure_message_when_negated).to match(source)
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
require_relative '../../spec_helper'
|
|
2
|
-
require_lib 'reek/spec'
|
|
3
|
-
|
|
4
|
-
RSpec.describe Reek::Spec::ShouldReek do
|
|
5
|
-
describe 'checking code in a string' do
|
|
6
|
-
let(:matcher) { described_class.new }
|
|
7
|
-
let(:clean_code) { 'def good() true; end' }
|
|
8
|
-
let(:smelly_code) { 'def x() y = 4; end' }
|
|
9
|
-
|
|
10
|
-
it 'matches a smelly String' do
|
|
11
|
-
expect(matcher).to be_matches(smelly_code)
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
it 'doesnt match a fragrant String' do
|
|
15
|
-
expect(matcher).not_to be_matches(clean_code)
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
it 'reports the smells when should_not fails' do
|
|
19
|
-
matcher.matches?(smelly_code)
|
|
20
|
-
expect(matcher.failure_message_when_negated).to match('UncommunicativeVariableName')
|
|
21
|
-
end
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
describe 'checking code in a File' do
|
|
25
|
-
context 'without masking' do
|
|
26
|
-
let(:matcher) { described_class.new }
|
|
27
|
-
|
|
28
|
-
it 'matches a smelly File' do
|
|
29
|
-
expect(matcher).to be_matches(SMELLY_FILE)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it 'doesnt match a fragrant File' do
|
|
33
|
-
expect(matcher).not_to be_matches(CLEAN_FILE)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
it 'reports the smells when should_not fails' do
|
|
37
|
-
matcher.matches?(SMELLY_FILE)
|
|
38
|
-
expect(matcher.failure_message_when_negated).to match('UncommunicativeMethodName')
|
|
39
|
-
end
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
context 'with masking' do
|
|
43
|
-
let(:path) { CONFIGURATION_DIR.join('full_mask.reek') }
|
|
44
|
-
let(:configuration) { test_configuration_for(path) }
|
|
45
|
-
let(:matcher) { described_class.new(configuration: configuration) }
|
|
46
|
-
|
|
47
|
-
it 'masks smells using the relevant configuration' do
|
|
48
|
-
expect(matcher).not_to be_matches(SMELLY_FILE)
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
end
|
|
52
|
-
end
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
require_relative '../../spec_helper'
|
|
2
|
-
require_lib 'reek/spec/smell_matcher'
|
|
3
|
-
|
|
4
|
-
RSpec.describe Reek::Spec::SmellMatcher do
|
|
5
|
-
let(:smell_warning) do
|
|
6
|
-
build_smell_warning(smell_type: 'UncommunicativeVariableName',
|
|
7
|
-
message: "has the variable name '@s'",
|
|
8
|
-
parameters: { test: 'something' })
|
|
9
|
-
end
|
|
10
|
-
let(:matcher) { described_class.new(smell_warning) }
|
|
11
|
-
|
|
12
|
-
describe '#matches?' do
|
|
13
|
-
it 'matches on class symbol' do
|
|
14
|
-
expect(matcher).to be_matches(:UncommunicativeVariableName)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
it 'matches on class symbol and params' do
|
|
18
|
-
expect(matcher).to be_matches(:UncommunicativeVariableName,
|
|
19
|
-
test: 'something')
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
it 'matches on class symbol, params and attributes' do
|
|
23
|
-
expect(matcher).to be_matches(:UncommunicativeVariableName,
|
|
24
|
-
test: 'something',
|
|
25
|
-
message: "has the variable name '@s'")
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
it 'does not match on different class symbol' do
|
|
29
|
-
expect(matcher).not_to be_matches(:FeatureEnvy)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
it 'does not match on different params' do
|
|
33
|
-
expect(matcher).not_to be_matches(:UncommunicativeVariableName,
|
|
34
|
-
test: 'something else')
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
it 'does not match on different attributes' do
|
|
38
|
-
expect(matcher).not_to be_matches(:UncommunicativeVariableName,
|
|
39
|
-
test: 'something',
|
|
40
|
-
message: 'nothing')
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
it 'raises error on uncomparable attribute' do
|
|
44
|
-
expect do
|
|
45
|
-
matcher.matches?(:UncommunicativeVariableName,
|
|
46
|
-
test: 'something',
|
|
47
|
-
random: 'nothing')
|
|
48
|
-
end.to raise_error("The attribute 'random' is not available for comparison")
|
|
49
|
-
end
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
describe '#matches_smell_type?' do
|
|
53
|
-
it 'matches on class symbol' do
|
|
54
|
-
expect(matcher).to be_matches_smell_type(:UncommunicativeVariableName)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
it 'does not match on different class symbol' do
|
|
58
|
-
expect(matcher).not_to be_matches_smell_type(:FeatureEnvy)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
describe '#matches_attributes?' do
|
|
63
|
-
it 'matches on params' do
|
|
64
|
-
expect(matcher).to be_matches_attributes(test: 'something')
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
it 'matches on class symbol, params and attributes' do
|
|
68
|
-
expect(matcher).to be_matches_attributes(test: 'something',
|
|
69
|
-
message: "has the variable name '@s'")
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
it 'does not match on different params' do
|
|
73
|
-
expect(matcher).not_to be_matches_attributes(test: 'something else')
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
it 'does not match on different attributes' do
|
|
77
|
-
expect(matcher).not_to be_matches_attributes(test: 'something',
|
|
78
|
-
message: 'nothing')
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
it 'raises error on uncomparable attribute' do
|
|
82
|
-
expect do
|
|
83
|
-
matcher.matches_attributes? test: 'something', random: 'nothing'
|
|
84
|
-
end.to raise_error("The attribute 'random' is not available for comparison")
|
|
85
|
-
end
|
|
86
|
-
end
|
|
87
|
-
end
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
require_relative '../spec_helper'
|
|
2
|
-
Reek::CLI::Silencer.without_warnings { require 'parser/ruby25' }
|
|
3
|
-
require_lib 'reek/tree_dresser'
|
|
4
|
-
|
|
5
|
-
RSpec.describe Reek::TreeDresser do
|
|
6
|
-
describe '#dress' do
|
|
7
|
-
let(:dresser) { described_class.new }
|
|
8
|
-
let(:sexp) do
|
|
9
|
-
Parser::Ruby25.parse('class Klazz; def meth(argument); argument.call_me; end; end')
|
|
10
|
-
end
|
|
11
|
-
let(:dressed_ast) { dresser.dress(sexp, {}) }
|
|
12
|
-
|
|
13
|
-
# The dressed AST looks like this:
|
|
14
|
-
# (class
|
|
15
|
-
# (const nil :Klazz) nil
|
|
16
|
-
# (def :meth
|
|
17
|
-
# (args
|
|
18
|
-
# (arg :argument))
|
|
19
|
-
# (send
|
|
20
|
-
# (lvar :argument) :call_me)))
|
|
21
|
-
let(:const_node) { dressed_ast.children.first }
|
|
22
|
-
let(:def_node) { dressed_ast.children.last }
|
|
23
|
-
let(:args_node) { def_node.children[1] }
|
|
24
|
-
let(:send_node) { def_node.children[2] }
|
|
25
|
-
|
|
26
|
-
it 'dresses `const` nodes properly' do
|
|
27
|
-
expect(const_node).to be_a Reek::AST::SexpExtensions::ConstNode
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
it 'dresses `def` nodes properly' do
|
|
31
|
-
expect(def_node).
|
|
32
|
-
to be_a(Reek::AST::SexpExtensions::DefNode).
|
|
33
|
-
and be_a(Reek::AST::SexpExtensions::MethodNodeBase)
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
it 'dresses `args` nodes properly' do
|
|
37
|
-
expect(args_node).
|
|
38
|
-
to be_a(Reek::AST::SexpExtensions::ArgsNode).
|
|
39
|
-
and be_a(Reek::AST::SexpExtensions::NestedAssignables)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
it 'dresses `send` nodes properly' do
|
|
43
|
-
expect(send_node).to be_a Reek::AST::SexpExtensions::SendNode
|
|
44
|
-
end
|
|
45
|
-
end
|
|
46
|
-
end
|
data/spec/spec_helper.rb
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
require 'pathname'
|
|
2
|
-
require 'timeout'
|
|
3
|
-
require 'rspec-benchmark'
|
|
4
|
-
require_relative '../lib/reek'
|
|
5
|
-
require_relative '../lib/reek/spec'
|
|
6
|
-
require_relative '../lib/reek/ast/ast_node_class_map'
|
|
7
|
-
require_relative '../lib/reek/configuration/app_configuration'
|
|
8
|
-
|
|
9
|
-
require_relative '../samples/paths'
|
|
10
|
-
|
|
11
|
-
begin
|
|
12
|
-
Reek::CLI::Silencer.without_warnings { require 'pry-byebug' }
|
|
13
|
-
rescue LoadError # rubocop:disable Lint/SuppressedException
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
# Simple helpers for our specs.
|
|
17
|
-
module Helpers
|
|
18
|
-
def test_configuration_for(config)
|
|
19
|
-
case config
|
|
20
|
-
when Pathname
|
|
21
|
-
configuration = Reek::Configuration::AppConfiguration.from_path(config)
|
|
22
|
-
when Hash
|
|
23
|
-
configuration = Reek::Configuration::AppConfiguration.from_hash config
|
|
24
|
-
else
|
|
25
|
-
raise "Unknown config given in `test_configuration_for`: #{config.inspect}"
|
|
26
|
-
end
|
|
27
|
-
configuration
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# @param code [String] The given code.
|
|
31
|
-
#
|
|
32
|
-
# @return syntax_tree [Reek::AST::Node]
|
|
33
|
-
def syntax_tree(code)
|
|
34
|
-
Reek::Source::SourceCode.from(code).syntax_tree
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# @param code [String] The given code.
|
|
38
|
-
#
|
|
39
|
-
# @return syntax_tree [Reek::Context::CodeContext]
|
|
40
|
-
def code_context(code)
|
|
41
|
-
Reek::Context::CodeContext.new(nil, syntax_tree(code))
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
# @param code [String] The given code.
|
|
45
|
-
#
|
|
46
|
-
# @return syntax_tree [Reek::Context::MethodContext]
|
|
47
|
-
def method_context(code)
|
|
48
|
-
Reek::Context::MethodContext.new(nil, syntax_tree(code))
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# Helper methods to generate a configuration for smell types that support
|
|
52
|
-
# `accept` and `reject` settings.
|
|
53
|
-
%w(accept reject).each do |switch|
|
|
54
|
-
define_method("#{switch}_configuration_for") do |smell_type, pattern:|
|
|
55
|
-
hash = {
|
|
56
|
-
smell_type => {
|
|
57
|
-
switch => pattern
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
Reek::Configuration::AppConfiguration.from_hash(hash)
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
|
|
64
|
-
# :reek:UncommunicativeMethodName
|
|
65
|
-
def sexp(type, *children)
|
|
66
|
-
@klass_map ||= Reek::AST::ASTNodeClassMap.new
|
|
67
|
-
@klass_map.klass_for(type).new(type, children)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
def build_smell_warning(smell_type: 'FeatureEnvy',
|
|
71
|
-
context: 'self',
|
|
72
|
-
lines: [42],
|
|
73
|
-
message: 'smell warning message',
|
|
74
|
-
source: 'dummy_file',
|
|
75
|
-
parameters: {})
|
|
76
|
-
Reek::SmellWarning.new(smell_type,
|
|
77
|
-
context: context,
|
|
78
|
-
lines: lines,
|
|
79
|
-
message: message,
|
|
80
|
-
source: source,
|
|
81
|
-
parameters: parameters)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def build_code_comment(comment: '', line: 1, source: 'string')
|
|
85
|
-
Reek::CodeComment.new(comment: comment, line: line, source: source)
|
|
86
|
-
end
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
RSpec.configure do |config|
|
|
90
|
-
config.filter_run :focus
|
|
91
|
-
config.run_all_when_everything_filtered = true
|
|
92
|
-
config.include Helpers
|
|
93
|
-
config.include RSpec::Benchmark::Matchers
|
|
94
|
-
config.example_status_persistence_file_path = 'spec/examples.txt'
|
|
95
|
-
|
|
96
|
-
config.disable_monkey_patching!
|
|
97
|
-
|
|
98
|
-
config.mock_with :rspec do |mocks|
|
|
99
|
-
mocks.verify_partial_doubles = true
|
|
100
|
-
mocks.verify_doubled_constant_names = true
|
|
101
|
-
end
|
|
102
|
-
end
|
|
103
|
-
|
|
104
|
-
RSpec::Matchers.define_negated_matcher :not_reek_of, :reek_of
|
|
105
|
-
|
|
106
|
-
private
|
|
107
|
-
|
|
108
|
-
def require_lib(path)
|
|
109
|
-
require_relative "../lib/#{path}"
|
|
110
|
-
end
|
data/tasks/configuration.rake
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
require_relative '../lib/reek'
|
|
2
|
-
require_relative '../lib/reek/detector_repository'
|
|
3
|
-
require_relative '../lib/reek/configuration/rake_task_converter'
|
|
4
|
-
require_relative '../lib/reek/configuration/app_configuration'
|
|
5
|
-
|
|
6
|
-
require 'yaml'
|
|
7
|
-
|
|
8
|
-
namespace :configuration do
|
|
9
|
-
desc 'Updates the default configuration file when smell defaults change'
|
|
10
|
-
task :update_default_configuration do
|
|
11
|
-
content = Reek::DetectorRepository.smell_types.each_with_object({}) do |klass, hash|
|
|
12
|
-
hash[klass.smell_type] = Reek::Configuration::RakeTaskConverter.convert klass.default_config
|
|
13
|
-
end
|
|
14
|
-
File.open(Reek::DEFAULT_SMELL_CONFIGURATION, 'w') do |file|
|
|
15
|
-
YAML.dump({ Reek::DETECTORS_KEY => content }, file)
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
data/tasks/console.rake
DELETED
data/tasks/reek.rake
DELETED
data/tasks/rubocop.rake
DELETED
data/tasks/test.rake
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
require 'cucumber/rake/task'
|
|
2
|
-
require 'rspec/core/rake_task'
|
|
3
|
-
|
|
4
|
-
namespace 'test' do
|
|
5
|
-
RSpec::Core::RakeTask.new('spec') do |t|
|
|
6
|
-
t.pattern = 'spec/reek/**/*_spec.rb'
|
|
7
|
-
t.ruby_opts = ['-rbundler/setup -rsimplecov -Ilib -w']
|
|
8
|
-
end
|
|
9
|
-
|
|
10
|
-
RSpec::Core::RakeTask.new('performance') do |t|
|
|
11
|
-
t.pattern = 'spec/performance/**/*_spec.rb'
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
desc 'Tests code quality'
|
|
15
|
-
RSpec::Core::RakeTask.new('quality') do |t|
|
|
16
|
-
t.pattern = 'spec/quality/**/*_spec.rb'
|
|
17
|
-
t.ruby_opts = ['-rbundler/setup -Ilib']
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
Cucumber::Rake::Task.new(:features) do |t|
|
|
21
|
-
t.cucumber_opts = 'features --format progress --color'
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
desc 'Runs all unit tests and acceptance tests'
|
|
25
|
-
task 'all' => ['test:spec', 'test:features']
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
desc 'Synonym for test:spec'
|
|
29
|
-
task 'spec' => 'test:spec'
|
|
30
|
-
|
|
31
|
-
desc 'Synonym for test:all'
|
|
32
|
-
task 'test' => 'test:all'
|