rubocop 1.35.1 → 1.37.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/README.md +1 -1
- data/config/default.yml +32 -1
- data/lib/rubocop/arguments_env.rb +17 -0
- data/lib/rubocop/arguments_file.rb +17 -0
- data/lib/rubocop/cli/command/execute_runner.rb +7 -7
- data/lib/rubocop/cop/generator.rb +1 -2
- data/lib/rubocop/cop/layout/block_alignment.rb +14 -12
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/indentation_width.rb +4 -2
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +13 -9
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +25 -9
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +28 -3
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -2
- data/lib/rubocop/cop/lint/duplicate_magic_comment.rb +73 -0
- data/lib/rubocop/cop/lint/duplicate_methods.rb +11 -1
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +25 -6
- data/lib/rubocop/cop/lint/duplicate_require.rb +1 -1
- data/lib/rubocop/cop/lint/empty_class.rb +3 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +46 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +50 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +4 -5
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +12 -1
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +7 -0
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +29 -9
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +3 -2
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -11
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +17 -2
- data/lib/rubocop/cop/lint/unreachable_loop.rb +2 -2
- data/lib/rubocop/cop/lint/unused_method_argument.rb +4 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_methods.rb +10 -5
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +13 -5
- data/lib/rubocop/cop/mixin/comments_help.rb +12 -0
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +6 -3
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -5
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +6 -5
- data/lib/rubocop/cop/naming/inclusive_language.rb +1 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +97 -1
- data/lib/rubocop/cop/style/accessor_grouping.rb +7 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/case_equality.rb +40 -10
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_compact.rb +6 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +40 -5
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/endless_method.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +4 -0
- data/lib/rubocop/cop/style/format_string_token.rb +1 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +13 -2
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +7 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/operator_method_call.rb +39 -0
- data/lib/rubocop/cop/style/perl_backrefs.rb +22 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -2
- data/lib/rubocop/cop/style/redundant_initialize.rb +3 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +8 -1
- data/lib/rubocop/cop/style/redundant_string_escape.rb +173 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/static_class.rb +32 -1
- data/lib/rubocop/cop/style/symbol_array.rb +2 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +6 -5
- data/lib/rubocop/cop/style/word_array.rb +2 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +8 -2
- data/lib/rubocop/options.rb +13 -13
- data/lib/rubocop/rspec/shared_contexts.rb +13 -1
- data/lib/rubocop/runner.rb +4 -0
- data/lib/rubocop/server/cache.rb +5 -1
- data/lib/rubocop/server/cli.rb +9 -2
- data/lib/rubocop/server/client_command/exec.rb +5 -0
- data/lib/rubocop/server/core.rb +2 -1
- data/lib/rubocop/server/socket_reader.rb +5 -1
- data/lib/rubocop/server.rb +1 -1
- data/lib/rubocop/version.rb +8 -2
- data/lib/rubocop.rb +3 -0
- metadata +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e928a8547def9cafd9cddc36b5a407aef7d46fdf9825941c7906073492d88668
|
4
|
+
data.tar.gz: 3ef9727850f93815ba310b7c3a8cf74e53a0ee18a0fcf6731fd97a3640ffe28d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f57e5d25375fe47734a6e198924db74b341501762dc8f54277a888788ab821215c96847940cec1af4d90673fe79ab906b451bf25bec90f9c8c080e78efc01111
|
7
|
+
data.tar.gz: 69cafbca956eaa49887596d255f6888057ede94f3621349398de95da5c477201f7bee7eae074ab4750ce0131dcb26d6dfdc77c31f5fcb478d2fc25d5ca73e68c
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
53
53
|
in your `Gemfile`:
|
54
54
|
|
55
55
|
```rb
|
56
|
-
gem 'rubocop', '~> 1.
|
56
|
+
gem 'rubocop', '~> 1.37', require: false
|
57
57
|
```
|
58
58
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -1707,6 +1707,11 @@ Lint/DuplicateHashKey:
|
|
1707
1707
|
VersionAdded: '0.34'
|
1708
1708
|
VersionChanged: '0.77'
|
1709
1709
|
|
1710
|
+
Lint/DuplicateMagicComment:
|
1711
|
+
Description: 'Check for duplicated magic comments.'
|
1712
|
+
Enabled: pending
|
1713
|
+
VersionAdded: '1.37'
|
1714
|
+
|
1710
1715
|
Lint/DuplicateMethods:
|
1711
1716
|
Description: 'Check for duplicate method definitions.'
|
1712
1717
|
Enabled: true
|
@@ -1957,6 +1962,8 @@ Lint/NestedMethodDefinition:
|
|
1957
1962
|
Description: 'Do not use nested method definitions.'
|
1958
1963
|
StyleGuide: '#no-nested-methods'
|
1959
1964
|
Enabled: true
|
1965
|
+
AllowedMethods: []
|
1966
|
+
AllowedPatterns: []
|
1960
1967
|
VersionAdded: '0.32'
|
1961
1968
|
|
1962
1969
|
Lint/NestedPercentLiteral:
|
@@ -2021,7 +2028,9 @@ Lint/OrAssignmentToConstant:
|
|
2021
2028
|
Lint/OrderedMagicComments:
|
2022
2029
|
Description: 'Checks the proper ordering of magic comments and whether a magic comment is not placed before a shebang.'
|
2023
2030
|
Enabled: true
|
2031
|
+
SafeAutoCorrect: false
|
2024
2032
|
VersionAdded: '0.53'
|
2033
|
+
VersionChanged: '1.37'
|
2025
2034
|
|
2026
2035
|
Lint/OutOfRangeRegexpRef:
|
2027
2036
|
Description: 'Checks for out of range reference for Regexp because it always returns nil.'
|
@@ -2794,6 +2803,7 @@ Naming/MethodParameterName:
|
|
2794
2803
|
AllowNamesEndingInNumbers: true
|
2795
2804
|
# Allowed names that will not register an offense
|
2796
2805
|
AllowedNames:
|
2806
|
+
- as
|
2797
2807
|
- at
|
2798
2808
|
- by
|
2799
2809
|
- db
|
@@ -2948,6 +2958,7 @@ Style/AccessModifierDeclarations:
|
|
2948
2958
|
- inline
|
2949
2959
|
- group
|
2950
2960
|
AllowModifiersOnSymbols: true
|
2961
|
+
SafeAutoCorrect: false
|
2951
2962
|
|
2952
2963
|
Style/AccessorGrouping:
|
2953
2964
|
Description: 'Checks for grouping of accessors in `class` and `module` bodies.'
|
@@ -3186,6 +3197,15 @@ Style/CaseEquality:
|
|
3186
3197
|
# # good
|
3187
3198
|
# String === "string"
|
3188
3199
|
AllowOnConstant: false
|
3200
|
+
# If `AllowOnSelfClass` option is enabled, the cop will ignore violations when the receiver of
|
3201
|
+
# the case equality operator is `self.class`.
|
3202
|
+
#
|
3203
|
+
# # bad
|
3204
|
+
# some_class === object
|
3205
|
+
#
|
3206
|
+
# # good
|
3207
|
+
# self.class === object
|
3208
|
+
AllowOnSelfClass: false
|
3189
3209
|
|
3190
3210
|
Style/CaseLikeIf:
|
3191
3211
|
Description: 'Identifies places where `if-elsif` constructions can be replaced with `case-when`.'
|
@@ -3839,7 +3859,7 @@ Style/HashSyntax:
|
|
3839
3859
|
- never
|
3840
3860
|
# accepts both shorthand and explicit use of hash literal value.
|
3841
3861
|
- either
|
3842
|
-
# like "
|
3862
|
+
# like "either", but will avoid mixing styles in a single hash
|
3843
3863
|
- consistent
|
3844
3864
|
# Force hashes that have a symbol value to use hash rockets
|
3845
3865
|
UseHashRocketsWithSymbolValues: false
|
@@ -4487,6 +4507,12 @@ Style/OpenStructUse:
|
|
4487
4507
|
Enabled: pending
|
4488
4508
|
VersionAdded: '1.23'
|
4489
4509
|
|
4510
|
+
Style/OperatorMethodCall:
|
4511
|
+
Description: 'Checks for redundant dot before operator method call.'
|
4512
|
+
StyleGuide: '#operator-method-call'
|
4513
|
+
Enabled: pending
|
4514
|
+
VersionAdded: '1.37'
|
4515
|
+
|
4490
4516
|
Style/OptionHash:
|
4491
4517
|
Description: "Don't use option hashes when you can use keyword arguments."
|
4492
4518
|
Enabled: false
|
@@ -4781,6 +4807,11 @@ Style/RedundantSortBy:
|
|
4781
4807
|
Enabled: true
|
4782
4808
|
VersionAdded: '0.36'
|
4783
4809
|
|
4810
|
+
Style/RedundantStringEscape:
|
4811
|
+
Description: 'Checks for redundant escapes in string literals.'
|
4812
|
+
Enabled: pending
|
4813
|
+
VersionAdded: '1.37'
|
4814
|
+
|
4784
4815
|
Style/RegexpLiteral:
|
4785
4816
|
Description: 'Use / or %r around regular expressions.'
|
4786
4817
|
StyleGuide: '#percent-r'
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# This is a class that reads optional command line arguments to rubocop from environment variable.
|
5
|
+
# @api private
|
6
|
+
class ArgumentsEnv
|
7
|
+
def self.read_as_arguments
|
8
|
+
if (arguments = ENV.fetch('RUBOCOP_OPTS', '')).empty?
|
9
|
+
[]
|
10
|
+
else
|
11
|
+
require 'shellwords'
|
12
|
+
|
13
|
+
Shellwords.split(arguments)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# This is a class that reads optional command line arguments to rubocop from .rubocop file.
|
5
|
+
# @api private
|
6
|
+
class ArgumentsFile
|
7
|
+
def self.read_as_arguments
|
8
|
+
if File.exist?('.rubocop') && !File.directory?('.rubocop')
|
9
|
+
require 'shellwords'
|
10
|
+
|
11
|
+
File.read('.rubocop').shellsplit
|
12
|
+
else
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -41,13 +41,13 @@ module RuboCop
|
|
41
41
|
|
42
42
|
def with_redirect
|
43
43
|
if @options[:stderr]
|
44
|
-
orig_stdout = $stdout
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
44
|
+
orig_stdout = $stdout
|
45
|
+
begin
|
46
|
+
$stdout = $stderr
|
47
|
+
yield
|
48
|
+
ensure
|
49
|
+
$stdout = orig_stdout
|
50
|
+
end
|
51
51
|
else
|
52
52
|
yield
|
53
53
|
end
|
@@ -206,9 +206,8 @@ module RuboCop
|
|
206
206
|
end
|
207
207
|
|
208
208
|
def snake_case(camel_case_string)
|
209
|
-
return 'rspec' if camel_case_string == 'RSpec'
|
210
|
-
|
211
209
|
camel_case_string
|
210
|
+
.gsub('RSpec', 'Rspec')
|
212
211
|
.gsub(%r{([^A-Z/])([A-Z]+)}, '\1_\2')
|
213
212
|
.gsub(%r{([A-Z])([A-Z][^A-Z\d/]+)}, '\1_\2')
|
214
213
|
.downcase
|
@@ -22,23 +22,24 @@ module RuboCop
|
|
22
22
|
# # bad
|
23
23
|
#
|
24
24
|
# foo.bar
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
25
|
+
# .each do
|
26
|
+
# baz
|
27
|
+
# end
|
28
28
|
#
|
29
29
|
# # good
|
30
30
|
#
|
31
|
-
#
|
32
|
-
#
|
31
|
+
# foo.bar
|
32
|
+
# .each do
|
33
|
+
# baz
|
33
34
|
# end
|
34
35
|
#
|
35
36
|
# @example EnforcedStyleAlignWith: start_of_block
|
36
37
|
# # bad
|
37
38
|
#
|
38
39
|
# foo.bar
|
39
|
-
#
|
40
|
-
#
|
41
|
-
#
|
40
|
+
# .each do
|
41
|
+
# baz
|
42
|
+
# end
|
42
43
|
#
|
43
44
|
# # good
|
44
45
|
#
|
@@ -51,16 +52,17 @@ module RuboCop
|
|
51
52
|
# # bad
|
52
53
|
#
|
53
54
|
# foo.bar
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
55
|
+
# .each do
|
56
|
+
# baz
|
57
|
+
# end
|
57
58
|
#
|
58
59
|
# # good
|
59
60
|
#
|
60
61
|
# foo.bar
|
61
62
|
# .each do
|
62
|
-
#
|
63
|
+
# baz
|
63
64
|
# end
|
65
|
+
#
|
64
66
|
class BlockAlignment < Base
|
65
67
|
include ConfigurableEnforcedStyle
|
66
68
|
include RangeHelp
|
@@ -148,7 +148,9 @@ module RuboCop
|
|
148
148
|
check_indentation(in_pattern_node.loc.keyword, in_pattern_node.body)
|
149
149
|
end
|
150
150
|
|
151
|
-
|
151
|
+
else_branch = case_match.else_branch&.empty_else_type? ? nil : case_match.else_branch
|
152
|
+
|
153
|
+
check_indentation(case_match.in_pattern_branches.last.loc.keyword, else_branch)
|
152
154
|
end
|
153
155
|
|
154
156
|
def on_if(node, base = node)
|
@@ -341,7 +343,7 @@ module RuboCop
|
|
341
343
|
end
|
342
344
|
|
343
345
|
def skip_check?(base_loc, body_node)
|
344
|
-
return true if
|
346
|
+
return true if allowed_line?(base_loc)
|
345
347
|
return true unless body_node
|
346
348
|
|
347
349
|
# Don't check if expression is on same line as "then" keyword, etc.
|
@@ -169,19 +169,22 @@ module RuboCop
|
|
169
169
|
|
170
170
|
def qualifies_for_compact?(node, token, side: :right)
|
171
171
|
if side == :right
|
172
|
-
multi_dimensional_array?(node, token) &&
|
172
|
+
multi_dimensional_array?(node, token) && token.space_before?
|
173
173
|
else
|
174
|
-
multi_dimensional_array?(node, token, side: :left) &&
|
175
|
-
!next_to_bracket?(token, side: :left)
|
174
|
+
multi_dimensional_array?(node, token, side: :left) && token.space_after?
|
176
175
|
end
|
177
176
|
end
|
178
177
|
|
179
178
|
def multi_dimensional_array?(node, token, side: :right)
|
180
|
-
|
179
|
+
offset = side == :right ? -1 : +1
|
180
|
+
i = index_for(node, token) + offset
|
181
|
+
# TODO: change this type check once
|
182
|
+
# https://github.com/rubocop/rubocop-ast/pull/240 is merged
|
183
|
+
i += offset while processed_source.tokens_within(node)[i].new_line?
|
181
184
|
if side == :right
|
182
|
-
processed_source.tokens_within(node)[i
|
185
|
+
processed_source.tokens_within(node)[i].right_bracket?
|
183
186
|
else
|
184
|
-
processed_source.tokens_within(node)[i
|
187
|
+
processed_source.tokens_within(node)[i].left_array_bracket?
|
185
188
|
end
|
186
189
|
end
|
187
190
|
|
@@ -200,12 +203,13 @@ module RuboCop
|
|
200
203
|
end
|
201
204
|
|
202
205
|
def compact_corrections(corrector, node, left, right)
|
203
|
-
if
|
206
|
+
if multi_dimensional_array?(node, left, side: :left)
|
204
207
|
compact(corrector, left, :right)
|
205
208
|
elsif !left.space_after?
|
206
209
|
corrector.insert_after(left.pos, ' ')
|
207
210
|
end
|
208
|
-
|
211
|
+
|
212
|
+
if multi_dimensional_array?(node, right)
|
209
213
|
compact(corrector, right, :left)
|
210
214
|
elsif !right.space_before?
|
211
215
|
corrector.insert_before(right.pos, ' ')
|
@@ -213,7 +217,7 @@ module RuboCop
|
|
213
217
|
end
|
214
218
|
|
215
219
|
def compact(corrector, bracket, side)
|
216
|
-
range = side_space_range(range: bracket.pos, side: side)
|
220
|
+
range = side_space_range(range: bracket.pos, side: side, include_newlines: true)
|
217
221
|
corrector.remove(range)
|
218
222
|
end
|
219
223
|
end
|
@@ -131,7 +131,7 @@ module RuboCop
|
|
131
131
|
args_delimiter = node.arguments.loc.begin if node.block_type? # Can be ( | or nil.
|
132
132
|
|
133
133
|
check_left_brace(inner, node.loc.begin, args_delimiter)
|
134
|
-
check_right_brace(inner, node.loc.begin, node.loc.end, node.single_line?)
|
134
|
+
check_right_brace(node, inner, node.loc.begin, node.loc.end, node.single_line?)
|
135
135
|
end
|
136
136
|
|
137
137
|
def check_left_brace(inner, left_brace, args_delimiter)
|
@@ -142,14 +142,15 @@ module RuboCop
|
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
145
|
-
def check_right_brace(inner, left_brace, right_brace, single_line)
|
145
|
+
def check_right_brace(node, inner, left_brace, right_brace, single_line)
|
146
146
|
if single_line && /\S$/.match?(inner)
|
147
147
|
no_space(right_brace.begin_pos, right_brace.end_pos, 'Space missing inside }.')
|
148
148
|
else
|
149
|
+
column = node.loc.expression.column
|
149
150
|
return if multiline_block?(left_brace, right_brace) &&
|
150
|
-
aligned_braces?(
|
151
|
+
aligned_braces?(inner, right_brace, column)
|
151
152
|
|
152
|
-
space_inside_right_brace(right_brace)
|
153
|
+
space_inside_right_brace(inner, right_brace, column)
|
153
154
|
end
|
154
155
|
end
|
155
156
|
|
@@ -157,8 +158,12 @@ module RuboCop
|
|
157
158
|
left_brace.first_line != right_brace.first_line
|
158
159
|
end
|
159
160
|
|
160
|
-
def aligned_braces?(
|
161
|
-
|
161
|
+
def aligned_braces?(inner, right_brace, column)
|
162
|
+
column == right_brace.column || column == inner_last_space_count(inner)
|
163
|
+
end
|
164
|
+
|
165
|
+
def inner_last_space_count(inner)
|
166
|
+
inner.split("\n").last.count(' ')
|
162
167
|
end
|
163
168
|
|
164
169
|
def no_space_inside_left_brace(left_brace, args_delimiter)
|
@@ -197,10 +202,21 @@ module RuboCop
|
|
197
202
|
args_delimiter&.is?('|')
|
198
203
|
end
|
199
204
|
|
200
|
-
def space_inside_right_brace(right_brace)
|
205
|
+
def space_inside_right_brace(inner, right_brace, column)
|
201
206
|
brace_with_space = range_with_surrounding_space(right_brace, side: :left)
|
202
|
-
|
203
|
-
|
207
|
+
begin_pos = brace_with_space.begin_pos
|
208
|
+
end_pos = brace_with_space.end_pos - 1
|
209
|
+
|
210
|
+
if brace_with_space.source.match?(/\R/)
|
211
|
+
begin_pos = end_pos - (right_brace.column - column)
|
212
|
+
end
|
213
|
+
|
214
|
+
if inner.end_with?(']')
|
215
|
+
end_pos -= 1
|
216
|
+
begin_pos = end_pos - (inner_last_space_count(inner) - column)
|
217
|
+
end
|
218
|
+
|
219
|
+
space(begin_pos, end_pos, 'Space inside } detected.')
|
204
220
|
end
|
205
221
|
|
206
222
|
def no_space(begin_pos, end_pos, msg)
|
@@ -46,10 +46,13 @@ module RuboCop
|
|
46
46
|
# # bad
|
47
47
|
# foo = { }
|
48
48
|
# bar = { }
|
49
|
+
# baz = {
|
50
|
+
# }
|
49
51
|
#
|
50
52
|
# # good
|
51
53
|
# foo = {}
|
52
54
|
# bar = {}
|
55
|
+
# baz = {}
|
53
56
|
#
|
54
57
|
# @example EnforcedStyleForEmptyBraces: space
|
55
58
|
# # The `space` EnforcedStyleForEmptyBraces style enforces that
|
@@ -60,8 +63,9 @@ module RuboCop
|
|
60
63
|
#
|
61
64
|
# # good
|
62
65
|
# foo = { }
|
63
|
-
# foo = {
|
64
|
-
# foo = {
|
66
|
+
# foo = { }
|
67
|
+
# foo = {
|
68
|
+
# }
|
65
69
|
#
|
66
70
|
class SpaceInsideHashLiteralBraces < Base
|
67
71
|
include SurroundingSpace
|
@@ -77,6 +81,7 @@ module RuboCop
|
|
77
81
|
|
78
82
|
check(tokens[0], tokens[1])
|
79
83
|
check(tokens[-2], tokens[-1]) if tokens.size > 2
|
84
|
+
check_whitespace_only_hash(node) if enforce_no_space_style_for_empty_braces?
|
80
85
|
end
|
81
86
|
|
82
87
|
private
|
@@ -103,7 +108,7 @@ module RuboCop
|
|
103
108
|
if is_same_braces && style == :compact
|
104
109
|
false
|
105
110
|
elsif is_empty_braces
|
106
|
-
|
111
|
+
!enforce_no_space_style_for_empty_braces?
|
107
112
|
else
|
108
113
|
style != :no_space
|
109
114
|
end
|
@@ -175,6 +180,26 @@ module RuboCop
|
|
175
180
|
|
176
181
|
range_between(begin_pos, range.end_pos - 1)
|
177
182
|
end
|
183
|
+
|
184
|
+
def check_whitespace_only_hash(node)
|
185
|
+
range = range_inside_hash(node)
|
186
|
+
return unless range.source.match?(/\A\s+\z/m)
|
187
|
+
|
188
|
+
add_offense(
|
189
|
+
range,
|
190
|
+
message: format(MSG, problem: 'empty hash literal braces detected')
|
191
|
+
) do |corrector|
|
192
|
+
corrector.remove(range)
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def range_inside_hash(node)
|
197
|
+
range_between(node.location.begin.end_pos, node.location.end.begin_pos)
|
198
|
+
end
|
199
|
+
|
200
|
+
def enforce_no_space_style_for_empty_braces?
|
201
|
+
cop_config['EnforcedStyleForEmptyBraces'] == 'no_space'
|
202
|
+
end
|
178
203
|
end
|
179
204
|
end
|
180
205
|
end
|
@@ -45,7 +45,7 @@ module RuboCop
|
|
45
45
|
# # bad
|
46
46
|
# expect { do_something }.to change { object.attribute }
|
47
47
|
#
|
48
|
-
# @example AllowedPatterns: [
|
48
|
+
# @example AllowedPatterns: ['change']
|
49
49
|
#
|
50
50
|
# # good
|
51
51
|
# expect { do_something }.to change { object.attribute }
|
@@ -81,7 +81,7 @@ module RuboCop
|
|
81
81
|
def allowed_method_pattern?(node)
|
82
82
|
node.assignment? || node.operator_method? || node.method?(:[]) ||
|
83
83
|
allowed_method?(node.last_argument.method_name) ||
|
84
|
-
matches_allowed_pattern?(node.last_argument.
|
84
|
+
matches_allowed_pattern?(node.last_argument.send_node.source)
|
85
85
|
end
|
86
86
|
|
87
87
|
def message(send_node)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks for duplicated magic comments.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
#
|
12
|
+
# # encoding: ascii
|
13
|
+
# # encoding: ascii
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
#
|
17
|
+
# # encoding: ascii
|
18
|
+
#
|
19
|
+
# # bad
|
20
|
+
#
|
21
|
+
# # frozen_string_literal: true
|
22
|
+
# # frozen_string_literal: true
|
23
|
+
#
|
24
|
+
# # good
|
25
|
+
#
|
26
|
+
# # frozen_string_literal: true
|
27
|
+
#
|
28
|
+
class DuplicateMagicComment < Base
|
29
|
+
include FrozenStringLiteral
|
30
|
+
include RangeHelp
|
31
|
+
extend AutoCorrector
|
32
|
+
|
33
|
+
MSG = 'Duplicate magic comment detected.'
|
34
|
+
|
35
|
+
def on_new_investigation
|
36
|
+
return if processed_source.buffer.source.empty?
|
37
|
+
|
38
|
+
magic_comment_lines.each_value do |comment_lines|
|
39
|
+
next if comment_lines.count <= 1
|
40
|
+
|
41
|
+
comment_lines[1..].each do |comment_line|
|
42
|
+
range = processed_source.buffer.line_range(comment_line + 1)
|
43
|
+
|
44
|
+
register_offense(range)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def magic_comment_lines
|
52
|
+
comment_lines = { encoding_magic_comments: [], frozen_string_literal_magic_comments: [] }
|
53
|
+
|
54
|
+
leading_magic_comments.each.with_index do |magic_comment, index|
|
55
|
+
if magic_comment.encoding_specified?
|
56
|
+
comment_lines[:encoding_magic_comments] << index
|
57
|
+
elsif magic_comment.frozen_string_literal_specified?
|
58
|
+
comment_lines[:frozen_string_literal_magic_comments] << index
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
comment_lines
|
63
|
+
end
|
64
|
+
|
65
|
+
def register_offense(range)
|
66
|
+
add_offense(range) do |corrector|
|
67
|
+
corrector.remove(range_by_whole_lines(range, include_final_newline: true))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -133,7 +133,7 @@ module RuboCop
|
|
133
133
|
end
|
134
134
|
|
135
135
|
def found_instance_method(node, name)
|
136
|
-
return unless (scope = node.parent_module_name)
|
136
|
+
return found_sclass_method(node, name) unless (scope = node.parent_module_name)
|
137
137
|
|
138
138
|
# Humanize the scope
|
139
139
|
scope = scope.sub(
|
@@ -145,6 +145,16 @@ module RuboCop
|
|
145
145
|
found_method(node, "#{scope}#{name}")
|
146
146
|
end
|
147
147
|
|
148
|
+
def found_sclass_method(node, name)
|
149
|
+
singleton_ancestor = node.each_ancestor.find(&:sclass_type?)
|
150
|
+
return unless singleton_ancestor
|
151
|
+
|
152
|
+
singleton_receiver_node = singleton_ancestor.children[0]
|
153
|
+
return unless singleton_receiver_node.send_type?
|
154
|
+
|
155
|
+
found_method(node, "#{singleton_receiver_node.method_name}.#{name}")
|
156
|
+
end
|
157
|
+
|
148
158
|
def found_method(node, method_name)
|
149
159
|
if @definitions.key?(method_name)
|
150
160
|
loc = case node.type
|
@@ -32,26 +32,40 @@ module RuboCop
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
35
36
|
def each_repeated_character_class_element_loc(node)
|
36
37
|
node.parsed_tree&.each_expression do |expr|
|
37
|
-
next if expr
|
38
|
+
next if skip_expression?(expr)
|
38
39
|
|
39
40
|
seen = Set.new
|
41
|
+
enum = expr.expressions.to_enum
|
42
|
+
expression_count = expr.expressions.count
|
40
43
|
|
41
|
-
|
42
|
-
|
44
|
+
expression_count.times do |current_number|
|
45
|
+
current_child = enum.next
|
46
|
+
next if within_interpolation?(node, current_child)
|
43
47
|
|
44
|
-
|
48
|
+
current_child_source = current_child.to_s
|
49
|
+
next_child = enum.peek if current_number + 1 < expression_count
|
45
50
|
|
46
|
-
|
51
|
+
if seen.include?(current_child_source)
|
52
|
+
next if start_with_escaped_zero_number?(current_child_source, next_child.to_s)
|
47
53
|
|
48
|
-
|
54
|
+
yield current_child.expression
|
55
|
+
end
|
56
|
+
|
57
|
+
seen << current_child_source
|
49
58
|
end
|
50
59
|
end
|
51
60
|
end
|
61
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
52
62
|
|
53
63
|
private
|
54
64
|
|
65
|
+
def skip_expression?(expr)
|
66
|
+
expr.type != :set || expr.token == :intersection
|
67
|
+
end
|
68
|
+
|
55
69
|
# Since we blank interpolations with a space for every char of the interpolation, we would
|
56
70
|
# mark every space (except the first) as duplicate if we do not skip regexp_parser nodes
|
57
71
|
# that are within an interpolation.
|
@@ -61,6 +75,11 @@ module RuboCop
|
|
61
75
|
interpolation_locs(node).any? { |il| il.overlaps?(parse_tree_child_loc) }
|
62
76
|
end
|
63
77
|
|
78
|
+
def start_with_escaped_zero_number?(current_child, next_child)
|
79
|
+
# Represents escaped code from `"\00"` (`"\u0000"`) to `"\07"` (`"\a"`).
|
80
|
+
current_child == '\\0' && next_child.match?(/[0-7]/)
|
81
|
+
end
|
82
|
+
|
64
83
|
def interpolation_locs(node)
|
65
84
|
@interpolation_locs ||= {}
|
66
85
|
|
@@ -85,7 +85,9 @@ module RuboCop
|
|
85
85
|
private
|
86
86
|
|
87
87
|
def body_or_allowed_comment_lines?(node)
|
88
|
-
|
88
|
+
return true if node.body
|
89
|
+
|
90
|
+
cop_config['AllowComments'] && processed_source.contains_comment?(node.source_range)
|
89
91
|
end
|
90
92
|
end
|
91
93
|
end
|