rubocop-rspec 1.7.0 → 3.0.2
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 +5 -5
- data/CHANGELOG.md +955 -79
- data/CODE_OF_CONDUCT.md +17 -0
- data/MIT-LICENSE.md +1 -2
- data/README.md +35 -35
- data/config/default.yml +940 -52
- data/config/obsoletion.yml +30 -0
- data/lib/rubocop/cop/rspec/align_left_let_brace.rb +49 -0
- data/lib/rubocop/cop/rspec/align_right_let_brace.rb +49 -0
- data/lib/rubocop/cop/rspec/any_instance.rb +10 -13
- data/lib/rubocop/cop/rspec/around_block.rb +97 -0
- data/lib/rubocop/cop/rspec/base.rb +26 -0
- data/lib/rubocop/cop/rspec/be.rb +39 -0
- data/lib/rubocop/cop/rspec/be_empty.rb +45 -0
- data/lib/rubocop/cop/rspec/be_eq.rb +47 -0
- data/lib/rubocop/cop/rspec/be_eql.rb +18 -15
- data/lib/rubocop/cop/rspec/be_nil.rb +74 -0
- data/lib/rubocop/cop/rspec/before_after_all.rb +45 -0
- data/lib/rubocop/cop/rspec/change_by_zero.rb +184 -0
- data/lib/rubocop/cop/rspec/class_check.rb +101 -0
- data/lib/rubocop/cop/rspec/contain_exactly.rb +56 -0
- data/lib/rubocop/cop/rspec/context_method.rb +57 -0
- data/lib/rubocop/cop/rspec/context_wording.rb +117 -0
- data/lib/rubocop/cop/rspec/describe_class.rb +52 -21
- data/lib/rubocop/cop/rspec/describe_method.rb +26 -11
- data/lib/rubocop/cop/rspec/describe_symbol.rb +37 -0
- data/lib/rubocop/cop/rspec/described_class.rb +181 -34
- data/lib/rubocop/cop/rspec/described_class_module_wrapping.rb +38 -0
- data/lib/rubocop/cop/rspec/dialect.rb +84 -0
- data/lib/rubocop/cop/rspec/duplicated_metadata.rb +58 -0
- data/lib/rubocop/cop/rspec/empty_example_group.rb +134 -47
- data/lib/rubocop/cop/rspec/empty_hook.rb +49 -0
- data/lib/rubocop/cop/rspec/empty_line_after_example.rb +82 -0
- data/lib/rubocop/cop/rspec/empty_line_after_example_group.rb +42 -0
- data/lib/rubocop/cop/rspec/empty_line_after_final_let.rb +40 -0
- data/lib/rubocop/cop/rspec/empty_line_after_hook.rb +82 -0
- data/lib/rubocop/cop/rspec/empty_line_after_subject.rb +36 -0
- data/lib/rubocop/cop/rspec/empty_metadata.rb +46 -0
- data/lib/rubocop/cop/rspec/empty_output.rb +47 -0
- data/lib/rubocop/cop/rspec/eq.rb +47 -0
- data/lib/rubocop/cop/rspec/example_length.rb +38 -20
- data/lib/rubocop/cop/rspec/example_without_description.rb +98 -0
- data/lib/rubocop/cop/rspec/example_wording.rb +117 -27
- data/lib/rubocop/cop/rspec/excessive_docstring_spacing.rb +110 -0
- data/lib/rubocop/cop/rspec/expect_actual.rb +46 -20
- data/lib/rubocop/cop/rspec/expect_change.rb +86 -0
- data/lib/rubocop/cop/rspec/expect_in_hook.rb +50 -0
- data/lib/rubocop/cop/rspec/expect_in_let.rb +42 -0
- data/lib/rubocop/cop/rspec/expect_output.rb +50 -0
- data/lib/rubocop/cop/rspec/focus.rb +79 -25
- data/lib/rubocop/cop/rspec/hook_argument.rb +48 -36
- data/lib/rubocop/cop/rspec/hooks_before_examples.rb +81 -0
- data/lib/rubocop/cop/rspec/identical_equality_assertion.rb +37 -0
- data/lib/rubocop/cop/rspec/implicit_block_expectation.rb +68 -0
- data/lib/rubocop/cop/rspec/implicit_expect.rb +100 -0
- data/lib/rubocop/cop/rspec/implicit_subject.rb +167 -0
- data/lib/rubocop/cop/rspec/indexed_let.rb +112 -0
- data/lib/rubocop/cop/rspec/instance_spy.rb +74 -0
- data/lib/rubocop/cop/rspec/instance_variable.rb +28 -14
- data/lib/rubocop/cop/rspec/is_expected_specify.rb +45 -0
- data/lib/rubocop/cop/rspec/it_behaves_like.rb +49 -0
- data/lib/rubocop/cop/rspec/iterated_expectation.rb +74 -0
- data/lib/rubocop/cop/rspec/leading_subject.rb +57 -29
- data/lib/rubocop/cop/rspec/leaky_constant_declaration.rb +127 -0
- data/lib/rubocop/cop/rspec/let_before_examples.rb +101 -0
- data/lib/rubocop/cop/rspec/let_setup.rb +32 -16
- data/lib/rubocop/cop/rspec/match_array.rb +59 -0
- data/lib/rubocop/cop/rspec/message_chain.rb +10 -15
- data/lib/rubocop/cop/rspec/message_expectation.rb +12 -9
- data/lib/rubocop/cop/rspec/message_spies.rb +88 -0
- data/lib/rubocop/cop/rspec/metadata_style.rb +202 -0
- data/lib/rubocop/cop/rspec/missing_example_group_argument.rb +35 -0
- data/lib/rubocop/cop/rspec/missing_expectation_target_method.rb +54 -0
- data/lib/rubocop/cop/rspec/mixin/comments_help.rb +38 -0
- data/lib/rubocop/cop/rspec/mixin/empty_line_separation.rb +59 -0
- data/lib/rubocop/cop/rspec/mixin/file_help.rb +14 -0
- data/lib/rubocop/cop/rspec/mixin/final_end_location.rb +19 -0
- data/lib/rubocop/cop/rspec/mixin/inside_example_group.rb +29 -0
- data/lib/rubocop/cop/rspec/mixin/location_help.rb +37 -0
- data/lib/rubocop/cop/rspec/mixin/metadata.rb +63 -0
- data/lib/rubocop/cop/rspec/mixin/namespace.rb +23 -0
- data/lib/rubocop/cop/rspec/mixin/skip_or_pending.rb +39 -0
- data/lib/rubocop/cop/rspec/mixin/top_level_group.rb +54 -0
- data/lib/rubocop/cop/rspec/mixin/variable.rb +21 -0
- data/lib/rubocop/cop/rspec/multiple_describes.rb +14 -12
- data/lib/rubocop/cop/rspec/multiple_expectations.rb +86 -26
- data/lib/rubocop/cop/rspec/multiple_memoized_helpers.rb +146 -0
- data/lib/rubocop/cop/rspec/multiple_subjects.rb +97 -0
- data/lib/rubocop/cop/rspec/named_subject.rb +107 -27
- data/lib/rubocop/cop/rspec/nested_groups.rb +84 -47
- data/lib/rubocop/cop/rspec/no_expectation_example.rb +102 -0
- data/lib/rubocop/cop/rspec/not_to_not.rb +30 -27
- data/lib/rubocop/cop/rspec/overwriting_setup.rb +74 -0
- data/lib/rubocop/cop/rspec/pending.rb +80 -0
- data/lib/rubocop/cop/rspec/pending_without_reason.rb +159 -0
- data/lib/rubocop/cop/rspec/predicate_matcher.rb +341 -0
- data/lib/rubocop/cop/rspec/receive_counts.rb +89 -0
- data/lib/rubocop/cop/rspec/receive_messages.rb +161 -0
- data/lib/rubocop/cop/rspec/receive_never.rb +41 -0
- data/lib/rubocop/cop/rspec/redundant_around.rb +65 -0
- data/lib/rubocop/cop/rspec/redundant_predicate_matcher.rb +67 -0
- data/lib/rubocop/cop/rspec/remove_const.rb +39 -0
- data/lib/rubocop/cop/rspec/repeated_description.rb +98 -0
- data/lib/rubocop/cop/rspec/repeated_example.rb +53 -0
- data/lib/rubocop/cop/rspec/repeated_example_group_body.rb +100 -0
- data/lib/rubocop/cop/rspec/repeated_example_group_description.rb +96 -0
- data/lib/rubocop/cop/rspec/repeated_include_example.rb +105 -0
- data/lib/rubocop/cop/rspec/repeated_subject_call.rb +125 -0
- data/lib/rubocop/cop/rspec/return_from_stub.rb +169 -0
- data/lib/rubocop/cop/rspec/scattered_let.rb +59 -0
- data/lib/rubocop/cop/rspec/scattered_setup.rb +92 -0
- data/lib/rubocop/cop/rspec/shared_context.rb +107 -0
- data/lib/rubocop/cop/rspec/shared_examples.rb +125 -0
- data/lib/rubocop/cop/rspec/single_argument_message_chain.rb +93 -0
- data/lib/rubocop/cop/rspec/skip_block_inside_example.rb +46 -0
- data/lib/rubocop/cop/rspec/sort_metadata.rb +71 -0
- data/lib/rubocop/cop/rspec/spec_file_path_format.rb +133 -0
- data/lib/rubocop/cop/rspec/spec_file_path_suffix.rb +40 -0
- data/lib/rubocop/cop/rspec/stubbed_mock.rb +176 -0
- data/lib/rubocop/cop/rspec/subject_declaration.rb +46 -0
- data/lib/rubocop/cop/rspec/subject_stub.rb +93 -74
- data/lib/rubocop/cop/rspec/undescriptive_literals_description.rb +69 -0
- data/lib/rubocop/cop/rspec/unspecified_exception.rb +67 -0
- data/lib/rubocop/cop/rspec/variable_definition.rb +77 -0
- data/lib/rubocop/cop/rspec/variable_name.rb +68 -0
- data/lib/rubocop/cop/rspec/verified_double_reference.rb +111 -0
- data/lib/rubocop/cop/rspec/verified_doubles.rb +28 -14
- data/lib/rubocop/cop/rspec/void_expect.rb +60 -0
- data/lib/rubocop/cop/rspec/yield.rb +82 -0
- data/lib/rubocop/cop/rspec_cops.rb +112 -0
- data/lib/rubocop/rspec/align_let_brace.rb +63 -0
- data/lib/rubocop/rspec/concept.rb +33 -0
- data/lib/rubocop/rspec/config_formatter.rb +27 -4
- data/lib/rubocop/rspec/cop/generator.rb +25 -0
- data/lib/rubocop/rspec/corrector/move_node.rb +51 -0
- data/lib/rubocop/rspec/description_extractor.rb +60 -18
- data/lib/rubocop/rspec/example.rb +37 -0
- data/lib/rubocop/rspec/example_group.rb +67 -0
- data/lib/rubocop/rspec/hook.rb +79 -0
- data/lib/rubocop/rspec/inject.rb +3 -1
- data/lib/rubocop/rspec/language.rb +184 -41
- data/lib/rubocop/rspec/node.rb +19 -0
- data/lib/rubocop/rspec/shared_contexts/default_rspec_language_config_context.rb +29 -0
- data/lib/rubocop/rspec/version.rb +1 -1
- data/lib/rubocop/rspec/wording.rb +61 -19
- data/lib/rubocop/rspec.rb +6 -2
- data/lib/rubocop-rspec.rb +45 -34
- metadata +130 -195
- data/Gemfile +0 -13
- data/Rakefile +0 -48
- data/lib/rubocop/cop/rspec/file_path.rb +0 -83
- data/lib/rubocop/rspec/language/node_pattern.rb +0 -16
- data/lib/rubocop/rspec/spec_only.rb +0 -61
- data/lib/rubocop/rspec/top_level_describe.rb +0 -61
- data/lib/rubocop/rspec/util.rb +0 -19
- data/rubocop-rspec.gemspec +0 -42
- data/spec/expect_violation/expectation_spec.rb +0 -85
- data/spec/project/changelog_spec.rb +0 -81
- data/spec/project/default_config_spec.rb +0 -52
- data/spec/project/project_requires_spec.rb +0 -8
- data/spec/rubocop/cop/rspec/any_instance_spec.rb +0 -30
- data/spec/rubocop/cop/rspec/be_eql_spec.rb +0 -59
- data/spec/rubocop/cop/rspec/describe_class_spec.rb +0 -113
- data/spec/rubocop/cop/rspec/describe_method_spec.rb +0 -32
- data/spec/rubocop/cop/rspec/described_class_spec.rb +0 -219
- data/spec/rubocop/cop/rspec/empty_example_group_spec.rb +0 -79
- data/spec/rubocop/cop/rspec/example_length_spec.rb +0 -117
- data/spec/rubocop/cop/rspec/example_wording_spec.rb +0 -82
- data/spec/rubocop/cop/rspec/expect_actual_spec.rb +0 -136
- data/spec/rubocop/cop/rspec/file_path_spec.rb +0 -236
- data/spec/rubocop/cop/rspec/focus_spec.rb +0 -130
- data/spec/rubocop/cop/rspec/hook_argument_spec.rb +0 -189
- data/spec/rubocop/cop/rspec/instance_variable_spec.rb +0 -75
- data/spec/rubocop/cop/rspec/leading_subject_spec.rb +0 -54
- data/spec/rubocop/cop/rspec/let_setup_spec.rb +0 -66
- data/spec/rubocop/cop/rspec/message_chain_spec.rb +0 -21
- data/spec/rubocop/cop/rspec/message_expectation_spec.rb +0 -63
- data/spec/rubocop/cop/rspec/multiple_describes_spec.rb +0 -28
- data/spec/rubocop/cop/rspec/multiple_expectations_spec.rb +0 -84
- data/spec/rubocop/cop/rspec/named_subject_spec.rb +0 -62
- data/spec/rubocop/cop/rspec/nested_groups_spec.rb +0 -55
- data/spec/rubocop/cop/rspec/not_to_not_spec.rb +0 -57
- data/spec/rubocop/cop/rspec/subject_stub_spec.rb +0 -183
- data/spec/rubocop/cop/rspec/verified_doubles_spec.rb +0 -71
- data/spec/rubocop/rspec/config_formatter_spec.rb +0 -48
- data/spec/rubocop/rspec/description_extractor_spec.rb +0 -35
- data/spec/rubocop/rspec/language/selector_set_spec.rb +0 -29
- data/spec/rubocop/rspec/spec_only_spec.rb +0 -97
- data/spec/rubocop/rspec/util/one_spec.rb +0 -21
- data/spec/rubocop/rspec/wording_spec.rb +0 -44
- data/spec/shared/rspec_only_cop_behavior.rb +0 -68
- data/spec/spec_helper.rb +0 -41
- data/spec/support/expect_violation.rb +0 -166
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'rspec/align_left_let_brace'
|
4
|
+
require_relative 'rspec/align_right_let_brace'
|
5
|
+
require_relative 'rspec/any_instance'
|
6
|
+
require_relative 'rspec/around_block'
|
7
|
+
require_relative 'rspec/be'
|
8
|
+
require_relative 'rspec/be_empty'
|
9
|
+
require_relative 'rspec/be_eq'
|
10
|
+
require_relative 'rspec/be_eql'
|
11
|
+
require_relative 'rspec/be_nil'
|
12
|
+
require_relative 'rspec/before_after_all'
|
13
|
+
require_relative 'rspec/change_by_zero'
|
14
|
+
require_relative 'rspec/class_check'
|
15
|
+
require_relative 'rspec/contain_exactly'
|
16
|
+
require_relative 'rspec/context_method'
|
17
|
+
require_relative 'rspec/context_wording'
|
18
|
+
require_relative 'rspec/describe_class'
|
19
|
+
require_relative 'rspec/describe_method'
|
20
|
+
require_relative 'rspec/describe_symbol'
|
21
|
+
require_relative 'rspec/described_class'
|
22
|
+
require_relative 'rspec/described_class_module_wrapping'
|
23
|
+
require_relative 'rspec/dialect'
|
24
|
+
require_relative 'rspec/duplicated_metadata'
|
25
|
+
require_relative 'rspec/empty_example_group'
|
26
|
+
require_relative 'rspec/empty_hook'
|
27
|
+
require_relative 'rspec/empty_line_after_example'
|
28
|
+
require_relative 'rspec/empty_line_after_example_group'
|
29
|
+
require_relative 'rspec/empty_line_after_final_let'
|
30
|
+
require_relative 'rspec/empty_line_after_hook'
|
31
|
+
require_relative 'rspec/empty_line_after_subject'
|
32
|
+
require_relative 'rspec/empty_metadata'
|
33
|
+
require_relative 'rspec/empty_output'
|
34
|
+
require_relative 'rspec/eq'
|
35
|
+
require_relative 'rspec/example_length'
|
36
|
+
require_relative 'rspec/example_without_description'
|
37
|
+
require_relative 'rspec/example_wording'
|
38
|
+
require_relative 'rspec/excessive_docstring_spacing'
|
39
|
+
require_relative 'rspec/expect_actual'
|
40
|
+
require_relative 'rspec/expect_change'
|
41
|
+
require_relative 'rspec/expect_in_hook'
|
42
|
+
require_relative 'rspec/expect_in_let'
|
43
|
+
require_relative 'rspec/expect_output'
|
44
|
+
require_relative 'rspec/focus'
|
45
|
+
require_relative 'rspec/hook_argument'
|
46
|
+
require_relative 'rspec/hooks_before_examples'
|
47
|
+
require_relative 'rspec/identical_equality_assertion'
|
48
|
+
require_relative 'rspec/implicit_block_expectation'
|
49
|
+
require_relative 'rspec/implicit_expect'
|
50
|
+
require_relative 'rspec/implicit_subject'
|
51
|
+
require_relative 'rspec/indexed_let'
|
52
|
+
require_relative 'rspec/instance_spy'
|
53
|
+
require_relative 'rspec/instance_variable'
|
54
|
+
require_relative 'rspec/is_expected_specify'
|
55
|
+
require_relative 'rspec/it_behaves_like'
|
56
|
+
require_relative 'rspec/iterated_expectation'
|
57
|
+
require_relative 'rspec/leading_subject'
|
58
|
+
require_relative 'rspec/leaky_constant_declaration'
|
59
|
+
require_relative 'rspec/let_before_examples'
|
60
|
+
require_relative 'rspec/let_setup'
|
61
|
+
require_relative 'rspec/match_array'
|
62
|
+
require_relative 'rspec/message_chain'
|
63
|
+
require_relative 'rspec/message_expectation'
|
64
|
+
require_relative 'rspec/message_spies'
|
65
|
+
require_relative 'rspec/metadata_style'
|
66
|
+
require_relative 'rspec/missing_example_group_argument'
|
67
|
+
require_relative 'rspec/missing_expectation_target_method'
|
68
|
+
require_relative 'rspec/multiple_describes'
|
69
|
+
require_relative 'rspec/multiple_expectations'
|
70
|
+
require_relative 'rspec/multiple_memoized_helpers'
|
71
|
+
require_relative 'rspec/multiple_subjects'
|
72
|
+
require_relative 'rspec/named_subject'
|
73
|
+
require_relative 'rspec/nested_groups'
|
74
|
+
require_relative 'rspec/no_expectation_example'
|
75
|
+
require_relative 'rspec/not_to_not'
|
76
|
+
require_relative 'rspec/overwriting_setup'
|
77
|
+
require_relative 'rspec/pending'
|
78
|
+
require_relative 'rspec/pending_without_reason'
|
79
|
+
require_relative 'rspec/predicate_matcher'
|
80
|
+
require_relative 'rspec/receive_counts'
|
81
|
+
require_relative 'rspec/receive_messages'
|
82
|
+
require_relative 'rspec/receive_never'
|
83
|
+
require_relative 'rspec/redundant_around'
|
84
|
+
require_relative 'rspec/redundant_predicate_matcher'
|
85
|
+
require_relative 'rspec/remove_const'
|
86
|
+
require_relative 'rspec/repeated_description'
|
87
|
+
require_relative 'rspec/repeated_example'
|
88
|
+
require_relative 'rspec/repeated_example_group_body'
|
89
|
+
require_relative 'rspec/repeated_example_group_description'
|
90
|
+
require_relative 'rspec/repeated_include_example'
|
91
|
+
require_relative 'rspec/repeated_subject_call'
|
92
|
+
require_relative 'rspec/return_from_stub'
|
93
|
+
require_relative 'rspec/scattered_let'
|
94
|
+
require_relative 'rspec/scattered_setup'
|
95
|
+
require_relative 'rspec/shared_context'
|
96
|
+
require_relative 'rspec/shared_examples'
|
97
|
+
require_relative 'rspec/single_argument_message_chain'
|
98
|
+
require_relative 'rspec/skip_block_inside_example'
|
99
|
+
require_relative 'rspec/sort_metadata'
|
100
|
+
require_relative 'rspec/spec_file_path_format'
|
101
|
+
require_relative 'rspec/spec_file_path_suffix'
|
102
|
+
require_relative 'rspec/stubbed_mock'
|
103
|
+
require_relative 'rspec/subject_declaration'
|
104
|
+
require_relative 'rspec/subject_stub'
|
105
|
+
require_relative 'rspec/undescriptive_literals_description'
|
106
|
+
require_relative 'rspec/unspecified_exception'
|
107
|
+
require_relative 'rspec/variable_definition'
|
108
|
+
require_relative 'rspec/variable_name'
|
109
|
+
require_relative 'rspec/verified_double_reference'
|
110
|
+
require_relative 'rspec/verified_doubles'
|
111
|
+
require_relative 'rspec/void_expect'
|
112
|
+
require_relative 'rspec/yield'
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module RSpec
|
5
|
+
# Shared behavior for aligning braces for single line lets
|
6
|
+
class AlignLetBrace
|
7
|
+
include RuboCop::RSpec::Language
|
8
|
+
include RuboCop::Cop::Util
|
9
|
+
|
10
|
+
def initialize(root, token)
|
11
|
+
@root = root
|
12
|
+
@token = token
|
13
|
+
end
|
14
|
+
|
15
|
+
def offending_tokens
|
16
|
+
single_line_lets.reject do |let|
|
17
|
+
target_column_for(let) == let_token(let).column
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def indent_for(node)
|
22
|
+
' ' * (target_column_for(node) - let_token(node).column)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def let_token(node)
|
28
|
+
node.loc.public_send(token)
|
29
|
+
end
|
30
|
+
|
31
|
+
def target_column_for(let)
|
32
|
+
let_group_for(let).map { |member| let_token(member).column }.max
|
33
|
+
end
|
34
|
+
|
35
|
+
def let_group_for(let)
|
36
|
+
adjacent_let_chunks.detect do |chunk|
|
37
|
+
chunk.any? do |member|
|
38
|
+
member == let && same_line?(member, let)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def adjacent_let_chunks
|
44
|
+
last_line = nil
|
45
|
+
|
46
|
+
single_line_lets.chunk do |node|
|
47
|
+
line = node.loc.line
|
48
|
+
last_line = (line if last_line.nil? || last_line + 1 == line)
|
49
|
+
last_line.nil?
|
50
|
+
end.map(&:last)
|
51
|
+
end
|
52
|
+
|
53
|
+
def single_line_lets
|
54
|
+
@single_line_lets ||=
|
55
|
+
root.each_node(:block).select do |node|
|
56
|
+
let?(node) && node.single_line?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_reader :root, :token
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module RSpec
|
5
|
+
# Wrapper for RSpec DSL methods
|
6
|
+
class Concept
|
7
|
+
extend RuboCop::NodePattern::Macros
|
8
|
+
include Language
|
9
|
+
|
10
|
+
def initialize(node)
|
11
|
+
@node = node
|
12
|
+
end
|
13
|
+
|
14
|
+
def eql?(other)
|
15
|
+
node == other.node
|
16
|
+
end
|
17
|
+
|
18
|
+
alias == eql?
|
19
|
+
|
20
|
+
def hash
|
21
|
+
[self.class, node].hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_node
|
25
|
+
node
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
attr_reader :node
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,10 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'yaml'
|
2
4
|
|
3
5
|
module RuboCop
|
4
6
|
module RSpec
|
5
7
|
# Builds a YAML config file from two config hashes
|
6
8
|
class ConfigFormatter
|
7
|
-
|
9
|
+
EXTENSION_ROOT_DEPARTMENT = %r{^(RSpec/)}.freeze
|
10
|
+
SUBDEPARTMENTS = [].freeze
|
11
|
+
AMENDMENTS = %(Metrics/BlockLength)
|
12
|
+
COP_DOC_BASE_URL = 'https://www.rubydoc.info/gems/rubocop-rspec/RuboCop/Cop/'
|
8
13
|
|
9
14
|
def initialize(config, descriptions)
|
10
15
|
@config = config
|
@@ -12,19 +17,37 @@ module RuboCop
|
|
12
17
|
end
|
13
18
|
|
14
19
|
def dump
|
15
|
-
YAML.dump(unified_config)
|
20
|
+
YAML.dump(unified_config)
|
21
|
+
.gsub(EXTENSION_ROOT_DEPARTMENT, "\n\\1")
|
22
|
+
.gsub(*AMENDMENTS, "\n\\0")
|
23
|
+
.gsub(/^(\s+)- /, '\1 - ')
|
24
|
+
.gsub('"~"', '~')
|
16
25
|
end
|
17
26
|
|
18
27
|
private
|
19
28
|
|
20
29
|
def unified_config
|
21
30
|
cops.each_with_object(config.dup) do |cop, unified|
|
22
|
-
|
31
|
+
next if SUBDEPARTMENTS.include?(cop) || AMENDMENTS.include?(cop)
|
32
|
+
|
33
|
+
replace_nil(unified[cop])
|
34
|
+
unified[cop].merge!(descriptions.fetch(cop))
|
35
|
+
unified[cop]['Reference'] = reference(cop)
|
23
36
|
end
|
24
37
|
end
|
25
38
|
|
26
39
|
def cops
|
27
|
-
(descriptions.keys
|
40
|
+
(descriptions.keys | config.keys).grep(EXTENSION_ROOT_DEPARTMENT)
|
41
|
+
end
|
42
|
+
|
43
|
+
def replace_nil(config)
|
44
|
+
config.each do |key, value|
|
45
|
+
config[key] = '~' if value.nil?
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def reference(cop)
|
50
|
+
COP_DOC_BASE_URL + cop
|
28
51
|
end
|
29
52
|
|
30
53
|
attr_reader :config, :descriptions
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module RSpec
|
5
|
+
module Cop
|
6
|
+
# Source and spec generator for new cops
|
7
|
+
#
|
8
|
+
# This generator will take a cop name and generate a source file
|
9
|
+
# and spec file when given a valid qualified cop name.
|
10
|
+
# @api private
|
11
|
+
class Generator < RuboCop::Cop::Generator
|
12
|
+
def todo
|
13
|
+
<<~TODO
|
14
|
+
Do 4 steps:
|
15
|
+
1. Modify the description of #{badge} in config/default.yml
|
16
|
+
2. Implement your new cop in the generated file!
|
17
|
+
3. Add an entry about new cop to CHANGELOG.md
|
18
|
+
4. Commit your new cop with a message such as
|
19
|
+
e.g. "Add new `#{badge}` cop"
|
20
|
+
TODO
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module RSpec
|
5
|
+
module Corrector
|
6
|
+
# Helper methods to move a node
|
7
|
+
class MoveNode
|
8
|
+
include RuboCop::Cop::RangeHelp
|
9
|
+
include RuboCop::Cop::RSpec::CommentsHelp
|
10
|
+
include RuboCop::Cop::RSpec::FinalEndLocation
|
11
|
+
|
12
|
+
attr_reader :original, :corrector, :processed_source
|
13
|
+
|
14
|
+
def initialize(node, corrector, processed_source)
|
15
|
+
@original = node
|
16
|
+
@corrector = corrector
|
17
|
+
@processed_source = processed_source # used by RangeHelp
|
18
|
+
end
|
19
|
+
|
20
|
+
def move_before(other)
|
21
|
+
position = start_line_position(other)
|
22
|
+
|
23
|
+
corrector.insert_before(position, "#{source(original)}\n")
|
24
|
+
corrector.remove(node_range_with_surrounding_space(original))
|
25
|
+
end
|
26
|
+
|
27
|
+
def move_after(other)
|
28
|
+
position = end_line_position(other)
|
29
|
+
|
30
|
+
corrector.insert_after(position, "\n#{source(original)}")
|
31
|
+
corrector.remove(node_range_with_surrounding_space(original))
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def source(node)
|
37
|
+
node_range(node).source
|
38
|
+
end
|
39
|
+
|
40
|
+
def node_range(node)
|
41
|
+
source_range_with_comment(node)
|
42
|
+
end
|
43
|
+
|
44
|
+
def node_range_with_surrounding_space(node)
|
45
|
+
range = node_range(node)
|
46
|
+
range_by_whole_lines(range, include_final_newline: true)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,35 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RuboCop
|
2
4
|
module RSpec
|
3
5
|
# Extracts cop descriptions from YARD docstrings
|
4
6
|
class DescriptionExtractor
|
5
|
-
COP_NAMESPACE = 'RuboCop::Cop::RSpec'.freeze
|
6
|
-
COP_FORMAT = 'RSpec/%s'.freeze
|
7
|
-
|
8
7
|
def initialize(yardocs)
|
9
|
-
@
|
8
|
+
@code_objects = yardocs.map(&CodeObject.public_method(:new))
|
10
9
|
end
|
11
10
|
|
12
11
|
def to_h
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
end
|
12
|
+
code_objects
|
13
|
+
.select(&:rspec_cop?)
|
14
|
+
.map(&:configuration)
|
15
|
+
.reduce(:merge)
|
18
16
|
end
|
19
17
|
|
20
18
|
private
|
21
19
|
|
22
|
-
|
23
|
-
yardocs
|
24
|
-
.select(&method(:cop?))
|
25
|
-
.map { |doc| [doc.name, doc.docstring] }
|
26
|
-
end
|
20
|
+
attr_reader :code_objects
|
27
21
|
|
28
|
-
|
29
|
-
|
30
|
-
|
22
|
+
# Decorator of a YARD code object for working with documented rspec cops
|
23
|
+
class CodeObject
|
24
|
+
RSPEC_COP_CLASS_NAME = 'RuboCop::Cop::RSpec::Base'
|
25
|
+
RUBOCOP_COP_CLASS_NAME = 'RuboCop::Cop::Base'
|
26
|
+
RSPEC_NAMESPACE = 'RuboCop::Cop::RSpec'
|
27
|
+
|
28
|
+
def initialize(yardoc)
|
29
|
+
@yardoc = yardoc
|
30
|
+
end
|
31
31
|
|
32
|
-
|
32
|
+
# Test if the YARD code object documents a concrete rspec cop class
|
33
|
+
#
|
34
|
+
# @return [Boolean]
|
35
|
+
def rspec_cop?
|
36
|
+
cop_subclass? && !abstract? && rspec_cop_namespace?
|
37
|
+
end
|
38
|
+
|
39
|
+
# Configuration for the documented cop that would live in default.yml
|
40
|
+
#
|
41
|
+
# @return [Hash]
|
42
|
+
def configuration
|
43
|
+
{ cop_name => { 'Description' => description } }
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def cop_name
|
49
|
+
Object.const_get(documented_constant).cop_name
|
50
|
+
end
|
51
|
+
|
52
|
+
def description
|
53
|
+
yardoc.docstring.split("\n\n").first.to_s
|
54
|
+
end
|
55
|
+
|
56
|
+
def rspec_cop_namespace?
|
57
|
+
documented_constant.start_with?(RSPEC_NAMESPACE)
|
58
|
+
end
|
59
|
+
|
60
|
+
def documented_constant
|
61
|
+
yardoc.to_s
|
62
|
+
end
|
63
|
+
|
64
|
+
def cop_subclass?
|
65
|
+
yardoc.superclass.path == RSPEC_COP_CLASS_NAME ||
|
66
|
+
yardoc.superclass.path == RUBOCOP_COP_CLASS_NAME
|
67
|
+
end
|
68
|
+
|
69
|
+
def abstract?
|
70
|
+
yardoc.tags.any? { |tag| tag.tag_name.eql?('abstract') }
|
71
|
+
end
|
72
|
+
|
73
|
+
attr_reader :yardoc
|
74
|
+
end
|
33
75
|
end
|
34
76
|
end
|
35
77
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module RSpec
|
5
|
+
# Wrapper for RSpec examples
|
6
|
+
class Example < Concept
|
7
|
+
# @!method extract_doc_string(node)
|
8
|
+
def_node_matcher :extract_doc_string, '(send _ _ $_ ...)'
|
9
|
+
|
10
|
+
# @!method extract_metadata(node)
|
11
|
+
def_node_matcher :extract_metadata, '(send _ _ _ $...)'
|
12
|
+
|
13
|
+
# @!method extract_implementation(node)
|
14
|
+
def_node_matcher :extract_implementation, '(block send args $_)'
|
15
|
+
|
16
|
+
def doc_string
|
17
|
+
extract_doc_string(definition)
|
18
|
+
end
|
19
|
+
|
20
|
+
def metadata
|
21
|
+
extract_metadata(definition)
|
22
|
+
end
|
23
|
+
|
24
|
+
def implementation
|
25
|
+
extract_implementation(node)
|
26
|
+
end
|
27
|
+
|
28
|
+
def definition
|
29
|
+
if node.send_type?
|
30
|
+
node
|
31
|
+
else
|
32
|
+
node.send_node
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module RSpec
|
5
|
+
# Wrapper for RSpec example groups
|
6
|
+
class ExampleGroup < Concept
|
7
|
+
# @!method scope_change?(node)
|
8
|
+
#
|
9
|
+
# Detect if the node is an example group or shared example
|
10
|
+
#
|
11
|
+
# Selectors which indicate that we should stop searching
|
12
|
+
#
|
13
|
+
def_node_matcher :scope_change?, <<~PATTERN
|
14
|
+
(block {
|
15
|
+
(send #rspec? {#SharedGroups.all #ExampleGroups.all} ...)
|
16
|
+
(send nil? #Includes.all ...)
|
17
|
+
} ...)
|
18
|
+
PATTERN
|
19
|
+
|
20
|
+
def lets
|
21
|
+
find_all_in_scope(node, :let?)
|
22
|
+
end
|
23
|
+
|
24
|
+
def subjects
|
25
|
+
find_all_in_scope(node, :subject?)
|
26
|
+
end
|
27
|
+
|
28
|
+
def examples
|
29
|
+
find_all_in_scope(node, :example?).map do |node|
|
30
|
+
Example.new(node)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def hooks
|
35
|
+
find_all_in_scope(node, :hook?).map do |node|
|
36
|
+
Hook.new(node)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
# Recursively search for predicate within the current scope
|
43
|
+
#
|
44
|
+
# Searches node and halts when a scope change is detected
|
45
|
+
#
|
46
|
+
# @param node [RuboCop::AST::Node] node to recursively search
|
47
|
+
# @param predicate [Symbol] method to call with node as argument
|
48
|
+
#
|
49
|
+
# @return [Array<RuboCop::AST::Node>] discovered nodes
|
50
|
+
def find_all_in_scope(node, predicate)
|
51
|
+
node.each_child_node.flat_map do |child|
|
52
|
+
find_all(child, predicate)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def find_all(node, predicate)
|
57
|
+
if public_send(predicate, node)
|
58
|
+
[node]
|
59
|
+
elsif scope_change?(node) || example?(node)
|
60
|
+
[]
|
61
|
+
else
|
62
|
+
find_all_in_scope(node, predicate)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module RSpec
|
5
|
+
# Wrapper for RSpec hook
|
6
|
+
class Hook < Concept
|
7
|
+
# @!method extract_metadata(node)
|
8
|
+
def_node_matcher :extract_metadata, <<~PATTERN
|
9
|
+
(block
|
10
|
+
(send _ _ #valid_scope? ? $...) ...
|
11
|
+
)
|
12
|
+
PATTERN
|
13
|
+
|
14
|
+
def name
|
15
|
+
node.method_name
|
16
|
+
end
|
17
|
+
|
18
|
+
def knowable_scope?
|
19
|
+
scope_argument.nil? ||
|
20
|
+
scope_argument.sym_type? ||
|
21
|
+
scope_argument.hash_type?
|
22
|
+
end
|
23
|
+
|
24
|
+
def example?
|
25
|
+
scope.equal?(:each)
|
26
|
+
end
|
27
|
+
|
28
|
+
def scope
|
29
|
+
return :each if scope_argument&.hash_type?
|
30
|
+
|
31
|
+
case scope_name
|
32
|
+
when nil, :each, :example then :each
|
33
|
+
when :context, :all then :context
|
34
|
+
when :suite then :suite
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def metadata
|
39
|
+
(extract_metadata(node) || [])
|
40
|
+
.map { |meta| transform_metadata(meta) }
|
41
|
+
.flatten
|
42
|
+
.inject(&:merge)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def valid_scope?(node)
|
48
|
+
node&.sym_type? && Language::HookScopes.all(node.value)
|
49
|
+
end
|
50
|
+
|
51
|
+
def transform_metadata(meta)
|
52
|
+
if meta.sym_type?
|
53
|
+
{ meta => true }
|
54
|
+
else
|
55
|
+
# This check is to be able to compare those two hooks:
|
56
|
+
#
|
57
|
+
# before(:example, :special) { ... }
|
58
|
+
# before(:example, special: true) { ... }
|
59
|
+
#
|
60
|
+
# In the second case it's a node with a pair that has a value
|
61
|
+
# of a `true_type?`.
|
62
|
+
meta.pairs.map { |pair| { pair.key => transform_true(pair.value) } }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def transform_true(node)
|
67
|
+
node.true_type? ? true : node
|
68
|
+
end
|
69
|
+
|
70
|
+
def scope_name
|
71
|
+
scope_argument.to_a.first
|
72
|
+
end
|
73
|
+
|
74
|
+
def scope_argument
|
75
|
+
node.send_node.first_argument
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
data/lib/rubocop/rspec/inject.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RuboCop
|
2
4
|
module RSpec
|
3
5
|
# Because RuboCop doesn't yet support plugins, we have to monkey patch in a
|
@@ -6,7 +8,7 @@ module RuboCop
|
|
6
8
|
def self.defaults!
|
7
9
|
path = CONFIG_DEFAULT.to_s
|
8
10
|
hash = ConfigLoader.send(:load_yaml_configuration, path)
|
9
|
-
config = Config.new(hash, path)
|
11
|
+
config = RuboCop::Config.new(hash, path)
|
10
12
|
puts "configuration from #{path}" if ConfigLoader.debug?
|
11
13
|
config = ConfigLoader.merge_with_default(config, path)
|
12
14
|
ConfigLoader.instance_variable_set(:@default_configuration, config)
|