rubocop 1.9.1 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +38 -16
- data/config/obsoletion.yml +4 -0
- data/lib/rubocop.rb +2 -0
- data/lib/rubocop/cop/gemspec/date_assignment.rb +56 -0
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +26 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -1
- data/lib/rubocop/cop/lint/debugger.rb +58 -14
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +13 -4
- data/lib/rubocop/cop/lint/duplicate_require.rb +2 -2
- data/lib/rubocop/cop/lint/else_layout.rb +1 -1
- data/lib/rubocop/cop/lint/multiple_comparison.rb +4 -4
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +5 -3
- data/lib/rubocop/cop/mixin/preferred_delimiters.rb +2 -2
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/style/constant_visibility.rb +27 -0
- data/lib/rubocop/cop/style/double_negation.rb +2 -2
- data/lib/rubocop/cop/style/eval_with_location.rb +87 -27
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/exponential_notation.rb +6 -7
- data/lib/rubocop/cop/style/hash_conversion.rb +81 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d690ba94b53010f458962d3c50bae5ec6198e0b54565422b1bce58351429618a
|
4
|
+
data.tar.gz: 4b0a3f5d69b88b1db292620328a02c26f8315b37fc49b066e4aa24c317c22f86
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3655b57caafb4704d05658ef53f39e09f30e0f32d2def6908cfc6ecefcf7a0b67aeeafe862bc4ad76f96fb2c6b17b00a60997ad4af31fc0727e16c20ce1141da
|
7
|
+
data.tar.gz: 69f5289513c39feb34bf4df834e45b3288b76eda570d860ab0aab3a4742283cbaa5f9bebae9663fc6e7f3d00ae18bd8638bdc4d40b4c13516966fb349496aec4
|
data/README.md
CHANGED
@@ -51,7 +51,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
51
51
|
in your `Gemfile`:
|
52
52
|
|
53
53
|
```rb
|
54
|
-
gem 'rubocop', '~> 1.
|
54
|
+
gem 'rubocop', '~> 1.10', require: false
|
55
55
|
```
|
56
56
|
|
57
57
|
See [versioning](https://docs.rubocop.org/rubocop/1.0/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -203,6 +203,13 @@ Bundler/OrderedGems:
|
|
203
203
|
|
204
204
|
#################### Gemspec ###############################
|
205
205
|
|
206
|
+
Gemspec/DateAssignment:
|
207
|
+
Description: 'Checks that `date =` is not used in gemspec file, it is set automatically when the gem is packaged.'
|
208
|
+
Enabled: pending
|
209
|
+
VersionAdded: '1.10'
|
210
|
+
Include:
|
211
|
+
- '**/*.gemspec'
|
212
|
+
|
206
213
|
Gemspec/DuplicatedAssignment:
|
207
214
|
Description: 'An attribute assignment method calls should be listed only once in a gemspec.'
|
208
215
|
Enabled: true
|
@@ -1446,23 +1453,31 @@ Lint/Debugger:
|
|
1446
1453
|
Description: 'Check for debugger calls.'
|
1447
1454
|
Enabled: true
|
1448
1455
|
VersionAdded: '0.14'
|
1449
|
-
VersionChanged: '
|
1450
|
-
DebuggerReceivers:
|
1451
|
-
- binding
|
1452
|
-
- Kernel
|
1453
|
-
- Pry
|
1456
|
+
VersionChanged: '1.10'
|
1457
|
+
DebuggerReceivers: [] # deprecated
|
1454
1458
|
DebuggerMethods:
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1462
|
-
|
1463
|
-
|
1464
|
-
|
1465
|
-
|
1459
|
+
# Groups are available so that a specific group can be disabled in
|
1460
|
+
# a user's configuration, but are otherwise not significant.
|
1461
|
+
Kernel:
|
1462
|
+
- binding.irb
|
1463
|
+
Byebug:
|
1464
|
+
- byebug
|
1465
|
+
- remote_byebug
|
1466
|
+
- Kernel.byebug
|
1467
|
+
- Kernel.remote_byebug
|
1468
|
+
Capybara:
|
1469
|
+
- save_and_open_page
|
1470
|
+
- save_and_open_screenshot
|
1471
|
+
Pry:
|
1472
|
+
- binding.pry
|
1473
|
+
- binding.remote_pry
|
1474
|
+
- binding.pry_remote
|
1475
|
+
- Pry.rescue
|
1476
|
+
Rails:
|
1477
|
+
- debugger
|
1478
|
+
- Kernel.debugger
|
1479
|
+
WebConsole:
|
1480
|
+
- binding.console
|
1466
1481
|
|
1467
1482
|
Lint/DeprecatedClassMethods:
|
1468
1483
|
Description: 'Check for deprecated class method calls.'
|
@@ -3087,6 +3102,8 @@ Style/ConstantVisibility:
|
|
3087
3102
|
visibility declarations.
|
3088
3103
|
Enabled: false
|
3089
3104
|
VersionAdded: '0.66'
|
3105
|
+
VersionChanged: '1.10'
|
3106
|
+
IgnoreModules: false
|
3090
3107
|
|
3091
3108
|
# Checks that you have put a copyright in a comment before any code.
|
3092
3109
|
#
|
@@ -3425,6 +3442,11 @@ Style/HashAsLastArrayItem:
|
|
3425
3442
|
- braces
|
3426
3443
|
- no_braces
|
3427
3444
|
|
3445
|
+
Style/HashConversion:
|
3446
|
+
Description: 'Avoid Hash[] in favor of ary.to_h or literal hashes.'
|
3447
|
+
Enabled: pending
|
3448
|
+
VersionAdded: '1.10'
|
3449
|
+
|
3428
3450
|
Style/HashEachMethods:
|
3429
3451
|
Description: 'Use Hash#each_key and Hash#each_value.'
|
3430
3452
|
StyleGuide: '#hash-each'
|
data/config/obsoletion.yml
CHANGED
@@ -187,6 +187,10 @@ changed_parameters:
|
|
187
187
|
parameters: ExcludedMethods
|
188
188
|
alternative: IgnoredMethods
|
189
189
|
severity: warning
|
190
|
+
- cops: Lint/Debugger
|
191
|
+
parameters: DebuggerReceivers
|
192
|
+
reason: "`DebuggerReceivers` is no longer necessary, method receivers should be specified in `DebuggerMethods` instead."
|
193
|
+
severity: warning
|
190
194
|
|
191
195
|
# Enforced styles that have been removed or replaced
|
192
196
|
changed_enforced_styles:
|
data/lib/rubocop.rb
CHANGED
@@ -152,6 +152,7 @@ require_relative 'rubocop/cop/bundler/gem_comment'
|
|
152
152
|
require_relative 'rubocop/cop/bundler/insecure_protocol_source'
|
153
153
|
require_relative 'rubocop/cop/bundler/ordered_gems'
|
154
154
|
|
155
|
+
require_relative 'rubocop/cop/gemspec/date_assignment'
|
155
156
|
require_relative 'rubocop/cop/gemspec/duplicated_assignment'
|
156
157
|
require_relative 'rubocop/cop/gemspec/ordered_dependencies'
|
157
158
|
require_relative 'rubocop/cop/gemspec/required_ruby_version'
|
@@ -472,6 +473,7 @@ require_relative 'rubocop/cop/style/global_std_stream'
|
|
472
473
|
require_relative 'rubocop/cop/style/global_vars'
|
473
474
|
require_relative 'rubocop/cop/style/guard_clause'
|
474
475
|
require_relative 'rubocop/cop/style/hash_as_last_array_item'
|
476
|
+
require_relative 'rubocop/cop/style/hash_conversion'
|
475
477
|
require_relative 'rubocop/cop/style/hash_each_methods'
|
476
478
|
require_relative 'rubocop/cop/style/hash_except'
|
477
479
|
require_relative 'rubocop/cop/style/hash_like_case'
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Gemspec
|
6
|
+
# This cop checks that `date =` is not used in gemspec file.
|
7
|
+
# It is set automatically when the gem is packaged.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# Gem::Specification.new do |spec|
|
13
|
+
# s.name = 'your_cool_gem_name'
|
14
|
+
# spec.date = Time.now.strftime('%Y-%m-%d')
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# Gem::Specification.new do |spec|
|
19
|
+
# s.name = 'your_cool_gem_name'
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
class DateAssignment < Base
|
23
|
+
include RangeHelp
|
24
|
+
extend AutoCorrector
|
25
|
+
|
26
|
+
MSG = 'Do not use `date =` in gemspec, it is set automatically when the gem is packaged.'
|
27
|
+
|
28
|
+
def_node_matcher :gem_specification, <<~PATTERN
|
29
|
+
(block
|
30
|
+
(send
|
31
|
+
(const
|
32
|
+
(const {cbase nil?} :Gem) :Specification) :new)
|
33
|
+
...)
|
34
|
+
PATTERN
|
35
|
+
|
36
|
+
def on_block(block_node)
|
37
|
+
return unless gem_specification(block_node)
|
38
|
+
|
39
|
+
block_parameter = block_node.arguments.first.source
|
40
|
+
|
41
|
+
date_assignment = block_node.descendants.detect do |node|
|
42
|
+
node.send_type? && node.receiver&.source == block_parameter && node.method?(:date=)
|
43
|
+
end
|
44
|
+
|
45
|
+
return unless date_assignment
|
46
|
+
|
47
|
+
add_offense(date_assignment) do |corrector|
|
48
|
+
range = range_by_whole_lines(date_assignment.source_range, include_final_newline: true)
|
49
|
+
|
50
|
+
corrector.remove(range)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -152,7 +152,7 @@ module RuboCop
|
|
152
152
|
MSG = 'Indent the first argument one step more than %<base>s.'
|
153
153
|
|
154
154
|
def on_send(node)
|
155
|
-
return if enforce_first_argument_with_fixed_indentation?
|
155
|
+
return if style != :consistent && enforce_first_argument_with_fixed_indentation?
|
156
156
|
return if !node.arguments? || node.operator_method?
|
157
157
|
|
158
158
|
indent = base_indentation(node) + configured_indentation_width
|
@@ -31,6 +31,32 @@ module RuboCop
|
|
31
31
|
# foo = if expression
|
32
32
|
# 'bar'
|
33
33
|
# end
|
34
|
+
#
|
35
|
+
# @example SupportedTypes: ['block', 'case', 'class', 'if', 'kwbegin', 'module'] (default)
|
36
|
+
# # good
|
37
|
+
# foo =
|
38
|
+
# if expression
|
39
|
+
# 'bar'
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# # good
|
43
|
+
# foo =
|
44
|
+
# [1].map do |i|
|
45
|
+
# i + 1
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# @example SupportedTypes: ['block']
|
49
|
+
# # good
|
50
|
+
# foo = if expression
|
51
|
+
# 'bar'
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# # good
|
55
|
+
# foo =
|
56
|
+
# [1].map do |i|
|
57
|
+
# 'bar' * i
|
58
|
+
# end
|
59
|
+
#
|
34
60
|
class MultilineAssignmentLayout < Base
|
35
61
|
include CheckAssignment
|
36
62
|
include ConfigurableEnforcedStyle
|
@@ -47,7 +47,7 @@ module RuboCop
|
|
47
47
|
end_pos = node.receiver.source_range.end_pos
|
48
48
|
|
49
49
|
return if begin_pos - end_pos == 1 ||
|
50
|
-
(range = range_between(end_pos, begin_pos - 1)).source
|
50
|
+
(range = range_between(end_pos, begin_pos - 1)).source.start_with?('[')
|
51
51
|
|
52
52
|
range
|
53
53
|
end
|
@@ -3,8 +3,21 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
|
-
# This cop checks for calls
|
7
|
-
#
|
6
|
+
# This cop checks for debug calls (such as `debugger` or `binding.pry`) that should
|
7
|
+
# not be kept for production code.
|
8
|
+
#
|
9
|
+
# The cop can be configured using `DebuggerMethods`. By default, a number of gems
|
10
|
+
# debug entrypoints are configured (`Kernel`, `Byebug`, `Capybara`, `Pry`, `Rails`,
|
11
|
+
# and `WebConsole`). Additional methods can be added.
|
12
|
+
#
|
13
|
+
# Specific default groups can be disabled if necessary:
|
14
|
+
#
|
15
|
+
# [source,yaml]
|
16
|
+
# ----
|
17
|
+
# Lint/Debugger:
|
18
|
+
# WebConsole: ~
|
19
|
+
# ---
|
20
|
+
#
|
8
21
|
#
|
9
22
|
# @example
|
10
23
|
#
|
@@ -33,14 +46,32 @@ module RuboCop
|
|
33
46
|
# def some_method
|
34
47
|
# do_something
|
35
48
|
# end
|
49
|
+
#
|
50
|
+
# @example DebuggerMethods: [my_debugger]
|
51
|
+
#
|
52
|
+
# # bad (ok during development)
|
53
|
+
#
|
54
|
+
# def some_method
|
55
|
+
# my_debugger
|
56
|
+
# end
|
36
57
|
class Debugger < Base
|
37
58
|
MSG = 'Remove debugger entry point `%<source>s`.'
|
38
59
|
|
39
60
|
RESTRICT_ON_SEND = [].freeze
|
40
61
|
|
62
|
+
def_node_matcher :kernel?, <<~PATTERN
|
63
|
+
(const {nil? cbase} :Kernel)
|
64
|
+
PATTERN
|
65
|
+
|
66
|
+
def_node_matcher :valid_receiver?, <<~PATTERN
|
67
|
+
{
|
68
|
+
(const {nil? cbase} %1)
|
69
|
+
(send {nil? #kernel?} %1)
|
70
|
+
}
|
71
|
+
PATTERN
|
72
|
+
|
41
73
|
def on_send(node)
|
42
|
-
return unless debugger_method?(node
|
43
|
-
return if !node.receiver.nil? && !debugger_receiver?(node)
|
74
|
+
return unless debugger_method?(node)
|
44
75
|
|
45
76
|
add_offense(node)
|
46
77
|
end
|
@@ -51,19 +82,32 @@ module RuboCop
|
|
51
82
|
format(MSG, source: node.source)
|
52
83
|
end
|
53
84
|
|
54
|
-
def
|
55
|
-
|
85
|
+
def debugger_methods
|
86
|
+
@debugger_methods ||= begin
|
87
|
+
config = cop_config.fetch('DebuggerMethods', [])
|
88
|
+
values = config.is_a?(Array) ? config : config.values.flatten
|
89
|
+
values.map do |v|
|
90
|
+
next unless v
|
91
|
+
|
92
|
+
*receiver, method_name = v.split('.')
|
93
|
+
{
|
94
|
+
receiver: receiver.empty? ? nil : receiver.join.to_sym,
|
95
|
+
method_name: method_name.to_sym
|
96
|
+
}
|
97
|
+
end.compact
|
98
|
+
end
|
56
99
|
end
|
57
100
|
|
58
|
-
def
|
59
|
-
|
60
|
-
|
61
|
-
node.receiver.method_name
|
62
|
-
when RuboCop::AST::ConstNode
|
63
|
-
node.receiver.const_name
|
64
|
-
end
|
101
|
+
def debugger_method?(send_node)
|
102
|
+
debugger_methods.any? do |method|
|
103
|
+
next unless method[:method_name] == send_node.method_name
|
65
104
|
|
66
|
-
|
105
|
+
if method[:receiver].nil?
|
106
|
+
send_node.receiver.nil?
|
107
|
+
else
|
108
|
+
valid_receiver?(send_node.receiver, method[:receiver])
|
109
|
+
end
|
110
|
+
end
|
67
111
|
end
|
68
112
|
end
|
69
113
|
end
|
@@ -44,6 +44,8 @@ module RuboCop
|
|
44
44
|
MSG = 'Use `%<constant>s.%<method>s(%<replacement_args>s)`' \
|
45
45
|
' instead of `%<original>s`.'
|
46
46
|
|
47
|
+
NO_ARG_ALGORITHM = %w[BF DES IDEA RC4].freeze
|
48
|
+
|
47
49
|
def_node_matcher :algorithm_const, <<~PATTERN
|
48
50
|
(send
|
49
51
|
$(const
|
@@ -104,7 +106,7 @@ module RuboCop
|
|
104
106
|
def algorithm_name(node)
|
105
107
|
name = node.loc.name.source
|
106
108
|
|
107
|
-
if openssl_class(node) == 'OpenSSL::Cipher'
|
109
|
+
if openssl_class(node) == 'OpenSSL::Cipher' && !NO_ARG_ALGORITHM.include?(name)
|
108
110
|
name.scan(/.{3}/).join('-')
|
109
111
|
else
|
110
112
|
name
|
@@ -124,16 +126,23 @@ module RuboCop
|
|
124
126
|
algorithm_name = algorithm_name(algorithm_constant)
|
125
127
|
|
126
128
|
if openssl_class(algorithm_constant) == 'OpenSSL::Cipher'
|
127
|
-
build_cipher_arguments(node, algorithm_name)
|
129
|
+
build_cipher_arguments(node, algorithm_name, node.arguments.empty?)
|
128
130
|
else
|
129
131
|
(["'#{algorithm_name}'"] + node.arguments.map(&:source)).join(', ')
|
130
132
|
end
|
131
133
|
end
|
132
134
|
|
133
|
-
def build_cipher_arguments(node, algorithm_name)
|
135
|
+
def build_cipher_arguments(node, algorithm_name, no_arguments)
|
134
136
|
algorithm_parts = algorithm_name.downcase.split('-')
|
135
137
|
size_and_mode = sanitize_arguments(node.arguments).map(&:downcase)
|
136
|
-
|
138
|
+
|
139
|
+
if NO_ARG_ALGORITHM.include?(algorithm_parts.first.upcase) && no_arguments
|
140
|
+
"'#{algorithm_parts.first}'"
|
141
|
+
else
|
142
|
+
mode = 'cbc' unless size_and_mode == ['cbc']
|
143
|
+
|
144
|
+
"'#{(algorithm_parts + size_and_mode + [mode]).compact.take(3).join('-')}'"
|
145
|
+
end
|
137
146
|
end
|
138
147
|
end
|
139
148
|
end
|
@@ -21,11 +21,11 @@ module RuboCop
|
|
21
21
|
#
|
22
22
|
class DuplicateRequire < Base
|
23
23
|
MSG = 'Duplicate `%<method>s` detected.'
|
24
|
-
REQUIRE_METHODS = %i[require require_relative].freeze
|
24
|
+
REQUIRE_METHODS = Set.new(%i[require require_relative]).freeze
|
25
25
|
RESTRICT_ON_SEND = REQUIRE_METHODS
|
26
26
|
|
27
27
|
def_node_matcher :require_call?, <<~PATTERN
|
28
|
-
(send {nil? (const _ :Kernel)}
|
28
|
+
(send {nil? (const _ :Kernel)} %REQUIRE_METHODS _)
|
29
29
|
PATTERN
|
30
30
|
|
31
31
|
def on_new_investigation
|
@@ -11,14 +11,10 @@ module RuboCop
|
|
11
11
|
# @example
|
12
12
|
#
|
13
13
|
# # bad
|
14
|
-
#
|
15
14
|
# x < y < z
|
16
15
|
# 10 <= x <= 20
|
17
16
|
#
|
18
|
-
# @example
|
19
|
-
#
|
20
17
|
# # good
|
21
|
-
#
|
22
18
|
# x < y && y < z
|
23
19
|
# 10 <= x && x <= 20
|
24
20
|
class MultipleComparison < Base
|
@@ -26,6 +22,7 @@ module RuboCop
|
|
26
22
|
|
27
23
|
MSG = 'Use the `&&` operator to compare multiple values.'
|
28
24
|
COMPARISON_METHODS = %i[< > <= >=].freeze
|
25
|
+
SET_OPERATION_OPERATORS = %i[& | ^].freeze
|
29
26
|
RESTRICT_ON_SEND = COMPARISON_METHODS
|
30
27
|
|
31
28
|
def_node_matcher :multiple_compare?, <<~PATTERN
|
@@ -34,6 +31,9 @@ module RuboCop
|
|
34
31
|
|
35
32
|
def on_send(node)
|
36
33
|
return unless (center = multiple_compare?(node))
|
34
|
+
# It allows multiple comparison using `&`, `|`, and `^` set operation operators.
|
35
|
+
# e.g. `x >= y & y < z`
|
36
|
+
return if center.send_type? && SET_OPERATION_OPERATORS.include?(center.method_name)
|
37
37
|
|
38
38
|
add_offense(node) do |corrector|
|
39
39
|
new_center = "#{center.source} && #{center.source}"
|
@@ -140,13 +140,15 @@ module RuboCop
|
|
140
140
|
def replacement_range_and_content(node)
|
141
141
|
variable, = *node
|
142
142
|
loc = node.loc
|
143
|
+
expression = loc.expression
|
143
144
|
|
144
145
|
if array_new?(variable)
|
145
|
-
|
146
|
+
expression = node.parent.loc.expression if node.parent.array_type?
|
147
|
+
[expression, variable.source]
|
146
148
|
elsif !variable.array_type?
|
147
|
-
[
|
149
|
+
[expression, "[#{variable.source}]"]
|
148
150
|
elsif redundant_brackets?(node)
|
149
|
-
[
|
151
|
+
[expression, remove_brackets(variable)]
|
150
152
|
else
|
151
153
|
[loc.operator, '']
|
152
154
|
end
|
@@ -35,10 +35,10 @@ module RuboCop
|
|
35
35
|
ensure_valid_preferred_delimiters
|
36
36
|
|
37
37
|
if preferred_delimiters_config.key?('default')
|
38
|
-
|
38
|
+
PERCENT_LITERAL_TYPES.map do |type|
|
39
39
|
[type, preferred_delimiters_config[type] ||
|
40
40
|
preferred_delimiters_config['default']]
|
41
|
-
end
|
41
|
+
end.to_h
|
42
42
|
else
|
43
43
|
preferred_delimiters_config
|
44
44
|
end
|
data/lib/rubocop/cop/registry.rb
CHANGED
@@ -26,6 +26,24 @@ module RuboCop
|
|
26
26
|
# public_constant :BAZ
|
27
27
|
# end
|
28
28
|
#
|
29
|
+
# @example IgnoreModules: false (default)
|
30
|
+
# # bad
|
31
|
+
# class Foo
|
32
|
+
# MyClass = Struct.new()
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # good
|
36
|
+
# class Foo
|
37
|
+
# MyClass = Struct.new()
|
38
|
+
# public_constant :MyClass
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
# @example IgnoreModules: true
|
42
|
+
# # good
|
43
|
+
# class Foo
|
44
|
+
# MyClass = Struct.new()
|
45
|
+
# end
|
46
|
+
#
|
29
47
|
class ConstantVisibility < Base
|
30
48
|
MSG = 'Explicitly make `%<constant_name>s` public or private using ' \
|
31
49
|
'either `#public_constant` or `#private_constant`.'
|
@@ -33,6 +51,7 @@ module RuboCop
|
|
33
51
|
def on_casgn(node)
|
34
52
|
return unless class_or_module_scope?(node)
|
35
53
|
return if visibility_declaration?(node)
|
54
|
+
return if ignore_modules? && module?(node)
|
36
55
|
|
37
56
|
message = message(node)
|
38
57
|
add_offense(node, message: message)
|
@@ -40,6 +59,14 @@ module RuboCop
|
|
40
59
|
|
41
60
|
private
|
42
61
|
|
62
|
+
def ignore_modules?
|
63
|
+
cop_config.fetch('IgnoreModules', false)
|
64
|
+
end
|
65
|
+
|
66
|
+
def module?(node)
|
67
|
+
node.children.last.class_constructor?
|
68
|
+
end
|
69
|
+
|
43
70
|
def message(node)
|
44
71
|
_namespace, constant_name, _value = *node
|
45
72
|
|
@@ -5,8 +5,8 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# This cop checks for uses of double negation (`!!`) to convert something to a boolean value.
|
7
7
|
#
|
8
|
-
# When using `EnforcedStyle: allowed_in_returns`, allow double
|
9
|
-
# that use boolean as a return value. When using `EnforcedStyle: forbidden`, double
|
8
|
+
# When using `EnforcedStyle: allowed_in_returns`, allow double negation in contexts
|
9
|
+
# that use boolean as a return value. When using `EnforcedStyle: forbidden`, double negation
|
10
10
|
# should be forbidden always.
|
11
11
|
#
|
12
12
|
# @example
|
@@ -12,6 +12,11 @@ module RuboCop
|
|
12
12
|
# The cop also checks that the line number given relative to `__LINE__` is
|
13
13
|
# correct.
|
14
14
|
#
|
15
|
+
# This cop will autocorrect incorrect or missing filename and line number
|
16
|
+
# values. However, if `eval` is called without a binding argument, the cop
|
17
|
+
# will not attempt to automatically add a binding, or add filename and
|
18
|
+
# line values.
|
19
|
+
#
|
15
20
|
# @example
|
16
21
|
# # bad
|
17
22
|
# eval <<-RUBY
|
@@ -36,7 +41,21 @@ module RuboCop
|
|
36
41
|
# def do_something
|
37
42
|
# end
|
38
43
|
# RUBY
|
44
|
+
#
|
45
|
+
# This cop works only when a string literal is given as a code string.
|
46
|
+
# No offence is reported if a string variable is given as below:
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# # not checked
|
50
|
+
# code = <<-RUBY
|
51
|
+
# def do_something
|
52
|
+
# end
|
53
|
+
# RUBY
|
54
|
+
# eval code
|
55
|
+
#
|
39
56
|
class EvalWithLocation < Base
|
57
|
+
extend AutoCorrector
|
58
|
+
|
40
59
|
MSG = 'Pass `__FILE__` and `__LINE__` to `%<method_name>s`.'
|
41
60
|
MSG_EVAL = 'Pass a binding, `__FILE__` and `__LINE__` to `eval`.'
|
42
61
|
MSG_INCORRECT_FILE = 'Incorrect file for `%<method_name>s`; ' \
|
@@ -66,21 +85,28 @@ module RuboCop
|
|
66
85
|
code = node.arguments.first
|
67
86
|
return unless code && (code.str_type? || code.dstr_type?)
|
68
87
|
|
88
|
+
check_location(node, code)
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def check_location(node, code)
|
69
94
|
file, line = file_and_line(node)
|
70
95
|
|
71
96
|
if line
|
72
97
|
check_file(node, file)
|
73
98
|
check_line(node, code)
|
99
|
+
elsif file
|
100
|
+
check_file(node, file)
|
101
|
+
add_offense_for_missing_line(node, code)
|
74
102
|
else
|
75
|
-
|
103
|
+
add_offense_for_missing_location(node, code)
|
76
104
|
end
|
77
105
|
end
|
78
106
|
|
79
|
-
|
80
|
-
|
81
|
-
def register_offense(node)
|
107
|
+
def register_offense(node, &block)
|
82
108
|
msg = node.method?(:eval) ? MSG_EVAL : format(MSG, method_name: node.method_name)
|
83
|
-
add_offense(node, message: msg)
|
109
|
+
add_offense(node, message: msg, &block)
|
84
110
|
end
|
85
111
|
|
86
112
|
def special_file_keyword?(node)
|
@@ -98,6 +124,10 @@ module RuboCop
|
|
98
124
|
[node.arguments[base], node.arguments[base + 1]]
|
99
125
|
end
|
100
126
|
|
127
|
+
def with_binding?(node)
|
128
|
+
node.method?(:eval) ? node.arguments.size >= 2 : true
|
129
|
+
end
|
130
|
+
|
101
131
|
# FIXME: It's a Style/ConditionalAssignment's false positive.
|
102
132
|
# rubocop:disable Style/ConditionalAssignment
|
103
133
|
def with_lineno?(node)
|
@@ -109,18 +139,16 @@ module RuboCop
|
|
109
139
|
end
|
110
140
|
# rubocop:enable Style/ConditionalAssignment
|
111
141
|
|
112
|
-
def
|
113
|
-
expected =
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end
|
142
|
+
def add_offense_for_incorrect_line(method_name, line_node, sign, line_diff)
|
143
|
+
expected = expected_line(sign, line_diff)
|
144
|
+
message = format(MSG_INCORRECT_LINE,
|
145
|
+
method_name: method_name,
|
146
|
+
actual: line_node.source,
|
147
|
+
expected: expected)
|
119
148
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
expected: expected)
|
149
|
+
add_offense(line_node.loc.expression, message: message) do |corrector|
|
150
|
+
corrector.replace(line_node, expected)
|
151
|
+
end
|
124
152
|
end
|
125
153
|
|
126
154
|
def check_file(node, file_node)
|
@@ -131,13 +159,14 @@ module RuboCop
|
|
131
159
|
expected: '__FILE__',
|
132
160
|
actual: file_node.source)
|
133
161
|
|
134
|
-
add_offense(file_node, message: message)
|
162
|
+
add_offense(file_node, message: message) do |corrector|
|
163
|
+
corrector.replace(file_node, '__FILE__')
|
164
|
+
end
|
135
165
|
end
|
136
166
|
|
137
167
|
def check_line(node, code)
|
138
168
|
line_node = node.arguments.last
|
139
|
-
|
140
|
-
line_diff = string_first_line(code) - lineno_range.first_line
|
169
|
+
line_diff = line_difference(line_node, code)
|
141
170
|
if line_diff.zero?
|
142
171
|
add_offense_for_same_line(node, line_node)
|
143
172
|
else
|
@@ -145,6 +174,10 @@ module RuboCop
|
|
145
174
|
end
|
146
175
|
end
|
147
176
|
|
177
|
+
def line_difference(line_node, code)
|
178
|
+
string_first_line(code) - line_node.loc.expression.first_line
|
179
|
+
end
|
180
|
+
|
148
181
|
def string_first_line(str_node)
|
149
182
|
if str_node.heredoc?
|
150
183
|
str_node.loc.heredoc_body.first_line
|
@@ -156,20 +189,47 @@ module RuboCop
|
|
156
189
|
def add_offense_for_same_line(node, line_node)
|
157
190
|
return if special_line_keyword?(line_node)
|
158
191
|
|
159
|
-
|
160
|
-
line_node.loc.expression,
|
161
|
-
message: message_incorrect_line(node.method_name, line_node, nil, 0)
|
162
|
-
)
|
192
|
+
add_offense_for_incorrect_line(node.method_name, line_node, nil, 0)
|
163
193
|
end
|
164
194
|
|
165
195
|
def add_offense_for_different_line(node, line_node, line_diff)
|
166
196
|
sign = line_diff.positive? ? :+ : :-
|
167
197
|
return if line_with_offset?(line_node, sign, line_diff.abs)
|
168
198
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
199
|
+
add_offense_for_incorrect_line(node.method_name, line_node, sign, line_diff.abs)
|
200
|
+
end
|
201
|
+
|
202
|
+
def expected_line(sign, line_diff)
|
203
|
+
if line_diff.zero?
|
204
|
+
'__LINE__'
|
205
|
+
else
|
206
|
+
"__LINE__ #{sign} #{line_diff.abs}"
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def add_offense_for_missing_line(node, code)
|
211
|
+
register_offense(node) do |corrector|
|
212
|
+
line_str = missing_line(node, code)
|
213
|
+
corrector.insert_after(node.loc.expression.end, ", #{line_str}")
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def add_offense_for_missing_location(node, code)
|
218
|
+
if node.method?(:eval) && !with_binding?(node)
|
219
|
+
register_offense(node)
|
220
|
+
return
|
221
|
+
end
|
222
|
+
|
223
|
+
register_offense(node) do |corrector|
|
224
|
+
line_str = missing_line(node, code)
|
225
|
+
corrector.insert_after(node.loc.expression.end, ", __FILE__, #{line_str}")
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
def missing_line(node, code)
|
230
|
+
line_diff = line_difference(node.arguments.last, code)
|
231
|
+
sign = line_diff.positive? ? :+ : :-
|
232
|
+
expected_line(sign, line_diff)
|
173
233
|
end
|
174
234
|
end
|
175
235
|
end
|
@@ -97,7 +97,7 @@ module RuboCop
|
|
97
97
|
replacement = ' &block'
|
98
98
|
replacement = ",#{replacement}" unless arg_range.source.end_with?(',')
|
99
99
|
corrector.insert_after(arg_range, replacement) unless last_arg.blockarg_type?
|
100
|
-
elsif node.call_type?
|
100
|
+
elsif node.call_type? || node.zsuper_type?
|
101
101
|
corrector.insert_after(node, '(&block)')
|
102
102
|
else
|
103
103
|
corrector.insert_after(node.loc.name, '(&block)')
|
@@ -5,13 +5,12 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# This cop enforces consistency when using exponential notation
|
7
7
|
# for numbers in the code (eg 1.2e4). Different styles are supported:
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# * `engineering` which enforces the exponent to be a multiple of 3
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
# without trailing zeroes.
|
8
|
+
#
|
9
|
+
# * `scientific` which enforces a mantissa between 1 (inclusive) and 10 (exclusive).
|
10
|
+
# * `engineering` which enforces the exponent to be a multiple of 3 and the mantissa
|
11
|
+
# to be between 0.1 (inclusive) and 10 (exclusive).
|
12
|
+
# * `integral` which enforces the mantissa to always be a whole number without
|
13
|
+
# trailing zeroes.
|
15
14
|
#
|
16
15
|
# @example EnforcedStyle: scientific (default)
|
17
16
|
# # Enforces a mantissa between 1 (inclusive) and 10 (exclusive).
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks the usage of pre-2.1 `Hash[args]` method of converting enumerables and
|
7
|
+
# sequences of values to hashes.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# Hash[ary]
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# ary.to_h
|
15
|
+
#
|
16
|
+
# # bad
|
17
|
+
# Hash[key1, value1, key2, value2]
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# {key1 => value1, key2 => value2}
|
21
|
+
class HashConversion < Base
|
22
|
+
extend AutoCorrector
|
23
|
+
|
24
|
+
MSG_TO_H = 'Prefer ary.to_h to Hash[ary].'
|
25
|
+
MSG_LITERAL_MULTI_ARG = 'Prefer literal hash to Hash[arg1, arg2, ...].'
|
26
|
+
MSG_LITERAL_HASH_ARG = 'Prefer literal hash to Hash[key: value, ...].'
|
27
|
+
MSG_SPLAT = 'Prefer array_of_pairs.to_h to Hash[*array].'
|
28
|
+
RESTRICT_ON_SEND = %i[[]].freeze
|
29
|
+
|
30
|
+
def_node_matcher :hash_from_array?, '(send (const {nil? cbase} :Hash) :[] ...)'
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
return unless hash_from_array?(node)
|
34
|
+
|
35
|
+
# There are several cases:
|
36
|
+
# If there is one argument:
|
37
|
+
# Hash[ary] => ary.to_h
|
38
|
+
# Hash[*ary] => don't suggest corrections
|
39
|
+
# If there is 0 or 2+ arguments:
|
40
|
+
# Hash[a1, a2, a3, a4] => {a1 => a2, a3 => a4}
|
41
|
+
# ...but don't suggest correction if there is odd number of them (it is a bug)
|
42
|
+
node.arguments.count == 1 ? single_argument(node) : multi_argument(node)
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def single_argument(node)
|
48
|
+
first_argument = node.first_argument
|
49
|
+
if first_argument.hash_type?
|
50
|
+
add_offense(node, message: MSG_LITERAL_HASH_ARG) do |corrector|
|
51
|
+
corrector.replace(node, "{#{first_argument.source}}")
|
52
|
+
end
|
53
|
+
elsif first_argument.splat_type?
|
54
|
+
add_offense(node, message: MSG_SPLAT)
|
55
|
+
else
|
56
|
+
add_offense(node, message: MSG_TO_H) do |corrector|
|
57
|
+
corrector.replace(node, "#{first_argument.source}.to_h")
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def multi_argument(node)
|
63
|
+
if node.arguments.count.odd?
|
64
|
+
add_offense(node, message: MSG_LITERAL_MULTI_ARG)
|
65
|
+
else
|
66
|
+
add_offense(node, message: MSG_LITERAL_MULTI_ARG) do |corrector|
|
67
|
+
corrector.replace(node, args_to_hash(node.arguments))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def args_to_hash(args)
|
73
|
+
content = args.each_slice(2)
|
74
|
+
.map { |arg1, arg2| "#{arg1.source} => #{arg2.source}" }
|
75
|
+
.join(', ')
|
76
|
+
"{#{content}}"
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -81,13 +81,13 @@ module RuboCop
|
|
81
81
|
}
|
82
82
|
|
83
83
|
PERL_VARS =
|
84
|
-
|
84
|
+
ENGLISH_VARS.flat_map { |k, vs| vs.map { |v| [v, [k]] } }.to_h
|
85
85
|
|
86
86
|
ENGLISH_VARS.merge!(
|
87
|
-
|
87
|
+
ENGLISH_VARS.flat_map { |_, vs| vs.map { |v| [v, [v]] } }.to_h
|
88
88
|
)
|
89
89
|
PERL_VARS.merge!(
|
90
|
-
|
90
|
+
PERL_VARS.flat_map { |_, vs| vs.map { |v| [v, [v]] } }.to_h
|
91
91
|
)
|
92
92
|
ENGLISH_VARS.each_value(&:freeze).freeze
|
93
93
|
PERL_VARS.each_value(&:freeze).freeze
|
data/lib/rubocop/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubocop
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bozhidar Batsov
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: exe
|
12
12
|
cert_chain: []
|
13
|
-
date: 2021-02-
|
13
|
+
date: 2021-02-15 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: parallel
|
@@ -244,6 +244,7 @@ files:
|
|
244
244
|
- lib/rubocop/cop/documentation.rb
|
245
245
|
- lib/rubocop/cop/exclude_limit.rb
|
246
246
|
- lib/rubocop/cop/force.rb
|
247
|
+
- lib/rubocop/cop/gemspec/date_assignment.rb
|
247
248
|
- lib/rubocop/cop/gemspec/duplicated_assignment.rb
|
248
249
|
- lib/rubocop/cop/gemspec/ordered_dependencies.rb
|
249
250
|
- lib/rubocop/cop/gemspec/required_ruby_version.rb
|
@@ -655,6 +656,7 @@ files:
|
|
655
656
|
- lib/rubocop/cop/style/global_vars.rb
|
656
657
|
- lib/rubocop/cop/style/guard_clause.rb
|
657
658
|
- lib/rubocop/cop/style/hash_as_last_array_item.rb
|
659
|
+
- lib/rubocop/cop/style/hash_conversion.rb
|
658
660
|
- lib/rubocop/cop/style/hash_each_methods.rb
|
659
661
|
- lib/rubocop/cop/style/hash_except.rb
|
660
662
|
- lib/rubocop/cop/style/hash_like_case.rb
|
@@ -866,7 +868,7 @@ metadata:
|
|
866
868
|
homepage_uri: https://rubocop.org/
|
867
869
|
changelog_uri: https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md
|
868
870
|
source_code_uri: https://github.com/rubocop-hq/rubocop/
|
869
|
-
documentation_uri: https://docs.rubocop.org/rubocop/1.
|
871
|
+
documentation_uri: https://docs.rubocop.org/rubocop/1.10/
|
870
872
|
bug_tracker_uri: https://github.com/rubocop-hq/rubocop/issues
|
871
873
|
post_install_message:
|
872
874
|
rdoc_options: []
|