rubocop 0.67.2 → 0.68.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.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +86 -233
  4. data/exe/rubocop +0 -12
  5. data/lib/rubocop.rb +13 -30
  6. data/lib/rubocop/ast/builder.rb +4 -0
  7. data/lib/rubocop/ast/node/alias_node.rb +24 -0
  8. data/lib/rubocop/ast/node/class_node.rb +31 -0
  9. data/lib/rubocop/ast/node/module_node.rb +24 -0
  10. data/lib/rubocop/ast/node/range_node.rb +7 -0
  11. data/lib/rubocop/ast/node/resbody_node.rb +12 -0
  12. data/lib/rubocop/ast/node/self_class_node.rb +24 -0
  13. data/lib/rubocop/cli.rb +40 -4
  14. data/lib/rubocop/config.rb +9 -7
  15. data/lib/rubocop/config_loader.rb +48 -7
  16. data/lib/rubocop/config_loader_resolver.rb +5 -4
  17. data/lib/rubocop/cop/commissioner.rb +24 -0
  18. data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +18 -6
  19. data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +12 -14
  20. data/lib/rubocop/cop/layout/access_modifier_indentation.rb +9 -20
  21. data/lib/rubocop/cop/layout/align_arguments.rb +93 -0
  22. data/lib/rubocop/cop/layout/align_parameters.rb +57 -33
  23. data/lib/rubocop/cop/layout/class_structure.rb +5 -5
  24. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +6 -8
  25. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +3 -6
  26. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +1 -2
  27. data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +1 -0
  28. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +292 -0
  29. data/lib/rubocop/cop/layout/{first_parameter_indentation.rb → indent_first_argument.rb} +11 -12
  30. data/lib/rubocop/cop/layout/{indent_array.rb → indent_first_array_element.rb} +2 -2
  31. data/lib/rubocop/cop/layout/{indent_hash.rb → indent_first_hash_element.rb} +2 -2
  32. data/lib/rubocop/cop/layout/indent_first_parameter.rb +96 -0
  33. data/lib/rubocop/cop/layout/indentation_width.rb +4 -16
  34. data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -4
  35. data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -16
  36. data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -2
  37. data/lib/rubocop/cop/lint/duplicate_methods.rb +6 -8
  38. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +4 -8
  39. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +157 -0
  40. data/lib/rubocop/cop/lint/inherit_exception.rb +3 -4
  41. data/lib/rubocop/cop/lint/literal_in_interpolation.rb +18 -1
  42. data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -5
  43. data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +25 -5
  44. data/lib/rubocop/cop/lint/useless_assignment.rb +2 -6
  45. data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -2
  46. data/lib/rubocop/cop/message_annotator.rb +1 -0
  47. data/lib/rubocop/cop/metrics/line_length.rb +139 -28
  48. data/lib/rubocop/cop/metrics/perceived_complexity.rb +3 -4
  49. data/lib/rubocop/cop/mixin/check_line_breakable.rb +190 -0
  50. data/lib/rubocop/cop/mixin/{array_hash_indentation.rb → multiline_element_indentation.rb} +3 -2
  51. data/lib/rubocop/cop/mixin/too_many_lines.rb +3 -7
  52. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +33 -4
  53. data/lib/rubocop/cop/rails/active_record_override.rb +23 -8
  54. data/lib/rubocop/cop/rails/delegate.rb +5 -8
  55. data/lib/rubocop/cop/rails/environment_comparison.rb +5 -3
  56. data/lib/rubocop/cop/rails/find_each.rb +1 -1
  57. data/lib/rubocop/cop/rails/redundant_allow_nil.rb +3 -3
  58. data/lib/rubocop/cop/rails/reflection_class_name.rb +1 -1
  59. data/lib/rubocop/cop/rails/skips_model_validations.rb +6 -7
  60. data/lib/rubocop/cop/rails/time_zone.rb +3 -10
  61. data/lib/rubocop/cop/rails/validation.rb +3 -0
  62. data/lib/rubocop/cop/registry.rb +3 -3
  63. data/lib/rubocop/cop/style/alias.rb +13 -7
  64. data/lib/rubocop/cop/style/block_delimiters.rb +20 -0
  65. data/lib/rubocop/cop/style/class_and_module_children.rb +19 -21
  66. data/lib/rubocop/cop/style/class_methods.rb +16 -24
  67. data/lib/rubocop/cop/style/conditional_assignment.rb +20 -49
  68. data/lib/rubocop/cop/style/documentation.rb +3 -7
  69. data/lib/rubocop/cop/style/format_string.rb +18 -21
  70. data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
  71. data/lib/rubocop/cop/style/inverse_methods.rb +4 -0
  72. data/lib/rubocop/cop/style/lambda.rb +12 -8
  73. data/lib/rubocop/cop/style/mixin_grouping.rb +8 -10
  74. data/lib/rubocop/cop/style/module_function.rb +2 -3
  75. data/lib/rubocop/cop/style/next.rb +10 -14
  76. data/lib/rubocop/cop/style/one_line_conditional.rb +5 -3
  77. data/lib/rubocop/cop/style/optional_arguments.rb +1 -4
  78. data/lib/rubocop/cop/style/random_with_offset.rb +44 -47
  79. data/lib/rubocop/cop/style/redundant_return.rb +6 -14
  80. data/lib/rubocop/cop/style/redundant_sort_by.rb +1 -1
  81. data/lib/rubocop/cop/style/safe_navigation.rb +3 -0
  82. data/lib/rubocop/cop/style/struct_inheritance.rb +2 -3
  83. data/lib/rubocop/cop/style/symbol_proc.rb +20 -40
  84. data/lib/rubocop/cop/style/unless_else.rb +1 -2
  85. data/lib/rubocop/cop/style/yoda_condition.rb +8 -7
  86. data/lib/rubocop/cop/util.rb +2 -4
  87. data/lib/rubocop/file_finder.rb +5 -10
  88. data/lib/rubocop/formatter/disabled_config_formatter.rb +5 -0
  89. data/lib/rubocop/node_pattern.rb +304 -170
  90. data/lib/rubocop/options.rb +4 -1
  91. data/lib/rubocop/rspec/shared_contexts.rb +3 -0
  92. data/lib/rubocop/version.rb +1 -1
  93. data/lib/rubocop/yaml_duplication_checker.rb +1 -1
  94. metadata +26 -50
  95. data/lib/rubocop/cop/performance/caller.rb +0 -69
  96. data/lib/rubocop/cop/performance/case_when_splat.rb +0 -177
  97. data/lib/rubocop/cop/performance/casecmp.rb +0 -108
  98. data/lib/rubocop/cop/performance/chain_array_allocation.rb +0 -78
  99. data/lib/rubocop/cop/performance/compare_with_block.rb +0 -122
  100. data/lib/rubocop/cop/performance/count.rb +0 -102
  101. data/lib/rubocop/cop/performance/detect.rb +0 -110
  102. data/lib/rubocop/cop/performance/double_start_end_with.rb +0 -94
  103. data/lib/rubocop/cop/performance/end_with.rb +0 -56
  104. data/lib/rubocop/cop/performance/fixed_size.rb +0 -97
  105. data/lib/rubocop/cop/performance/flat_map.rb +0 -78
  106. data/lib/rubocop/cop/performance/inefficient_hash_search.rb +0 -99
  107. data/lib/rubocop/cop/performance/open_struct.rb +0 -46
  108. data/lib/rubocop/cop/performance/range_include.rb +0 -50
  109. data/lib/rubocop/cop/performance/redundant_block_call.rb +0 -93
  110. data/lib/rubocop/cop/performance/redundant_match.rb +0 -56
  111. data/lib/rubocop/cop/performance/redundant_merge.rb +0 -183
  112. data/lib/rubocop/cop/performance/regexp_match.rb +0 -265
  113. data/lib/rubocop/cop/performance/reverse_each.rb +0 -42
  114. data/lib/rubocop/cop/performance/size.rb +0 -77
  115. data/lib/rubocop/cop/performance/start_with.rb +0 -59
  116. data/lib/rubocop/cop/performance/string_replacement.rb +0 -173
  117. data/lib/rubocop/cop/performance/times_map.rb +0 -71
  118. data/lib/rubocop/cop/performance/unfreeze_string.rb +0 -50
  119. data/lib/rubocop/cop/performance/uri_default_parser.rb +0 -47
