rubocop 1.85.1 → 1.86.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/config/default.yml +3 -10
- data/lib/rubocop/cache_config.rb +1 -1
- data/lib/rubocop/cli/command/auto_generate_config.rb +1 -1
- data/lib/rubocop/cli/command/show_cops.rb +2 -2
- data/lib/rubocop/cli/command/show_docs_url.rb +1 -1
- data/lib/rubocop/config.rb +1 -1
- data/lib/rubocop/config_finder.rb +1 -1
- data/lib/rubocop/config_store.rb +1 -1
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +9 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -2
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +28 -3
- data/lib/rubocop/cop/layout/space_around_keyword.rb +3 -1
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -0
- data/lib/rubocop/cop/lint/constant_reassignment.rb +59 -9
- data/lib/rubocop/cop/lint/duplicate_methods.rb +50 -8
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +6 -1
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +8 -1
- data/lib/rubocop/cop/lint/empty_when.rb +8 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +16 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -0
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -0
- data/lib/rubocop/cop/lint/useless_constant_scoping.rb +4 -4
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +2 -0
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +6 -5
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
- data/lib/rubocop/cop/registry.rb +20 -13
- data/lib/rubocop/cop/style/and_or.rb +1 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +25 -7
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +23 -31
- data/lib/rubocop/cop/style/collection_compact.rb +36 -16
- data/lib/rubocop/cop/style/concat_array_literals.rb +2 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +0 -4
- data/lib/rubocop/cop/style/empty_class_definition.rb +24 -2
- data/lib/rubocop/cop/style/file_open.rb +1 -1
- data/lib/rubocop/cop/style/global_vars.rb +1 -1
- data/lib/rubocop/cop/style/hash_lookup_method.rb +7 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -0
- data/lib/rubocop/cop/style/if_with_semicolon.rb +7 -5
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +2 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -3
- data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +5 -11
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/redundant_each.rb +3 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +19 -20
- data/lib/rubocop/cop/style/redundant_percent_q.rb +4 -1
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +0 -5
- data/lib/rubocop/cop/style/safe_navigation.rb +7 -7
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +4 -3
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -0
- data/lib/rubocop/cop/style/yoda_expression.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +1 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +10 -3
- data/lib/rubocop/mcp/server.rb +25 -1
- data/lib/rubocop/path_util.rb +14 -2
- data/lib/rubocop/plugin/loader.rb +1 -1
- data/lib/rubocop/result_cache.rb +10 -1
- data/lib/rubocop/rspec/shared_contexts.rb +11 -2
- data/lib/rubocop/runner.rb +8 -3
- data/lib/rubocop/server/core.rb +2 -0
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/version.rb +2 -2
- metadata +3 -17
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a8991e66e8594a8ba30b4122a2990df1d7f610e3e51515b016e68432bcd94855
|
|
4
|
+
data.tar.gz: dadc1936594395ec71c4b628867d1ed2e2f585fcafedb886e5493d0b81c4cb2f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f95a7d048724e297f77b42444bd2eae15889bfa1b9b815fabbde131af75e99e114ab6ba2b4c0d078c937be9abd899ec7d9fb0650354b4bfd3cfb5a554f4bcfc3
|
|
7
|
+
data.tar.gz: ed088266152e384f4c2c82dead8363ced3c990b6492a4b4652f98a548ec16b0c57da73e1295dbbc302b00c5affd3fe2e540d9c012221068449d733d1c812139c
|
data/config/default.yml
CHANGED
|
@@ -3,20 +3,16 @@
|
|
|
3
3
|
AllCops:
|
|
4
4
|
RubyInterpreters:
|
|
5
5
|
- ruby
|
|
6
|
-
- macruby
|
|
7
6
|
- rake
|
|
8
7
|
- jruby
|
|
9
|
-
- rbx
|
|
10
8
|
# Include common Ruby source files.
|
|
11
9
|
Include:
|
|
12
10
|
- '**/*.rb'
|
|
13
11
|
- '**/*.arb'
|
|
14
12
|
- '**/*.axlsx'
|
|
15
13
|
- '**/*.builder'
|
|
16
|
-
- '**/*.fcgi'
|
|
17
14
|
- '**/*.gemfile'
|
|
18
15
|
- '**/*.gemspec'
|
|
19
|
-
- '**/*.god'
|
|
20
16
|
- '**/*.jb'
|
|
21
17
|
- '**/*.jbuilder'
|
|
22
18
|
- '**/*.mspec'
|
|
@@ -25,15 +21,12 @@ AllCops:
|
|
|
25
21
|
- '**/*.podspec'
|
|
26
22
|
- '**/*.rabl'
|
|
27
23
|
- '**/*.rake'
|
|
28
|
-
- '**/*.rbuild'
|
|
29
24
|
- '**/*.rbw'
|
|
30
|
-
- '**/*.rbx'
|
|
31
25
|
- '**/*.ru'
|
|
32
26
|
- '**/*.ruby'
|
|
33
27
|
- '**/*.schema'
|
|
34
28
|
- '**/*.spec'
|
|
35
29
|
- '**/*.thor'
|
|
36
|
-
- '**/*.watchr'
|
|
37
30
|
- '**/.irbrc'
|
|
38
31
|
- '**/.pryrc'
|
|
39
32
|
- '**/.simplecov'
|
|
@@ -43,7 +36,6 @@ AllCops:
|
|
|
43
36
|
- '**/Brewfile'
|
|
44
37
|
- '**/Buildfile'
|
|
45
38
|
- '**/Capfile'
|
|
46
|
-
- '**/Cheffile'
|
|
47
39
|
- '**/Dangerfile'
|
|
48
40
|
- '**/Deliverfile'
|
|
49
41
|
- '**/Fastfile'
|
|
@@ -60,7 +52,6 @@ AllCops:
|
|
|
60
52
|
- '**/Snapfile'
|
|
61
53
|
- '**/Steepfile'
|
|
62
54
|
- '**/Thorfile'
|
|
63
|
-
- '**/Vagabondfile'
|
|
64
55
|
- '**/Vagrantfile'
|
|
65
56
|
Exclude:
|
|
66
57
|
- 'node_modules/**/*'
|
|
@@ -117,7 +108,7 @@ AllCops:
|
|
|
117
108
|
# line option.
|
|
118
109
|
UseCache: true
|
|
119
110
|
# Threshold for how many files can be stored in the result cache before some
|
|
120
|
-
# of the files are automatically removed.
|
|
111
|
+
# of the files are automatically removed. Set to false to disable cache pruning.
|
|
121
112
|
MaxFilesInCache: 20000
|
|
122
113
|
# The cache will be stored in "rubocop_cache" under this directory. If
|
|
123
114
|
# CacheRootDirectory is ~ (nil), which it is by default, the root will be
|
|
@@ -3993,11 +3984,13 @@ Style/EmptyClassDefinition:
|
|
|
3993
3984
|
Description: 'Enforces consistent style for empty class definitions.'
|
|
3994
3985
|
Enabled: pending
|
|
3995
3986
|
VersionAdded: '1.84'
|
|
3987
|
+
VersionChanged: '1.86'
|
|
3996
3988
|
EnforcedStyle: class_keyword
|
|
3997
3989
|
SupportedStyles:
|
|
3998
3990
|
- class_keyword
|
|
3999
3991
|
- class_new
|
|
4000
3992
|
- class_definition # Deprecated.
|
|
3993
|
+
AllowedParentClasses: []
|
|
4001
3994
|
|
|
4002
3995
|
Style/EmptyElse:
|
|
4003
3996
|
Description: 'Avoid empty else-clauses.'
|
data/lib/rubocop/cache_config.rb
CHANGED
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
|
35
35
|
root_dir do
|
|
36
36
|
next cache_root_override if cache_root_override
|
|
37
37
|
|
|
38
|
-
config_path = ConfigFinder.find_config_path(
|
|
38
|
+
config_path = ConfigFinder.find_config_path(PathUtil.pwd)
|
|
39
39
|
file_contents = File.read(config_path)
|
|
40
40
|
|
|
41
41
|
# Returns early if `CacheRootDirectory` is not used before requiring `erb` or `yaml`.
|
|
@@ -153,7 +153,7 @@ module RuboCop
|
|
|
153
153
|
def relative_path_to_todo_from_options_config
|
|
154
154
|
return AUTO_GENERATED_FILE unless @options[:config]
|
|
155
155
|
|
|
156
|
-
base = Pathname.new(
|
|
156
|
+
base = Pathname.new(PathUtil.pwd)
|
|
157
157
|
config_dir = Pathname.new(@options[:config]).realpath.dirname
|
|
158
158
|
|
|
159
159
|
# Don't have the path start with `/`
|
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
|
25
25
|
super
|
|
26
26
|
|
|
27
27
|
# Load the configs so the require()s are done for custom cops
|
|
28
|
-
@config = @config_store.for(
|
|
28
|
+
@config = @config_store.for(PathUtil.pwd)
|
|
29
29
|
|
|
30
30
|
@cop_matchers = @options[:show_cops].map do |pattern|
|
|
31
31
|
if pattern.include?('*')
|
|
@@ -46,7 +46,7 @@ module RuboCop
|
|
|
46
46
|
registry = Cop::Registry.global
|
|
47
47
|
show_all = @cop_matchers.empty?
|
|
48
48
|
|
|
49
|
-
puts "# Available cops (#{registry.length}) + config for #{
|
|
49
|
+
puts "# Available cops (#{registry.length}) + config for #{PathUtil.pwd}: " if show_all
|
|
50
50
|
|
|
51
51
|
registry.departments.sort!.each do |department|
|
|
52
52
|
print_cops_of_department(registry, department, show_all)
|
data/lib/rubocop/config.rb
CHANGED
data/lib/rubocop/config_store.rb
CHANGED
|
@@ -9,7 +9,7 @@ module RuboCop
|
|
|
9
9
|
|
|
10
10
|
# @api private
|
|
11
11
|
COMMON_PARAMS = %w[Exclude Include Severity inherit_mode AutoCorrect StyleGuide Details
|
|
12
|
-
Enabled Reference References].freeze
|
|
12
|
+
Enabled Reference References Safe SafeAutoCorrect].freeze
|
|
13
13
|
# @api private
|
|
14
14
|
INTERNAL_PARAMS = %w[Description StyleGuide
|
|
15
15
|
VersionAdded VersionChanged VersionRemoved
|
|
@@ -52,7 +52,7 @@ module RuboCop
|
|
|
52
52
|
'following the first line of a multi-line method call.'
|
|
53
53
|
|
|
54
54
|
def on_send(node)
|
|
55
|
-
return if !multiple_arguments?(node) || (node.
|
|
55
|
+
return if !multiple_arguments?(node) || (node.call_type? && node.method?(:[]=)) ||
|
|
56
56
|
autocorrect_incompatible_with_other_cops?
|
|
57
57
|
|
|
58
58
|
items = flattened_arguments(node)
|
|
@@ -112,7 +112,7 @@ module RuboCop
|
|
|
112
112
|
end
|
|
113
113
|
|
|
114
114
|
def last_heredoc_line(node)
|
|
115
|
-
if node.
|
|
115
|
+
if node.call_type?
|
|
116
116
|
node.arguments.select { |arg| heredoc?(arg) }.map { |arg| arg.loc.heredoc_end.line }.max
|
|
117
117
|
elsif heredoc?(node)
|
|
118
118
|
node.loc.heredoc_end.line
|
|
@@ -60,6 +60,11 @@ module RuboCop
|
|
|
60
60
|
END_OF_HEREDOC_LINE = 1
|
|
61
61
|
SIMPLE_DIRECTIVE_COMMENT_PATTERN = /\A# *:nocov:\z/.freeze
|
|
62
62
|
|
|
63
|
+
# @!method guard_clause_branch?(node)
|
|
64
|
+
def_node_matcher :guard_clause_branch?, <<~PATTERN
|
|
65
|
+
{(send nil? {:raise :fail} ...) return break next}
|
|
66
|
+
PATTERN
|
|
67
|
+
|
|
63
68
|
def on_if(node)
|
|
64
69
|
return if correct_style?(node)
|
|
65
70
|
return if multiple_statements_on_line?(node)
|
|
@@ -97,14 +102,16 @@ module RuboCop
|
|
|
97
102
|
end
|
|
98
103
|
|
|
99
104
|
def correct_style?(node)
|
|
100
|
-
!
|
|
105
|
+
!node.if_branch&.guard_clause? ||
|
|
101
106
|
next_line_rescue_or_ensure?(node) ||
|
|
102
107
|
next_sibling_parent_empty_or_else?(node) ||
|
|
103
108
|
next_sibling_empty_or_guard_clause?(node)
|
|
104
109
|
end
|
|
105
110
|
|
|
106
111
|
def contains_guard_clause?(node)
|
|
107
|
-
node.if_branch
|
|
112
|
+
return false unless (branch = node.if_branch)
|
|
113
|
+
|
|
114
|
+
guard_clause_branch?(branch)
|
|
108
115
|
end
|
|
109
116
|
|
|
110
117
|
def next_line_empty_or_allowed_directive_comment?(line)
|
|
@@ -185,7 +185,7 @@ module RuboCop
|
|
|
185
185
|
end
|
|
186
186
|
|
|
187
187
|
def empty_line_between_macros
|
|
188
|
-
cop_config.fetch('DefLikeMacros', []).map(&:to_sym)
|
|
188
|
+
@empty_line_between_macros ||= cop_config.fetch('DefLikeMacros', []).map(&:to_sym).freeze
|
|
189
189
|
end
|
|
190
190
|
|
|
191
191
|
def macro_candidate?(node)
|
|
@@ -129,8 +129,9 @@ module RuboCop
|
|
|
129
129
|
# we check if it's an if/unless/while/until.
|
|
130
130
|
return unless (rhs = first_part_of_call_chain(rhs))
|
|
131
131
|
|
|
132
|
-
# If `rhs` is a `begin` node
|
|
133
|
-
|
|
132
|
+
# If `rhs` is a `begin` node or a logical operator,
|
|
133
|
+
# unwrap to find the leading conditional.
|
|
134
|
+
rhs = rhs.child_nodes.first while rhs.type?(:begin, :or, :and)
|
|
134
135
|
|
|
135
136
|
return unless rhs.conditional?
|
|
136
137
|
return if rhs.if_type? && rhs.ternary?
|
|
@@ -128,12 +128,15 @@ module RuboCop
|
|
|
128
128
|
if hash_pair_indented?(node, pair_ancestor, given_style)
|
|
129
129
|
return check_hash_pair_indented_style(rhs, pair_ancestor)
|
|
130
130
|
end
|
|
131
|
-
|
|
132
|
-
return false if !pair_ancestor && not_for_this_cop?(node)
|
|
131
|
+
return false if skip_for_context?(node, pair_ancestor)
|
|
133
132
|
|
|
134
133
|
check_regular_indentation(node, lhs, rhs, given_style)
|
|
135
134
|
end
|
|
136
135
|
|
|
136
|
+
def skip_for_context?(node, pair_ancestor)
|
|
137
|
+
pair_ancestor ? inside_multiline_chain_arg?(node) : not_for_this_cop?(node)
|
|
138
|
+
end
|
|
139
|
+
|
|
137
140
|
def hash_pair_aligned?(pair_ancestor, given_style)
|
|
138
141
|
pair_ancestor && given_style == :aligned
|
|
139
142
|
end
|
|
@@ -152,7 +155,10 @@ module RuboCop
|
|
|
152
155
|
end
|
|
153
156
|
|
|
154
157
|
def check_hash_pair_indentation(node, lhs, rhs)
|
|
155
|
-
@base = find_hash_pair_alignment_base(node)
|
|
158
|
+
@base = find_hash_pair_alignment_base(node)
|
|
159
|
+
return false if !@base && inside_multiline_chain_arg?(node)
|
|
160
|
+
|
|
161
|
+
@base ||= lhs.source_range
|
|
156
162
|
return if aligned_with_first_line_dot?(node, rhs)
|
|
157
163
|
|
|
158
164
|
calculate_column_delta_offense(rhs, @base.column)
|
|
@@ -166,6 +172,25 @@ module RuboCop
|
|
|
166
172
|
first_call.loc.dot.join(first_call.loc.selector)
|
|
167
173
|
end
|
|
168
174
|
|
|
175
|
+
def inside_multiline_chain_arg?(node)
|
|
176
|
+
enclosing_call = find_enclosing_chain_call(node)
|
|
177
|
+
return false unless enclosing_call
|
|
178
|
+
|
|
179
|
+
!same_line?(enclosing_call.loc.selector, enclosing_call.receiver.source_range)
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def find_enclosing_chain_call(node)
|
|
183
|
+
hash_ancestor = find_pair_ancestor(node).parent
|
|
184
|
+
enclosing_call = hash_ancestor.parent
|
|
185
|
+
return unless hash_arg_in_chain?(enclosing_call, hash_ancestor)
|
|
186
|
+
|
|
187
|
+
enclosing_call
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def hash_arg_in_chain?(call, hash_node)
|
|
191
|
+
call&.call_type? && call.receiver != hash_node && call.loc?(:dot)
|
|
192
|
+
end
|
|
193
|
+
|
|
169
194
|
def aligned_with_first_line_dot?(node, rhs)
|
|
170
195
|
return false unless rhs.source.start_with?('.', '&.')
|
|
171
196
|
|
|
@@ -47,9 +47,11 @@ module RuboCop
|
|
|
47
47
|
check(node, [:operator].freeze) if node.keyword?
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
def on_block(node)
|
|
50
|
+
def on_block(node)
|
|
51
51
|
check(node, %i[begin end].freeze)
|
|
52
52
|
end
|
|
53
|
+
alias on_numblock on_block
|
|
54
|
+
alias on_itblock on_block
|
|
53
55
|
|
|
54
56
|
def on_break(node)
|
|
55
57
|
check(node, [:keyword].freeze)
|
|
@@ -26,6 +26,7 @@ module RuboCop
|
|
|
26
26
|
|
|
27
27
|
MSG_REQUIRE_SPACE = 'Use a space between `->` and `(` in lambda literals.'
|
|
28
28
|
MSG_REQUIRE_NO_SPACE = 'Do not use spaces between `->` and `(` in lambda literals.'
|
|
29
|
+
RESTRICT_ON_SEND = %i[lambda].freeze
|
|
29
30
|
|
|
30
31
|
def on_send(node)
|
|
31
32
|
return unless arrow_lambda_with_args?(node)
|
|
@@ -6,8 +6,11 @@ module RuboCop
|
|
|
6
6
|
# Checks for constant reassignments.
|
|
7
7
|
#
|
|
8
8
|
# Emulates Ruby's runtime warning "already initialized constant X"
|
|
9
|
-
# when a constant is reassigned in the same file and namespace
|
|
10
|
-
#
|
|
9
|
+
# when a constant is reassigned in the same file and namespace.
|
|
10
|
+
#
|
|
11
|
+
# The cop tracks constants defined via `NAME = value` syntax as well as
|
|
12
|
+
# class/module keyword definitions. It detects reassignment when a constant
|
|
13
|
+
# is first defined one way and then redefined using the `NAME = value` syntax.
|
|
11
14
|
#
|
|
12
15
|
# The cop cannot catch all offenses, like, for example, when a constant
|
|
13
16
|
# is reassigned in another file, or when using metaprogramming (`Module#const_set`).
|
|
@@ -36,6 +39,14 @@ module RuboCop
|
|
|
36
39
|
# X = :bar
|
|
37
40
|
# end
|
|
38
41
|
#
|
|
42
|
+
# # bad
|
|
43
|
+
# class FooError < StandardError; end
|
|
44
|
+
# FooError = Class.new(RuntimeError)
|
|
45
|
+
#
|
|
46
|
+
# # bad
|
|
47
|
+
# module M; end
|
|
48
|
+
# M = 1
|
|
49
|
+
#
|
|
39
50
|
# # good - keep only one assignment
|
|
40
51
|
# X = :bar
|
|
41
52
|
#
|
|
@@ -69,16 +80,30 @@ module RuboCop
|
|
|
69
80
|
|
|
70
81
|
# @!method remove_constant(node)
|
|
71
82
|
def_node_matcher :remove_constant, <<~PATTERN
|
|
72
|
-
(send
|
|
83
|
+
(send {nil? self} :remove_const
|
|
73
84
|
({sym str} $_))
|
|
74
85
|
PATTERN
|
|
75
86
|
|
|
87
|
+
def on_class(node)
|
|
88
|
+
return unless unconditional_definition?(node)
|
|
89
|
+
|
|
90
|
+
constant_definitions[definition_name(node)] ||= :class
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def on_module(node)
|
|
94
|
+
return unless unconditional_definition?(node)
|
|
95
|
+
|
|
96
|
+
constant_definitions[definition_name(node)] ||= :module
|
|
97
|
+
end
|
|
98
|
+
|
|
76
99
|
def on_casgn(node)
|
|
77
100
|
return unless fixed_constant_path?(node)
|
|
78
101
|
return unless simple_assignment?(node)
|
|
79
|
-
return if constant_names.add?(fully_qualified_constant_name(node))
|
|
80
102
|
|
|
81
|
-
|
|
103
|
+
name = fully_qualified_constant_name(node)
|
|
104
|
+
return constant_definitions[name] = :casgn unless constant_definitions.key?(name)
|
|
105
|
+
|
|
106
|
+
add_offense(node, message: format(MSG, constant: constant_display_name(node)))
|
|
82
107
|
end
|
|
83
108
|
|
|
84
109
|
def on_send(node)
|
|
@@ -90,7 +115,7 @@ module RuboCop
|
|
|
90
115
|
|
|
91
116
|
return if namespaces.none?
|
|
92
117
|
|
|
93
|
-
|
|
118
|
+
constant_definitions.delete(fully_qualified_name_for(namespaces, constant))
|
|
94
119
|
end
|
|
95
120
|
|
|
96
121
|
private
|
|
@@ -104,7 +129,7 @@ module RuboCop
|
|
|
104
129
|
return true if ancestor.type?(:module, :class)
|
|
105
130
|
|
|
106
131
|
ancestor.begin_type? || ancestor.literal? || ancestor.casgn_type? ||
|
|
107
|
-
freeze_method?(ancestor)
|
|
132
|
+
ancestor.type?(:masgn, :mlhs) || freeze_method?(ancestor)
|
|
108
133
|
end
|
|
109
134
|
end
|
|
110
135
|
|
|
@@ -128,6 +153,10 @@ module RuboCop
|
|
|
128
153
|
['', *namespaces, constant].join('::')
|
|
129
154
|
end
|
|
130
155
|
|
|
156
|
+
def constant_display_name(node)
|
|
157
|
+
[*constant_namespaces(node), node.name].join('::')
|
|
158
|
+
end
|
|
159
|
+
|
|
131
160
|
def constant_namespaces(node)
|
|
132
161
|
node.each_path.select(&:const_type?).map(&:short_name)
|
|
133
162
|
end
|
|
@@ -139,8 +168,29 @@ module RuboCop
|
|
|
139
168
|
.reverse
|
|
140
169
|
end
|
|
141
170
|
|
|
142
|
-
def
|
|
143
|
-
|
|
171
|
+
def unconditional_definition?(node)
|
|
172
|
+
node.each_ancestor.all? do |ancestor|
|
|
173
|
+
ancestor.type?(:begin, :module, :class)
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def definition_name(node)
|
|
178
|
+
identifier = node.identifier
|
|
179
|
+
|
|
180
|
+
if identifier.namespace&.cbase_type?
|
|
181
|
+
fully_qualified_name_for([], identifier.short_name)
|
|
182
|
+
else
|
|
183
|
+
namespaces = ancestor_namespaces(node) + identifier_namespaces(identifier)
|
|
184
|
+
fully_qualified_name_for(namespaces, identifier.short_name)
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def identifier_namespaces(identifier)
|
|
189
|
+
identifier.each_path.select(&:const_type?).map(&:short_name)
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
def constant_definitions
|
|
193
|
+
@constant_definitions ||= {}
|
|
144
194
|
end
|
|
145
195
|
end
|
|
146
196
|
end
|
|
@@ -197,6 +197,13 @@ module RuboCop
|
|
|
197
197
|
# @!method sym_name(node)
|
|
198
198
|
def_node_matcher :sym_name, '(sym $_name)'
|
|
199
199
|
|
|
200
|
+
# @!method class_or_module_new_block?(node)
|
|
201
|
+
def_node_matcher :class_or_module_new_block?, <<~PATTERN
|
|
202
|
+
(block
|
|
203
|
+
(send (const _ {:Class :Module}) :new ...)
|
|
204
|
+
...)
|
|
205
|
+
PATTERN
|
|
206
|
+
|
|
200
207
|
def on_send(node) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
201
208
|
name, original_name = alias_method?(node)
|
|
202
209
|
|
|
@@ -233,9 +240,12 @@ module RuboCop
|
|
|
233
240
|
|
|
234
241
|
def check_self_receiver(node, name)
|
|
235
242
|
enclosing = node.parent_module_name
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
243
|
+
if enclosing
|
|
244
|
+
found_method(node, "#{enclosing}.#{name}")
|
|
245
|
+
elsif (anon_block = anonymous_class_block(node))
|
|
246
|
+
scope = qualified_name(anon_block.parent_module_name, nil, 'Object')
|
|
247
|
+
found_method(node, "#{scope}.#{name}", scope_id: anon_block_scope_id(anon_block))
|
|
248
|
+
end
|
|
239
249
|
end
|
|
240
250
|
|
|
241
251
|
def inside_condition?(node)
|
|
@@ -274,16 +284,45 @@ module RuboCop
|
|
|
274
284
|
end
|
|
275
285
|
|
|
276
286
|
def found_instance_method(node, name)
|
|
277
|
-
|
|
287
|
+
if (scope = node.parent_module_name)
|
|
288
|
+
found_method(node, "#{humanize_scope(scope)}#{name}")
|
|
289
|
+
elsif (anon_block = anonymous_class_block(node))
|
|
290
|
+
base = qualified_name(anon_block.parent_module_name, nil, 'Object')
|
|
291
|
+
scope = node.each_ancestor(:sclass).any? ? "#<Class:#{base}>" : base
|
|
292
|
+
found_method(
|
|
293
|
+
node, "#{humanize_scope(scope)}#{name}", scope_id: anon_block_scope_id(anon_block)
|
|
294
|
+
)
|
|
295
|
+
else
|
|
296
|
+
found_sclass_method(node, name)
|
|
297
|
+
end
|
|
298
|
+
end
|
|
278
299
|
|
|
279
|
-
|
|
300
|
+
def humanize_scope(scope)
|
|
280
301
|
scope = scope.sub(
|
|
281
302
|
/(?:(?<name>.*)::)#<Class:\k<name>>|#<Class:(?<name>.*)>(?:::)?/,
|
|
282
303
|
'\k<name>.'
|
|
283
304
|
)
|
|
284
|
-
scope
|
|
305
|
+
scope.end_with?('.') ? scope : "#{scope}#"
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def anonymous_class_block(node)
|
|
309
|
+
first_block = node.each_ancestor(:block).first
|
|
310
|
+
return unless class_or_module_new_block?(first_block)
|
|
311
|
+
return if first_block.parent&.type?(:lvasgn, :block)
|
|
312
|
+
return if node.each_ancestor(:sclass).any? { |s| !s.children.first.self_type? }
|
|
313
|
+
|
|
314
|
+
first_block
|
|
315
|
+
end
|
|
285
316
|
|
|
286
|
-
|
|
317
|
+
def anon_block_scope_id(anon_block)
|
|
318
|
+
parent = anon_block.parent
|
|
319
|
+
return unless parent&.call_type?
|
|
320
|
+
|
|
321
|
+
if parent.receiver
|
|
322
|
+
"#{parent.receiver.source}.#{parent.method_name}"
|
|
323
|
+
else
|
|
324
|
+
source_location(anon_block)
|
|
325
|
+
end
|
|
287
326
|
end
|
|
288
327
|
|
|
289
328
|
def found_sclass_method(node, name)
|
|
@@ -296,8 +335,10 @@ module RuboCop
|
|
|
296
335
|
found_method(node, "#{singleton_receiver_node.method_name}.#{name}")
|
|
297
336
|
end
|
|
298
337
|
|
|
299
|
-
|
|
338
|
+
# rubocop:disable Metrics/AbcSize
|
|
339
|
+
def found_method(node, method_name, scope_id: nil)
|
|
300
340
|
key = method_key(node, method_name)
|
|
341
|
+
key = "#{key}@#{scope_id}" if scope_id
|
|
301
342
|
scope = node.each_ancestor(:rescue, :ensure).first&.type
|
|
302
343
|
|
|
303
344
|
if @definitions.key?(key)
|
|
@@ -314,6 +355,7 @@ module RuboCop
|
|
|
314
355
|
@definitions[key] = node
|
|
315
356
|
end
|
|
316
357
|
end
|
|
358
|
+
# rubocop:enable Metrics/AbcSize
|
|
317
359
|
|
|
318
360
|
def method_key(node, method_name)
|
|
319
361
|
if (ancestor_def = node.each_ancestor(:any_def).first)
|
|
@@ -70,7 +70,7 @@ module RuboCop
|
|
|
70
70
|
|
|
71
71
|
def on_if(node)
|
|
72
72
|
return if node.body || same_line?(node.loc.begin, node.loc.end)
|
|
73
|
-
return if
|
|
73
|
+
return if allow_comments?(node)
|
|
74
74
|
|
|
75
75
|
range = offense_range(node)
|
|
76
76
|
|
|
@@ -83,6 +83,11 @@ module RuboCop
|
|
|
83
83
|
|
|
84
84
|
private
|
|
85
85
|
|
|
86
|
+
def allow_comments?(node)
|
|
87
|
+
cop_config['AllowComments'] && contains_comments?(node) &&
|
|
88
|
+
!comments_contain_disables?(node, name)
|
|
89
|
+
end
|
|
90
|
+
|
|
86
91
|
def offense_range(node)
|
|
87
92
|
if node.loc.else
|
|
88
93
|
node.source_range.begin.join(node.loc.else.begin)
|
|
@@ -53,11 +53,18 @@ module RuboCop
|
|
|
53
53
|
def on_case_match(node)
|
|
54
54
|
node.in_pattern_branches.each do |branch|
|
|
55
55
|
next if branch.body
|
|
56
|
-
next if
|
|
56
|
+
next if allow_comments?(branch)
|
|
57
57
|
|
|
58
58
|
add_offense(branch)
|
|
59
59
|
end
|
|
60
60
|
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
def allow_comments?(node)
|
|
65
|
+
cop_config['AllowComments'] && contains_comments?(node) &&
|
|
66
|
+
!comments_contain_disables?(node, name)
|
|
67
|
+
end
|
|
61
68
|
end
|
|
62
69
|
end
|
|
63
70
|
end
|
|
@@ -50,11 +50,18 @@ module RuboCop
|
|
|
50
50
|
def on_case(node)
|
|
51
51
|
node.when_branches.each do |when_node|
|
|
52
52
|
next if when_node.body
|
|
53
|
-
next if
|
|
53
|
+
next if allow_comments?(when_node)
|
|
54
54
|
|
|
55
55
|
add_offense(when_node)
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
|
+
|
|
59
|
+
private
|
|
60
|
+
|
|
61
|
+
def allow_comments?(node)
|
|
62
|
+
cop_config['AllowComments'] && contains_comments?(node) &&
|
|
63
|
+
!comments_contain_disables?(node, name)
|
|
64
|
+
end
|
|
58
65
|
end
|
|
59
66
|
end
|
|
60
67
|
end
|
|
@@ -162,7 +162,7 @@ module RuboCop
|
|
|
162
162
|
end
|
|
163
163
|
|
|
164
164
|
def allow_receiver?(receiver)
|
|
165
|
-
if receiver.numeric_type? || (receiver.
|
|
165
|
+
if receiver.numeric_type? || (receiver.call_type? &&
|
|
166
166
|
(conversion_method?(receiver.method_name) ||
|
|
167
167
|
allowed_method_name?(receiver.method_name)))
|
|
168
168
|
true
|
|
@@ -62,6 +62,22 @@ module RuboCop
|
|
|
62
62
|
# do_something if attrs.respond_to?(:[])
|
|
63
63
|
#
|
|
64
64
|
# # bad
|
|
65
|
+
# foo&.bar ? foo&.bar.baz : qux
|
|
66
|
+
#
|
|
67
|
+
# # good
|
|
68
|
+
# foo&.bar ? foo.bar.baz : qux
|
|
69
|
+
#
|
|
70
|
+
# # bad
|
|
71
|
+
# if foo&.bar
|
|
72
|
+
# foo&.bar.baz
|
|
73
|
+
# end
|
|
74
|
+
#
|
|
75
|
+
# # good
|
|
76
|
+
# if foo&.bar
|
|
77
|
+
# foo.bar.baz
|
|
78
|
+
# end
|
|
79
|
+
#
|
|
80
|
+
# # bad
|
|
65
81
|
# while node&.is_a?(BeginNode)
|
|
66
82
|
# node = node.parent
|
|
67
83
|
# end
|