rubocop 1.75.1 → 1.77.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 +20 -14
- data/config/default.yml +103 -25
- data/config/obsoletion.yml +6 -3
- data/lib/rubocop/config_validator.rb +6 -6
- data/lib/rubocop/cop/autocorrect_logic.rb +18 -10
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
- data/lib/rubocop/cop/correctors/parentheses_corrector.rb +5 -2
- data/lib/rubocop/cop/gemspec/attribute_assignment.rb +91 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +37 -15
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/require_mfa.rb +15 -1
- data/lib/rubocop/cop/internal_affairs/example_description.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +4 -4
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +2 -0
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +6 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/class_structure.rb +35 -0
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -2
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -3
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/leading_comment_space.rb +13 -1
- data/lib/rubocop/cop/layout/line_length.rb +26 -5
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +2 -4
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +10 -0
- data/lib/rubocop/cop/layout/space_before_brackets.rb +5 -38
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +12 -3
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +3 -0
- data/lib/rubocop/cop/lint/ambiguous_range.rb +5 -0
- data/lib/rubocop/cop/lint/array_literal_in_regexp.rb +2 -3
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -5
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +86 -5
- data/lib/rubocop/cop/lint/empty_interpolation.rb +3 -1
- data/lib/rubocop/cop/lint/float_comparison.rb +31 -4
- data/lib/rubocop/cop/lint/identity_comparison.rb +19 -15
- data/lib/rubocop/cop/lint/literal_as_condition.rb +31 -25
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +1 -1
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +2 -2
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_type_conversion.rb +7 -4
- data/lib/rubocop/cop/lint/return_in_void_context.rb +7 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +4 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +25 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +5 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +1 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +29 -4
- data/lib/rubocop/cop/lint/useless_assignment.rb +2 -0
- data/lib/rubocop/cop/lint/useless_default_value_argument.rb +90 -0
- data/lib/rubocop/cop/lint/useless_or.rb +98 -0
- data/lib/rubocop/cop/lint/useless_rescue.rb +1 -1
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +3 -3
- data/lib/rubocop/cop/lint/void.rb +2 -2
- data/lib/rubocop/cop/message_annotator.rb +7 -3
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +1 -1
- data/lib/rubocop/cop/mixin/def_node.rb +1 -1
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -2
- data/lib/rubocop/cop/mixin/gemspec_help.rb +22 -0
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +15 -14
- data/lib/rubocop/cop/mixin/line_length_help.rb +24 -8
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -0
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_comma.rb +9 -5
- data/lib/rubocop/cop/naming/file_name.rb +2 -2
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +1 -1
- data/lib/rubocop/cop/naming/predicate_method.rb +281 -0
- data/lib/rubocop/cop/naming/{predicate_name.rb → predicate_prefix.rb} +4 -4
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -10
- data/lib/rubocop/cop/style/arguments_forwarding.rb +8 -5
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/class_and_module_children.rb +19 -3
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -1
- data/lib/rubocop/cop/style/collection_querying.rb +167 -0
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/commented_keyword.rb +2 -2
- data/lib/rubocop/cop/style/comparable_between.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +18 -4
- data/lib/rubocop/cop/style/data_inheritance.rb +7 -0
- data/lib/rubocop/cop/style/def_with_parentheses.rb +18 -5
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/empty_literal.rb +4 -0
- data/lib/rubocop/cop/style/empty_string_inside_interpolation.rb +100 -0
- data/lib/rubocop/cop/style/eval_with_location.rb +3 -3
- data/lib/rubocop/cop/style/explicit_block_argument.rb +2 -2
- data/lib/rubocop/cop/style/exponential_notation.rb +2 -2
- data/lib/rubocop/cop/style/fetch_env_var.rb +32 -6
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +3 -2
- data/lib/rubocop/cop/style/global_std_stream.rb +3 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +12 -3
- data/lib/rubocop/cop/style/hash_fetch_chain.rb +0 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +3 -0
- data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
- data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +3 -3
- data/lib/rubocop/cop/style/if_unless_modifier.rb +33 -6
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +4 -7
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +1 -1
- data/lib/rubocop/cop/style/it_block_parameter.rb +33 -14
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
- data/lib/rubocop/cop/style/lambda_call.rb +7 -2
- data/lib/rubocop/cop/style/map_into_array.rb +3 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +11 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -3
- data/lib/rubocop/cop/style/min_max_comparison.rb +13 -5
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -0
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/redundant_array_flatten.rb +50 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +13 -1
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +6 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +0 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +41 -3
- data/lib/rubocop/cop/style/redundant_self.rb +8 -5
- data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
- data/lib/rubocop/cop/style/return_nil.rb +2 -2
- data/lib/rubocop/cop/style/safe_navigation.rb +42 -14
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +6 -3
- data/lib/rubocop/cop/style/string_concatenation.rb +1 -2
- data/lib/rubocop/cop/style/struct_inheritance.rb +8 -1
- data/lib/rubocop/cop/style/super_arguments.rb +1 -2
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +7 -1
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +1 -1
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +1 -1
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +7 -3
- data/lib/rubocop/cop/variable_force/variable.rb +1 -1
- data/lib/rubocop/cops_documentation_generator.rb +6 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +1 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +4 -4
- data/lib/rubocop/magic_comment.rb +8 -0
- data/lib/rubocop/rspec/cop_helper.rb +2 -2
- data/lib/rubocop/rspec/expect_offense.rb +9 -3
- data/lib/rubocop/rspec/shared_contexts.rb +1 -2
- data/lib/rubocop/server/cache.rb +13 -10
- data/lib/rubocop/target_finder.rb +6 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +8 -1
- data/lib/ruby_lsp/rubocop/addon.rb +2 -2
- metadata +14 -7
@@ -23,6 +23,14 @@ module RuboCop
|
|
23
23
|
# # good (method calls possibly can return different results)
|
24
24
|
# hash[foo] = hash[foo]
|
25
25
|
#
|
26
|
+
# @example AllowRBSInlineAnnotation:true
|
27
|
+
# # good
|
28
|
+
# foo = foo #: Integer
|
29
|
+
# foo, bar = foo, bar #: Integer
|
30
|
+
# Foo = Foo #: Integer
|
31
|
+
# hash['foo'] = hash['foo'] #: Integer
|
32
|
+
# obj.attr = obj.attr #: Integer
|
33
|
+
#
|
26
34
|
class SelfAssignment < Base
|
27
35
|
MSG = 'Self-assignment detected.'
|
28
36
|
|
@@ -34,6 +42,8 @@ module RuboCop
|
|
34
42
|
}.freeze
|
35
43
|
|
36
44
|
def on_send(node)
|
45
|
+
return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.receiver)
|
46
|
+
|
37
47
|
if node.method?(:[]=)
|
38
48
|
handle_key_assignment(node) if node.arguments.size == 2
|
39
49
|
elsif node.assignment_method?
|
@@ -44,6 +54,7 @@ module RuboCop
|
|
44
54
|
|
45
55
|
def on_lvasgn(node)
|
46
56
|
return unless node.rhs
|
57
|
+
return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.rhs)
|
47
58
|
|
48
59
|
rhs_type = ASSIGNMENT_TYPE_TO_RHS_TYPE[node.type]
|
49
60
|
|
@@ -55,16 +66,22 @@ module RuboCop
|
|
55
66
|
|
56
67
|
def on_casgn(node)
|
57
68
|
return unless node.rhs&.const_type?
|
69
|
+
return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.rhs)
|
58
70
|
|
59
71
|
add_offense(node) if node.namespace == node.rhs.namespace &&
|
60
72
|
node.short_name == node.rhs.short_name
|
61
73
|
end
|
62
74
|
|
63
75
|
def on_masgn(node)
|
76
|
+
first_lhs = node.lhs.assignments.first
|
77
|
+
return if allow_rbs_inline_annotation? && rbs_inline_annotation?(first_lhs)
|
78
|
+
|
64
79
|
add_offense(node) if multiple_self_assignment?(node)
|
65
80
|
end
|
66
81
|
|
67
82
|
def on_or_asgn(node)
|
83
|
+
return if allow_rbs_inline_annotation? && rbs_inline_annotation?(node.lhs)
|
84
|
+
|
68
85
|
add_offense(node) if rhs_matches_lhs?(node.rhs, node.lhs)
|
69
86
|
end
|
70
87
|
alias on_and_asgn on_or_asgn
|
@@ -108,6 +125,14 @@ module RuboCop
|
|
108
125
|
add_offense(node)
|
109
126
|
end
|
110
127
|
end
|
128
|
+
|
129
|
+
def rbs_inline_annotation?(node)
|
130
|
+
processed_source.ast_with_comments[node].any? { |comment| comment.text.start_with?('#:') }
|
131
|
+
end
|
132
|
+
|
133
|
+
def allow_rbs_inline_annotation?
|
134
|
+
cop_config['AllowRBSInlineAnnotation']
|
135
|
+
end
|
111
136
|
end
|
112
137
|
end
|
113
138
|
end
|
@@ -8,6 +8,11 @@ module RuboCop
|
|
8
8
|
# given by `ruby -cw` prior to Ruby 2.6:
|
9
9
|
# "shadowing outer local variable - foo".
|
10
10
|
#
|
11
|
+
# The cop is now disabled by default to match the upstream Ruby behavior.
|
12
|
+
# It's useful, however, if you'd like to avoid shadowing variables from outer
|
13
|
+
# scopes, which some people consider an anti-pattern that makes it harder
|
14
|
+
# to keep track of what's going on in a program.
|
15
|
+
#
|
11
16
|
# NOTE: Shadowing of variables in block passed to `Ractor.new` is allowed
|
12
17
|
# because `Ractor` should not access outer variables.
|
13
18
|
# eg. following style is encouraged:
|
@@ -116,7 +116,7 @@ module RuboCop
|
|
116
116
|
private
|
117
117
|
|
118
118
|
def comment_between_rescue_and_end?(node)
|
119
|
-
ancestor = node.each_ancestor(:kwbegin, :
|
119
|
+
ancestor = node.each_ancestor(:kwbegin, :any_def, :any_block).first
|
120
120
|
return false unless ancestor
|
121
121
|
|
122
122
|
end_line = ancestor.loc.end&.line || ancestor.loc.last_line
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
40
40
|
# top-level return node's ancestors should not be of block, def, or
|
41
41
|
# defs type.
|
42
42
|
def top_level_return?(return_node)
|
43
|
-
return_node.each_ancestor(:block, :
|
43
|
+
return_node.each_ancestor(:block, :any_def).none?
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
@@ -4,10 +4,10 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Lint
|
6
6
|
# Checks for redundant access modifiers, including those with no
|
7
|
-
# code, those which are repeated,
|
8
|
-
# class or module body.
|
9
|
-
#
|
10
|
-
# are not redundant.
|
7
|
+
# code, those which are repeated, those which are on top-level, and
|
8
|
+
# leading `public` modifiers in a class or module body.
|
9
|
+
# Conditionally-defined methods are considered as always being defined,
|
10
|
+
# and thus access modifiers guarding such methods are not redundant.
|
11
11
|
#
|
12
12
|
# This cop has `ContextCreatingMethods` option. The default setting value
|
13
13
|
# is an empty array that means no method is specified.
|
@@ -58,6 +58,12 @@ module RuboCop
|
|
58
58
|
# private # this is redundant (no following methods are defined)
|
59
59
|
# end
|
60
60
|
#
|
61
|
+
# # bad
|
62
|
+
# private # this is useless (access modifiers have no effect on top-level)
|
63
|
+
#
|
64
|
+
# def method
|
65
|
+
# end
|
66
|
+
#
|
61
67
|
# # good
|
62
68
|
# class Foo
|
63
69
|
# private # this is not redundant (a method is defined)
|
@@ -145,6 +151,17 @@ module RuboCop
|
|
145
151
|
alias on_numblock on_block
|
146
152
|
alias on_itblock on_block
|
147
153
|
|
154
|
+
def on_begin(node)
|
155
|
+
return if node.parent
|
156
|
+
|
157
|
+
node.child_nodes.each do |child|
|
158
|
+
next unless child.send_type? && access_modifier?(child)
|
159
|
+
|
160
|
+
# This call always registers an offense for access modifier `child.method_name`
|
161
|
+
check_send_node(child, child.method_name, true)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
148
165
|
private
|
149
166
|
|
150
167
|
def autocorrect(corrector, node)
|
@@ -257,6 +274,10 @@ module RuboCop
|
|
257
274
|
|
258
275
|
def any_method_definition?(child)
|
259
276
|
cop_config.fetch('MethodCreatingMethods', []).any? do |m|
|
277
|
+
# Some users still have `"included"` in their `MethodCreatingMethods` configurations,
|
278
|
+
# so to prevent Ruby method redefinition warnings let's just skip this value.
|
279
|
+
next if m == 'included'
|
280
|
+
|
260
281
|
matcher_name = :"#{m}_method?"
|
261
282
|
unless respond_to?(matcher_name)
|
262
283
|
self.class.def_node_matcher matcher_name, <<~PATTERN
|
@@ -279,7 +300,11 @@ module RuboCop
|
|
279
300
|
end
|
280
301
|
|
281
302
|
def any_context_creating_methods?(child)
|
303
|
+
# Some users still have `"included"` in their `ContextCreatingMethods` configurations,
|
304
|
+
# so to prevent Ruby method redefinition warnings let's just skip this value.
|
282
305
|
cop_config.fetch('ContextCreatingMethods', []).any? do |m|
|
306
|
+
next if m == 'included'
|
307
|
+
|
283
308
|
matcher_name = :"#{m}_block?"
|
284
309
|
unless respond_to?(matcher_name)
|
285
310
|
self.class.def_node_matcher matcher_name, <<~PATTERN
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks for usage of method `fetch` or `Array.new` with default value argument
|
7
|
+
# and block. In such cases, block will always be used as default value.
|
8
|
+
#
|
9
|
+
# This cop emulates Ruby warning "block supersedes default value argument" which
|
10
|
+
# applies to `Array.new`, `Array#fetch`, `Hash#fetch`, `ENV.fetch` and
|
11
|
+
# `Thread#fetch`.
|
12
|
+
#
|
13
|
+
# A `fetch` call without a receiver is considered a custom method and does not register
|
14
|
+
# an offense.
|
15
|
+
#
|
16
|
+
# @safety
|
17
|
+
# This cop is unsafe because the receiver could have nonstandard implementation
|
18
|
+
# of `fetch`, or be a class other than the one listed above.
|
19
|
+
#
|
20
|
+
# It is also unsafe because default value argument could have side effects:
|
21
|
+
#
|
22
|
+
# [source,ruby]
|
23
|
+
# ----
|
24
|
+
# def x(a) = puts "side effect"
|
25
|
+
# Array.new(5, x(1)) { 2 }
|
26
|
+
# ----
|
27
|
+
#
|
28
|
+
# so removing it would change behavior.
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# # bad
|
32
|
+
# x.fetch(key, default_value) { block_value }
|
33
|
+
# Array.new(size, default_value) { block_value }
|
34
|
+
#
|
35
|
+
# # good
|
36
|
+
# x.fetch(key) { block_value }
|
37
|
+
# Array.new(size) { block_value }
|
38
|
+
#
|
39
|
+
# # also good - in case default value argument is desired instead
|
40
|
+
# x.fetch(key, default_value)
|
41
|
+
# Array.new(size, default_value)
|
42
|
+
#
|
43
|
+
# # good - keyword arguments aren't registered as offenses
|
44
|
+
# x.fetch(key, keyword: :arg) { block_value }
|
45
|
+
#
|
46
|
+
# @example AllowedReceivers: ['Rails.cache']
|
47
|
+
# # good
|
48
|
+
# Rails.cache.fetch(name, options) { block }
|
49
|
+
#
|
50
|
+
class UselessDefaultValueArgument < Base
|
51
|
+
include AllowedReceivers
|
52
|
+
extend AutoCorrector
|
53
|
+
|
54
|
+
MSG = 'Block supersedes default value argument.'
|
55
|
+
|
56
|
+
RESTRICT_ON_SEND = %i[fetch new].freeze
|
57
|
+
|
58
|
+
# @!method default_value_argument_and_block(node)
|
59
|
+
def_node_matcher :default_value_argument_and_block, <<~PATTERN
|
60
|
+
(any_block
|
61
|
+
{
|
62
|
+
(call !nil? :fetch $_key $_default_value)
|
63
|
+
(send (const _ :Array) :new $_size $_default_value)
|
64
|
+
}
|
65
|
+
_args
|
66
|
+
_block_body)
|
67
|
+
PATTERN
|
68
|
+
|
69
|
+
def on_send(node)
|
70
|
+
unless (prev_arg_node, default_value_node = default_value_argument_and_block(node.parent))
|
71
|
+
return
|
72
|
+
end
|
73
|
+
return if allowed_receiver?(node.receiver)
|
74
|
+
return if hash_without_braces?(default_value_node)
|
75
|
+
|
76
|
+
add_offense(default_value_node) do |corrector|
|
77
|
+
corrector.remove(prev_arg_node.source_range.end.join(default_value_node.source_range))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
alias on_csend on_send
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
def hash_without_braces?(node)
|
85
|
+
node.hash_type? && !node.braces?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks for useless OR (`||` and `or`) expressions.
|
7
|
+
#
|
8
|
+
# Some methods always return a truthy value, even when called
|
9
|
+
# on `nil` (e.g. `nil.to_i` evaluates to `0`). Therefore, OR expressions
|
10
|
+
# appended after these methods will never evaluate.
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# x.to_a || fallback
|
16
|
+
# x.to_c || fallback
|
17
|
+
# x.to_d || fallback
|
18
|
+
# x.to_i || fallback
|
19
|
+
# x.to_f || fallback
|
20
|
+
# x.to_h || fallback
|
21
|
+
# x.to_r || fallback
|
22
|
+
# x.to_s || fallback
|
23
|
+
# x.to_sym || fallback
|
24
|
+
# x.intern || fallback
|
25
|
+
# x.inspect || fallback
|
26
|
+
# x.hash || fallback
|
27
|
+
# x.object_id || fallback
|
28
|
+
# x.__id__ || fallback
|
29
|
+
#
|
30
|
+
# x.to_s or fallback
|
31
|
+
#
|
32
|
+
# # good - if fallback is same as return value of method called on nil
|
33
|
+
# x.to_a # nil.to_a returns []
|
34
|
+
# x.to_c # nil.to_c returns (0+0i)
|
35
|
+
# x.to_d # nil.to_d returns 0.0
|
36
|
+
# x.to_i # nil.to_i returns 0
|
37
|
+
# x.to_f # nil.to_f returns 0.0
|
38
|
+
# x.to_h # nil.to_h returns {}
|
39
|
+
# x.to_r # nil.to_r returns (0/1)
|
40
|
+
# x.to_s # nil.to_s returns ''
|
41
|
+
# x.to_sym # nil.to_sym raises an error
|
42
|
+
# x.intern # nil.intern raises an error
|
43
|
+
# x.inspect # nil.inspect returns "nil"
|
44
|
+
# x.hash # nil.hash returns an Integer
|
45
|
+
# x.object_id # nil.object_id returns an Integer
|
46
|
+
# x.__id__ # nil.object_id returns an Integer
|
47
|
+
#
|
48
|
+
# # good - if the intention is not to call the method on nil
|
49
|
+
# x&.to_a || fallback
|
50
|
+
# x&.to_c || fallback
|
51
|
+
# x&.to_d || fallback
|
52
|
+
# x&.to_i || fallback
|
53
|
+
# x&.to_f || fallback
|
54
|
+
# x&.to_h || fallback
|
55
|
+
# x&.to_r || fallback
|
56
|
+
# x&.to_s || fallback
|
57
|
+
# x&.to_sym || fallback
|
58
|
+
# x&.intern || fallback
|
59
|
+
# x&.inspect || fallback
|
60
|
+
# x&.hash || fallback
|
61
|
+
# x&.object_id || fallback
|
62
|
+
# x&.__id__ || fallback
|
63
|
+
#
|
64
|
+
# x&.to_s or fallback
|
65
|
+
#
|
66
|
+
class UselessOr < Base
|
67
|
+
MSG = '`%<rhs>s` will never evaluate because `%<lhs>s` always returns a truthy value.'
|
68
|
+
|
69
|
+
TRUTHY_RETURN_VALUE_METHODS = Set[:to_a, :to_c, :to_d, :to_i, :to_f, :to_h, :to_r,
|
70
|
+
:to_s, :to_sym, :intern, :inspect, :hash, :object_id,
|
71
|
+
:__id__].freeze
|
72
|
+
|
73
|
+
# @!method truthy_return_value_method?(node)
|
74
|
+
def_node_matcher :truthy_return_value_method?, <<~PATTERN
|
75
|
+
(send _ %TRUTHY_RETURN_VALUE_METHODS)
|
76
|
+
PATTERN
|
77
|
+
|
78
|
+
def on_or(node)
|
79
|
+
if truthy_return_value_method?(node.lhs)
|
80
|
+
report_offense(node, node.lhs)
|
81
|
+
elsif truthy_return_value_method?(node.rhs)
|
82
|
+
parent = node.parent
|
83
|
+
parent = parent.parent if parent&.begin_type?
|
84
|
+
|
85
|
+
report_offense(parent, node.rhs) if parent&.or_type?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def report_offense(or_node, truthy_node)
|
92
|
+
add_offense(or_node.loc.operator.join(or_node.rhs.source_range),
|
93
|
+
message: format(MSG, lhs: truthy_node.source, rhs: or_node.rhs.source))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -89,7 +89,7 @@ module RuboCop
|
|
89
89
|
private
|
90
90
|
|
91
91
|
def inspect_def(node, def_node)
|
92
|
-
return if allowed_arguments(def_node.arguments)
|
92
|
+
return if allowed_arguments?(def_node.arguments)
|
93
93
|
|
94
94
|
add_offense(node.loc.selector, message: format(MSG, method_name: def_node.method_name))
|
95
95
|
end
|
@@ -101,7 +101,7 @@ module RuboCop
|
|
101
101
|
definition = find_method_definition(node, method_name)
|
102
102
|
|
103
103
|
return unless definition
|
104
|
-
return if allowed_arguments(definition.arguments)
|
104
|
+
return if allowed_arguments?(definition.arguments)
|
105
105
|
|
106
106
|
add_offense(node, message: format(MSG, method_name: method_name))
|
107
107
|
end
|
@@ -115,7 +115,7 @@ module RuboCop
|
|
115
115
|
end
|
116
116
|
|
117
117
|
# `ruby2_keywords` is only allowed if there's a `restarg` and no keyword arguments
|
118
|
-
def allowed_arguments(arguments)
|
118
|
+
def allowed_arguments?(arguments)
|
119
119
|
return false if arguments.empty?
|
120
120
|
|
121
121
|
arguments.each_child_node(:restarg).any? &&
|
@@ -128,8 +128,8 @@ module RuboCop
|
|
128
128
|
|
129
129
|
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
130
130
|
def check_void_op(node, &block)
|
131
|
-
node = node.children.first while node
|
132
|
-
return unless node
|
131
|
+
node = node.children.first while node&.begin_type?
|
132
|
+
return unless node&.call_type? && OPERATORS.include?(node.method_name)
|
133
133
|
if !UNARY_OPERATORS.include?(node.method_name) && node.loc.dot && node.arguments.none?
|
134
134
|
return
|
135
135
|
end
|
@@ -32,7 +32,7 @@ module RuboCop
|
|
32
32
|
# @param [String] cop_name for specific cop name
|
33
33
|
# @param [Hash] cop_config configs for specific cop, from config#for_cop
|
34
34
|
# @option cop_config [String] :StyleGuide Extension of base styleguide URL
|
35
|
-
# @option cop_config [String] :
|
35
|
+
# @option cop_config [String] :References Full reference URLs
|
36
36
|
# @option cop_config [String] :Details
|
37
37
|
#
|
38
38
|
# @param [Hash, nil] options optional
|
@@ -100,8 +100,12 @@ module RuboCop
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def reference_urls
|
103
|
-
urls =
|
104
|
-
|
103
|
+
urls = cop_config
|
104
|
+
.values_at('References', 'Reference') # Support legacy Reference key
|
105
|
+
.flat_map { Array(_1) }
|
106
|
+
.reject(&:empty?)
|
107
|
+
|
108
|
+
urls unless urls.empty?
|
105
109
|
end
|
106
110
|
|
107
111
|
def extra_details?
|
@@ -39,7 +39,7 @@ module RuboCop
|
|
39
39
|
class AbcSize < Base
|
40
40
|
include MethodComplexity
|
41
41
|
|
42
|
-
MSG = 'Assignment Branch Condition size for
|
42
|
+
MSG = 'Assignment Branch Condition size for `%<method>s` is too high. ' \
|
43
43
|
'[%<abc_vector>s %<complexity>.4g/%<max>.4g]'
|
44
44
|
|
45
45
|
private
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
66
66
|
end
|
67
67
|
|
68
68
|
# @deprecated Use processed_source.line_with_comment?(line)
|
69
|
-
def end_of_line_comment(line)
|
69
|
+
def end_of_line_comment(line) # rubocop:disable Naming/PredicateMethod
|
70
70
|
warn Rainbow(<<~WARNING).yellow, uplevel: 1
|
71
71
|
`end_of_line_comment` is deprecated. Use `processed_source.line_with_comment?` instead.
|
72
72
|
WARNING
|
@@ -48,7 +48,7 @@ module RuboCop
|
|
48
48
|
|
49
49
|
args = process_args(node.arguments)
|
50
50
|
return extract_breakable_node_from_elements(node, args, max)
|
51
|
-
elsif node.
|
51
|
+
elsif node.any_def_type?
|
52
52
|
return extract_breakable_node_from_elements(node, node.arguments, max)
|
53
53
|
elsif node.type?(:array, :hash)
|
54
54
|
return extract_breakable_node_from_elements(node, node.children, max)
|
@@ -220,7 +220,7 @@ module RuboCop
|
|
220
220
|
|
221
221
|
# @api private
|
222
222
|
def already_on_multiple_lines?(node)
|
223
|
-
return node.first_line != node.last_argument.last_line if node.
|
223
|
+
return node.first_line != node.last_argument.last_line if node.any_def_type?
|
224
224
|
|
225
225
|
!node.single_line?
|
226
226
|
end
|
@@ -40,7 +40,7 @@ module RuboCop
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def safe_to_split?(node)
|
43
|
-
node.each_descendant(:if, :case, :kwbegin, :
|
43
|
+
node.each_descendant(:if, :case, :kwbegin, :any_def).none? &&
|
44
44
|
node.each_descendant(:dstr, :str).none? { |n| n.heredoc? || n.value.include?("\n") } &&
|
45
45
|
node.each_descendant(:begin, :sym).none? { |b| !b.single_line? }
|
46
46
|
end
|
@@ -19,7 +19,7 @@ module RuboCop
|
|
19
19
|
|
20
20
|
# @!method non_public_modifier?(node)
|
21
21
|
def_node_matcher :non_public_modifier?, <<~PATTERN
|
22
|
-
(send nil? {:private :protected :private_class_method} (
|
22
|
+
(send nil? {:private :protected :private_class_method} (any_def ...))
|
23
23
|
PATTERN
|
24
24
|
end
|
25
25
|
end
|
@@ -21,7 +21,7 @@ module RuboCop
|
|
21
21
|
|
22
22
|
# @!method empty_line_required?(node)
|
23
23
|
def_node_matcher :empty_line_required?,
|
24
|
-
'{
|
24
|
+
'{any_def class module (send nil? {:private :protected :public})}'
|
25
25
|
|
26
26
|
def check(node, body, adjusted_first_line: nil)
|
27
27
|
return if valid_body_style?(body)
|
@@ -6,7 +6,6 @@ module RuboCop
|
|
6
6
|
module FrozenStringLiteral
|
7
7
|
module_function
|
8
8
|
|
9
|
-
FROZEN_STRING_LITERAL_REGEXP = /#\s*frozen[-_]?string[-_]?literal:/i.freeze
|
10
9
|
FROZEN_STRING_LITERAL_ENABLED = '# frozen_string_literal: true'
|
11
10
|
FROZEN_STRING_LITERAL_TYPES_RUBY27 = %i[str dstr].freeze
|
12
11
|
|
@@ -90,7 +89,7 @@ module RuboCop
|
|
90
89
|
|
91
90
|
if first_non_comment_token
|
92
91
|
# `line` is 1-indexed so we need to subtract 1 to get the array index
|
93
|
-
processed_source.lines[0...first_non_comment_token.line - 1]
|
92
|
+
processed_source.lines[0...(first_non_comment_token.line - 1)]
|
94
93
|
else
|
95
94
|
processed_source.lines
|
96
95
|
end
|
@@ -25,6 +25,28 @@ module RuboCop
|
|
25
25
|
(args
|
26
26
|
(arg $_)) ...)
|
27
27
|
PATTERN
|
28
|
+
|
29
|
+
# @!method assignment_method_declarations(node)
|
30
|
+
def_node_search :assignment_method_declarations, <<~PATTERN
|
31
|
+
(send
|
32
|
+
(lvar {#match_block_variable_name? :_1 :it}) _ ...)
|
33
|
+
PATTERN
|
34
|
+
|
35
|
+
# @!method indexed_assignment_method_declarations(node)
|
36
|
+
def_node_search :indexed_assignment_method_declarations, <<~PATTERN
|
37
|
+
(send
|
38
|
+
(send (lvar {#match_block_variable_name? :_1 :it}) _)
|
39
|
+
:[]=
|
40
|
+
literal?
|
41
|
+
_
|
42
|
+
)
|
43
|
+
PATTERN
|
44
|
+
|
45
|
+
def match_block_variable_name?(receiver_name)
|
46
|
+
gem_specification(processed_source.ast) do |block_variable_name|
|
47
|
+
return block_variable_name == receiver_name
|
48
|
+
end
|
49
|
+
end
|
28
50
|
end
|
29
51
|
end
|
30
52
|
end
|
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
true
|
11
11
|
end
|
12
12
|
|
13
|
-
def deltas_for_first_pair(first_pair
|
13
|
+
def deltas_for_first_pair(first_pair)
|
14
14
|
{
|
15
15
|
separator: separator_delta(first_pair),
|
16
16
|
value: value_delta(first_pair)
|
@@ -81,13 +81,7 @@ module RuboCop
|
|
81
81
|
class TableAlignment
|
82
82
|
include ValueAlignment
|
83
83
|
|
84
|
-
def
|
85
|
-
self.max_key_width = 0
|
86
|
-
end
|
87
|
-
|
88
|
-
def deltas_for_first_pair(first_pair, node)
|
89
|
-
self.max_key_width = node.keys.map { |key| key.source.length }.max
|
90
|
-
|
84
|
+
def deltas_for_first_pair(first_pair)
|
91
85
|
separator_delta = separator_delta(first_pair, first_pair, 0)
|
92
86
|
{
|
93
87
|
separator: separator_delta,
|
@@ -97,30 +91,37 @@ module RuboCop
|
|
97
91
|
|
98
92
|
private
|
99
93
|
|
100
|
-
attr_accessor :max_key_width
|
101
|
-
|
102
94
|
def key_delta(first_pair, current_pair)
|
103
95
|
first_pair.key_delta(current_pair)
|
104
96
|
end
|
105
97
|
|
106
98
|
def hash_rocket_delta(first_pair, current_pair)
|
107
|
-
first_pair.loc.column + max_key_width + 1 -
|
99
|
+
first_pair.loc.column + max_key_width(first_pair.parent) + 1 -
|
100
|
+
current_pair.loc.operator.column
|
108
101
|
end
|
109
102
|
|
110
103
|
def value_delta(first_pair, current_pair)
|
111
104
|
correct_value_column = first_pair.key.loc.column +
|
112
|
-
|
113
|
-
|
105
|
+
max_key_width(first_pair.parent) +
|
106
|
+
max_delimiter_width(first_pair.parent)
|
114
107
|
|
115
108
|
current_pair.value_omission? ? 0 : correct_value_column - current_pair.value.loc.column
|
116
109
|
end
|
110
|
+
|
111
|
+
def max_key_width(hash_node)
|
112
|
+
hash_node.keys.map { |key| key.source.length }.max
|
113
|
+
end
|
114
|
+
|
115
|
+
def max_delimiter_width(hash_node)
|
116
|
+
hash_node.pairs.map { |pair| pair.delimiter(true).length }.max
|
117
|
+
end
|
117
118
|
end
|
118
119
|
|
119
120
|
# Handles calculation of deltas when the enforced style is 'separator'.
|
120
121
|
class SeparatorAlignment
|
121
122
|
include ValueAlignment
|
122
123
|
|
123
|
-
def deltas_for_first_pair(
|
124
|
+
def deltas_for_first_pair(_first_pair)
|
124
125
|
{}
|
125
126
|
end
|
126
127
|
|