@@ -1,42 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Performance
6
- # This cop is used to identify usages of `reverse.each` and
7
- # change them to use `reverse_each` instead.
8
- #
9
- # @example
10
- # # bad
11
- # [].reverse.each
12
- #
13
- # # good
14
- # [].reverse_each
15
- class ReverseEach < Cop
16
- include RangeHelp
17
-
18
- MSG = 'Use `reverse_each` instead of `reverse.each`.'.freeze
19
- UNDERSCORE = '_'.freeze
20
-
21
- def_node_matcher :reverse_each?, <<-MATCHER
22
- (send $(send _ :reverse) :each)
23
- MATCHER
24
-
25
- def on_send(node)
26
- reverse_each?(node) do |receiver|
27
- location_of_reverse = receiver.loc.selector.begin_pos
28
- end_location = node.loc.selector.end_pos
29
-
30
- range = range_between(location_of_reverse, end_location)
31
-
32
- add_offense(node, location: range)
33
- end
34
- end
35
-
36
- def autocorrect(node)
37
- ->(corrector) { corrector.replace(node.loc.dot, UNDERSCORE) }
38
- end
39
- end
40
- end
41
- end
42
- end
@@ -1,77 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Performance
6
- # This cop is used to identify usages of `count` on an
7
- # `Array` and `Hash` and change them to `size`.
8
- #
9
- # @example
10
- # # bad
11
- # [1, 2, 3].count
12
- #
13
- # # bad
14
- # {a: 1, b: 2, c: 3}.count
15
- #
16
- # # good
17
- # [1, 2, 3].size
18
- #
19
- # # good
20
- # {a: 1, b: 2, c: 3}.size
21
- #
22
- # # good
23
- # [1, 2, 3].count { |e| e > 2 }
24
- # TODO: Add advanced detection of variables that could
25
- # have been assigned to an array or a hash.
26
- class Size < Cop
27
- MSG = 'Use `size` instead of `count`.'.freeze
28
-
29
- def on_send(node)
30
- return unless eligible_node?(node)
31
-
32
- add_offense(node, location: :selector)
33
- end
34
-
35
- def autocorrect(node)
36
- ->(corrector) { corrector.replace(node.loc.selector, 'size') }
37
- end
38
-
39
- private
40
-
41
- def eligible_node?(node)
42
- return false unless node.method?(:count) && !node.arguments?
43
-
44
- eligible_receiver?(node.receiver) && !allowed_parent?(node.parent)
45
- end
46
-
47
- def eligible_receiver?(node)
48
- return false unless node
49
-
50
- array?(node) || hash?(node)
51
- end
52
-
53
- def allowed_parent?(node)
54
- node && node.block_type?
55
- end
56
-
57
- def array?(node)
58
- return true if node.array_type?
59
- return false unless node.send_type?
60
-
61
- _, constant = *node.receiver
62
-
63
- constant == :Array || node.method_name == :to_a
64
- end
65
-
66
- def hash?(node)
67
- return true if node.hash_type?
68
- return false unless node.send_type?
69
-
70
- _, constant = *node.receiver
71
-
72
- constant == :Hash || node.method_name == :to_h
73
- end
74
- end
75
- end
76
- end
77
- end
@@ -1,59 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Performance
6
- # This cop identifies unnecessary use of a regex where
7
- # `String#start_with?` would suffice.
8
- #
9
- # @example
10
- # # bad
11
- # 'abc'.match?(/\Aab/)
12
- # 'abc' =~ /\Aab/
13
- # 'abc'.match(/\Aab/)
14
- #
15
- # # good
16
- # 'abc'.start_with?('ab')
17
- class StartWith < Cop
18
- MSG = 'Use `String#start_with?` instead of a regex match anchored to ' \
19
- 'the beginning of the string.'.freeze
20
- SINGLE_QUOTE = "'".freeze
21
-
22
- def_node_matcher :redundant_regex?, <<-PATTERN
23
- {(send $!nil? {:match :=~ :match?} (regexp (str $#literal_at_start?) (regopt)))
24
- (send (regexp (str $#literal_at_start?) (regopt)) {:match :=~} $_)}
25
- PATTERN
26
-
27
- def literal_at_start?(regex_str)
28
- # is this regexp 'literal' in the sense of only matching literal
29
- # chars, rather than using metachars like `.` and `*` and so on?
30
- # also, is it anchored at the start of the string?
31
- # (tricky: \s, \d, and so on are metacharacters, but other characters
32
- # escaped with a slash are just literals. LITERAL_REGEX takes all
33
- # that into account.)
34
- regex_str =~ /\A\\A(?:#{LITERAL_REGEX})+\z/
35
- end
36
-
37
- def on_send(node)
38
- return unless redundant_regex?(node)
39
-
40
- add_offense(node)
41
- end
42
-
43
- def autocorrect(node)
44
- redundant_regex?(node) do |receiver, regex_str|
45
- receiver, regex_str = regex_str, receiver if receiver.is_a?(String)
46
- regex_str = regex_str[2..-1] # drop \A anchor
47
- regex_str = interpret_string_escapes(regex_str)
48
-
49
- lambda do |corrector|
50
- new_source = receiver.source + '.start_with?(' +
51
- to_string_literal(regex_str) + ')'
52
- corrector.replace(node.source_range, new_source)
53
- end
54
- end
55
- end
56
- end
57
- end
58
- end
59
- end
@@ -1,173 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Performance
6
- # This cop identifies places where `gsub` can be replaced by
7
- # `tr` or `delete`.
8
- #
9
- # @example
10
- # # bad
11
- # 'abc'.gsub('b', 'd')
12
- # 'abc'.gsub('a', '')
13
- # 'abc'.gsub(/a/, 'd')
14
- # 'abc'.gsub!('a', 'd')
15
- #
16
- # # good
17
- # 'abc'.gsub(/.*/, 'a')
18
- # 'abc'.gsub(/a+/, 'd')
19
- # 'abc'.tr('b', 'd')
20
- # 'a b c'.delete(' ')
21
- class StringReplacement < Cop
22
- include RangeHelp
23
-
24
- MSG = 'Use `%<prefer>s` instead of `%<current>s`.'.freeze
25
- DETERMINISTIC_REGEX = /\A(?:#{LITERAL_REGEX})+\Z/.freeze
26
- DELETE = 'delete'.freeze
27
- TR = 'tr'.freeze
28
- BANG = '!'.freeze
29
- SINGLE_QUOTE = "'".freeze
30
-
31
- def_node_matcher :string_replacement?, <<-PATTERN
32
- (send _ {:gsub :gsub!}
33
- ${regexp str (send (const nil? :Regexp) {:new :compile} _)}
34
- $str)
35
- PATTERN
36
-
37
- def on_send(node)
38
- string_replacement?(node) do |first_param, second_param|
39
- return if accept_second_param?(second_param)
40
- return if accept_first_param?(first_param)
41
-
42
- offense(node, first_param, second_param)
43
- end
44
- end
45
-
46
- def autocorrect(node)
47
- _string, _method, first_param, second_param = *node
48
- first_source, = first_source(first_param)
49
- second_source, = *second_param
50
-
51
- unless first_param.str_type?
52
- first_source = interpret_string_escapes(first_source)
53
- end
54
-
55
- replacement_method =
56
- replacement_method(node, first_source, second_source)
57
-
58
- replace_method(node, first_source, second_source, first_param,
59
- replacement_method)
60
- end
61
-
62
- def replace_method(node, first, second, first_param, replacement)
63
- lambda do |corrector|
64
- corrector.replace(node.loc.selector, replacement)
65
- unless first_param.str_type?
66
- corrector.replace(first_param.source_range,
67
- to_string_literal(first))
68
- end
69
-
70
- if second.empty? && first.length == 1
71
- remove_second_param(corrector, node, first_param)
72
- end
73
- end
74
- end
75
-
76
- private
77
-
78
- def accept_second_param?(second_param)
79
- second_source, = *second_param
80
- second_source.length > 1
81
- end
82
-
83
- def accept_first_param?(first_param)
84
- first_source, options = first_source(first_param)
85
- return true if first_source.nil?
86
-
87
- unless first_param.str_type?
88
- return true if options
89
- return true unless first_source =~ DETERMINISTIC_REGEX
90
-
91
- # This must be done after checking DETERMINISTIC_REGEX
92
- # Otherwise things like \s will trip us up
93
- first_source = interpret_string_escapes(first_source)
94
- end
95
-
96
- first_source.length != 1
97
- end
98
-
99
- def offense(node, first_param, second_param)
100
- first_source, = first_source(first_param)
101
- unless first_param.str_type?
102
- first_source = interpret_string_escapes(first_source)
103
- end
104
- second_source, = *second_param
105
- message = message(node, first_source, second_source)
106
-
107
- add_offense(node, location: range(node), message: message)
108
- end
109
-
110
- def first_source(first_param)
111
- case first_param.type
112
- when :regexp
113
- source_from_regex_literal(first_param)
114
- when :send
115
- source_from_regex_constructor(first_param)
116
- when :str
117
- first_param.children.first
118
- end
119
- end
120
-
121
- def source_from_regex_literal(node)
122
- regex, options = *node
123
- source, = *regex
124
- options, = *options
125
- [source, options]
126
- end
127
-
128
- def source_from_regex_constructor(node)
129
- _const, _init, regex = *node
130
- case regex.type
131
- when :regexp
132
- source_from_regex_literal(regex)
133
- when :str
134
- source, = *regex
135
- source
136
- end
137
- end
138
-
139
- def range(node)
140
- range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
141
- end
142
-
143
- def replacement_method(node, first_source, second_source)
144
- replacement = if second_source.empty? && first_source.length == 1
145
- DELETE
146
- else
147
- TR
148
- end
149
-
150
- "#{replacement}#{BANG if node.bang_method?}"
151
- end
152
-
153
- def message(node, first_source, second_source)
154
- replacement_method =
155
- replacement_method(node, first_source, second_source)
156
-
157
- format(MSG, prefer: replacement_method, current: node.method_name)
158
- end
159
-
160
- def method_suffix(node)
161
- node.loc.end ? node.loc.end.source : ''
162
- end
163
-
164
- def remove_second_param(corrector, node, first_param)
165
- end_range = range_between(first_param.source_range.end_pos,
166
- node.source_range.end_pos)
167
-
168
- corrector.replace(end_range, method_suffix(node))
169
- end
170
- end
171
- end
172
- end
173
- end
@@ -1,71 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Performance
6
- # This cop checks for .times.map calls.
7
- # In most cases such calls can be replaced
8
- # with an explicit array creation.
9
- #
10
- # @example
11
- # # bad
12
- # 9.times.map do |i|
13
- # i.to_s
14
- # end
15
- #
16
- # # good
17
- # Array.new(9) do |i|
18
- # i.to_s
19
- # end
20
- class TimesMap < Cop
21
- MESSAGE = 'Use `Array.new(%<count>s)` with a block ' \
22
- 'instead of `.times.%<map_or_collect>s`'.freeze
23
- MESSAGE_ONLY_IF = 'only if `%<count>s` is always 0 or more'.freeze
24
-
25
- def on_send(node)
26
- check(node)
27
- end
28
-
29
- def on_block(node)
30
- check(node)
31
- end
32
-
33
- def autocorrect(node)
34
- map_or_collect, count = times_map_call(node)
35
-
36
- replacement =
37
- "Array.new(#{count.source}" \
38
- "#{map_or_collect.arguments.map { |arg| ", #{arg.source}" }.join})"
39
-
40
- lambda do |corrector|
41
- corrector.replace(map_or_collect.loc.expression, replacement)
42
- end
43
- end
44
-
45
- private
46
-
47
- def check(node)
48
- times_map_call(node) do |map_or_collect, count|
49
- add_offense(node, message: message(map_or_collect, count))
50
- end
51
- end
52
-
53
- def message(map_or_collect, count)
54
- template = if count.literal?
55
- MESSAGE + '.'
56
- else
57
- "#{MESSAGE} #{MESSAGE_ONLY_IF}."
58
- end
59
- format(template,
60
- count: count.source,
61
- map_or_collect: map_or_collect.method_name)
62
- end
63
-
64
- def_node_matcher :times_map_call, <<-PATTERN
65
- {(block $(send (send $!nil? :times) {:map :collect}) ...)
66
- $(send (send $!nil? :times) {:map :collect} (block_pass ...))}
67
- PATTERN
68
- end
69
- end
70
- end
71
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- module Cop
5
- module Performance
6
- # In Ruby 2.3 or later, use unary plus operator to unfreeze a string
7
- # literal instead of `String#dup` and `String.new`.
8
- # Unary plus operator is faster than `String#dup`.
9
- #
10
- # Note: `String.new` (without operator) is not exactly the same as `+''`.
11
- # These differ in encoding. `String.new.encoding` is always `ASCII-8BIT`.
12
- # However, `(+'').encoding` is the same as script encoding(e.g. `UTF-8`).
13
- # So, if you expect `ASCII-8BIT` encoding, disable this cop.
14
- #
15
- # @example
16
- # # bad
17
- # ''.dup
18
- # "something".dup
19
- # String.new
20
- # String.new('')
21
- # String.new('something')
22
- #
23
- # # good
24
- # +'something'
25
- # +''
26
- class UnfreezeString < Cop
27
- extend TargetRubyVersion
28
-
29
- minimum_target_ruby_version 2.3
30
-
31
- MSG = 'Use unary plus to get an unfrozen string literal.'.freeze
32
-
33
- def_node_matcher :dup_string?, <<-PATTERN
34
- (send {str dstr} :dup)
35
- PATTERN
36
-
37
- def_node_matcher :string_new?, <<-PATTERN
38
- {
39
- (send (const nil? :String) :new {str dstr})
40
- (send (const nil? :String) :new)
41
- }
42
- PATTERN
43
-
44
- def on_send(node)
45
- add_offense(node) if dup_string?(node) || string_new?(node)
46
- end
47
- end
48
- end
49
- end
50
- end