rubocop 1.9.1 → 1.10.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 +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: []
|