rubocop 1.22.1 → 1.24.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 +88 -8
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/cli/command/show_docs_url.rb +48 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
- data/lib/rubocop/cli.rb +1 -0
- data/lib/rubocop/config_loader_resolver.rb +1 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/if_then_corrector.rb +55 -0
- data/lib/rubocop/cop/documentation.rb +19 -2
- data/lib/rubocop/cop/gemspec/date_assignment.rb +2 -10
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -10
- data/lib/rubocop/cop/gemspec/require_mfa.rb +146 -0
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +30 -23
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -10
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +60 -0
- data/lib/rubocop/cop/internal_affairs/redundant_method_dispatch_node.rb +46 -0
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +3 -1
- data/lib/rubocop/cop/internal_affairs.rb +2 -0
- data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/comment_indentation.rb +31 -2
- data/lib/rubocop/cop/layout/dot_position.rb +13 -7
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +22 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
- data/lib/rubocop/cop/layout/end_alignment.rb +1 -2
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -2
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_colon.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_comment.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +4 -0
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +11 -5
- data/lib/rubocop/cop/layout/space_inside_parens.rb +0 -4
- data/lib/rubocop/cop/lint/ambiguous_range.rb +3 -3
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +1 -1
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +16 -4
- data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +6 -0
- data/lib/rubocop/cop/lint/else_layout.rb +1 -1
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +4 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +5 -2
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +117 -0
- data/lib/rubocop/cop/metrics/block_length.rb +1 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +0 -9
- data/lib/rubocop/cop/metrics/method_length.rb +1 -0
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +5 -0
- data/lib/rubocop/cop/mixin/gemspec_help.rb +30 -0
- data/lib/rubocop/cop/mixin/hash_alignment_styles.rb +4 -3
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +56 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -5
- data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +102 -0
- data/lib/rubocop/cop/naming/file_name.rb +37 -4
- data/lib/rubocop/cop/security/json_load.rb +1 -1
- data/lib/rubocop/cop/security/open.rb +11 -1
- data/lib/rubocop/cop/style/character_literal.rb +8 -1
- data/lib/rubocop/cop/style/collection_compact.rb +31 -13
- data/lib/rubocop/cop/style/combinable_loops.rb +2 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -3
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/empty_case_condition.rb +10 -0
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/file_read.rb +112 -0
- data/lib/rubocop/cop/style/file_write.rb +98 -0
- data/lib/rubocop/cop/style/format_string_token.rb +2 -1
- data/lib/rubocop/cop/style/hash_conversion.rb +2 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +22 -0
- data/lib/rubocop/cop/style/if_inside_else.rb +15 -0
- data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +68 -0
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +10 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +18 -39
- data/lib/rubocop/cop/style/open_struct_use.rb +69 -0
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -2
- data/lib/rubocop/cop/style/quoted_symbols.rb +11 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +17 -3
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +5 -1
- data/lib/rubocop/cop/style/redundant_self.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -5
- data/lib/rubocop/cop/style/select_by_regexp.rb +9 -3
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/cop/util.rb +11 -1
- data/lib/rubocop/formatter/html_formatter.rb +5 -2
- data/lib/rubocop/formatter/json_formatter.rb +4 -1
- data/lib/rubocop/options.rb +6 -1
- data/lib/rubocop/remote_config.rb +2 -4
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/yaml_duplication_checker.rb +1 -1
- data/lib/rubocop.rb +11 -0
- metadata +24 -9
@@ -30,15 +30,17 @@ module RuboCop
|
|
30
30
|
def on_send(node)
|
31
31
|
return unless arrow_lambda_with_args?(node)
|
32
32
|
|
33
|
-
lambda_node = range_of_offense(node)
|
34
|
-
|
35
33
|
if style == :require_space && !space_after_arrow?(node)
|
34
|
+
lambda_node = range_of_offense(node)
|
35
|
+
|
36
36
|
add_offense(lambda_node, message: MSG_REQUIRE_SPACE) do |corrector|
|
37
|
-
corrector.insert_before(node
|
37
|
+
corrector.insert_before(lambda_arguments(node), ' ')
|
38
38
|
end
|
39
39
|
elsif style == :require_no_space && space_after_arrow?(node)
|
40
|
-
|
41
|
-
|
40
|
+
space = space_after_arrow(node)
|
41
|
+
|
42
|
+
add_offense(space, message: MSG_REQUIRE_NO_SPACE) do |corrector|
|
43
|
+
corrector.remove(space)
|
42
44
|
end
|
43
45
|
end
|
44
46
|
end
|
@@ -66,6 +68,10 @@ module RuboCop
|
|
66
68
|
node.parent.arguments.loc.expression.end_pos
|
67
69
|
)
|
68
70
|
end
|
71
|
+
|
72
|
+
def lambda_arguments(node)
|
73
|
+
node.parent.children[1]
|
74
|
+
end
|
69
75
|
end
|
70
76
|
end
|
71
77
|
end
|
@@ -8,7 +8,7 @@ module RuboCop
|
|
8
8
|
# Ranges have quite low precedence, which leads to unexpected behaviour when
|
9
9
|
# using a range with other operators. This cop avoids that by making ranges
|
10
10
|
# explicit by requiring parenthesis around complex range boundaries (anything
|
11
|
-
# that is not a
|
11
|
+
# that is not a literal: numerics, strings, symbols, etc.).
|
12
12
|
#
|
13
13
|
# This cop can be configured with `RequireParenthesesForMethodChains` in order to
|
14
14
|
# specify whether method chains (including `self.foo`) should be wrapped in parens
|
@@ -81,8 +81,8 @@ module RuboCop
|
|
81
81
|
|
82
82
|
def acceptable?(node)
|
83
83
|
node.begin_type? ||
|
84
|
-
node.
|
85
|
-
node.variable? || node.const_type? ||
|
84
|
+
node.literal? ||
|
85
|
+
node.variable? || node.const_type? || node.self_type? ||
|
86
86
|
(node.call_type? && acceptable_call?(node))
|
87
87
|
end
|
88
88
|
|
@@ -12,6 +12,7 @@ module RuboCop
|
|
12
12
|
# File.exists?(some_path)
|
13
13
|
# Dir.exists?(some_path)
|
14
14
|
# iterator?
|
15
|
+
# ENV.freeze # Calling `Env.freeze` raises `TypeError` since Ruby 2.7.
|
15
16
|
# Socket.gethostbyname(host)
|
16
17
|
# Socket.gethostbyaddr(host)
|
17
18
|
#
|
@@ -22,6 +23,7 @@ module RuboCop
|
|
22
23
|
# File.exist?(some_path)
|
23
24
|
# Dir.exist?(some_path)
|
24
25
|
# block_given?
|
26
|
+
# ENV # `ENV.freeze` cannot prohibit changes to environment variables.
|
25
27
|
# Addrinfo.getaddrinfo(nodename, service)
|
26
28
|
# Addrinfo.tcp(host, port).getnameinfo
|
27
29
|
class DeprecatedClassMethods < Base
|
@@ -106,6 +108,9 @@ module RuboCop
|
|
106
108
|
|
107
109
|
DeprecatedClassMethod.new(:iterator?) => Replacement.new(:block_given?),
|
108
110
|
|
111
|
+
DeprecatedClassMethod.new(:freeze, class_constant: :ENV) =>
|
112
|
+
Replacement.new(nil, class_constant: :ENV),
|
113
|
+
|
109
114
|
DeprecatedClassMethod.new(:gethostbyaddr, class_constant: :Socket, correctable: false) =>
|
110
115
|
Replacement.new(:getnameinfo, class_constant: :Addrinfo, instance_method: true),
|
111
116
|
|
@@ -120,11 +125,18 @@ module RuboCop
|
|
120
125
|
|
121
126
|
def on_send(node)
|
122
127
|
check(node) do |deprecated|
|
123
|
-
|
128
|
+
prefer = replacement(deprecated)
|
129
|
+
message = format(MSG, current: deprecated, prefer: prefer)
|
130
|
+
current_method = node.loc.selector
|
131
|
+
|
132
|
+
add_offense(current_method, message: message) do |corrector|
|
133
|
+
next unless deprecated.correctable?
|
124
134
|
|
125
|
-
|
126
|
-
|
127
|
-
|
135
|
+
if (preferred_method = prefer.method)
|
136
|
+
corrector.replace(current_method, preferred_method)
|
137
|
+
else
|
138
|
+
corrector.remove(node.loc.dot)
|
139
|
+
corrector.remove(current_method)
|
128
140
|
end
|
129
141
|
end
|
130
142
|
end
|
@@ -42,11 +42,12 @@ module RuboCop
|
|
42
42
|
# Maybe further investigation of RuboCop AST will lead to an essential solution.
|
43
43
|
return unless node.loc
|
44
44
|
|
45
|
-
constant = node.absolute? ? constant_name(node, node.short_name
|
45
|
+
constant = node.absolute? ? constant_name(node, node.short_name) : node.source
|
46
46
|
return unless (deprecated_constant = deprecated_constants[constant])
|
47
47
|
|
48
48
|
alternative = deprecated_constant['Alternative']
|
49
49
|
version = deprecated_constant['DeprecatedVersion']
|
50
|
+
return if target_ruby_version < version.to_f
|
50
51
|
|
51
52
|
add_offense(node, message: message(alternative, node.source, version)) do |corrector|
|
52
53
|
corrector.replace(node, alternative)
|
@@ -56,7 +57,7 @@ module RuboCop
|
|
56
57
|
private
|
57
58
|
|
58
59
|
def constant_name(node, nested_constant_name)
|
59
|
-
return nested_constant_name unless node.namespace.const_type?
|
60
|
+
return nested_constant_name.to_s unless node.namespace.const_type?
|
60
61
|
|
61
62
|
constant_name(node.namespace, "#{node.namespace.short_name}::#{nested_constant_name}")
|
62
63
|
end
|
@@ -55,8 +55,14 @@ module RuboCop
|
|
55
55
|
...)
|
56
56
|
PATTERN
|
57
57
|
|
58
|
+
# @!method digest_const?(node)
|
59
|
+
def_node_matcher :digest_const?, <<~PATTERN
|
60
|
+
(const _ :Digest)
|
61
|
+
PATTERN
|
62
|
+
|
58
63
|
def on_send(node)
|
59
64
|
return if node.arguments.any? { |arg| arg.variable? || arg.send_type? || arg.const_type? }
|
65
|
+
return if digest_const?(node.receiver)
|
60
66
|
return unless algorithm_const(node)
|
61
67
|
|
62
68
|
message = message(node)
|
@@ -72,7 +72,7 @@ module RuboCop
|
|
72
72
|
first_else = else_branch.begin_type? ? else_branch.children.first : else_branch
|
73
73
|
|
74
74
|
return unless first_else
|
75
|
-
return unless first_else
|
75
|
+
return unless same_line?(first_else, node.loc.else)
|
76
76
|
|
77
77
|
add_offense(first_else) { |corrector| autocorrect(corrector, node, first_else) }
|
78
78
|
end
|
@@ -20,6 +20,10 @@ module RuboCop
|
|
20
20
|
# # good
|
21
21
|
# io.wait_writable(timeout)
|
22
22
|
#
|
23
|
+
# @safety
|
24
|
+
# This cop's autocorrection is unsafe because `NoMethodError` occurs
|
25
|
+
# if `require 'io/wait'` is not called.
|
26
|
+
#
|
23
27
|
class IncompatibleIoSelectWithFiberScheduler < Base
|
24
28
|
extend AutoCorrector
|
25
29
|
|
@@ -30,6 +30,7 @@ module RuboCop
|
|
30
30
|
# '10'.to_i
|
31
31
|
# '10.2'.to_f
|
32
32
|
# '10'.to_c
|
33
|
+
# '1/3'.to_r
|
33
34
|
# ['1', '2', '3'].map(&:to_i)
|
34
35
|
# foo.try(:to_f)
|
35
36
|
# bar.send(:to_c)
|
@@ -39,6 +40,7 @@ module RuboCop
|
|
39
40
|
# Integer('10', 10)
|
40
41
|
# Float('10.2')
|
41
42
|
# Complex('10')
|
43
|
+
# Rational('1/3')
|
42
44
|
# ['1', '2', '3'].map { |i| Integer(i, 10) }
|
43
45
|
# foo.try { |i| Float(i) }
|
44
46
|
# bar.send { |i| Complex(i) }
|
@@ -59,13 +61,14 @@ module RuboCop
|
|
59
61
|
CONVERSION_METHOD_CLASS_MAPPING = {
|
60
62
|
to_i: "#{Integer.name}(%<number_object>s, 10)",
|
61
63
|
to_f: "#{Float.name}(%<number_object>s)",
|
62
|
-
to_c: "#{Complex.name}(%<number_object>s)"
|
64
|
+
to_c: "#{Complex.name}(%<number_object>s)",
|
65
|
+
to_r: "#{Rational.name}(%<number_object>s)"
|
63
66
|
}.freeze
|
64
67
|
MSG = 'Replace unsafe number conversion with number '\
|
65
68
|
'class parsing, instead of using '\
|
66
69
|
'`%<current>s`, use stricter '\
|
67
70
|
'`%<corrected_method>s`.'
|
68
|
-
CONVERSION_METHODS = %i[Integer Float Complex to_i to_f to_c].freeze
|
71
|
+
CONVERSION_METHODS = %i[Integer Float Complex Rational to_i to_f to_c to_r].freeze
|
69
72
|
METHODS = CONVERSION_METHOD_CLASS_MAPPING.keys.map(&:inspect).join(' ')
|
70
73
|
|
71
74
|
# @!method to_method(node)
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop looks for `ruby2_keywords` calls for methods that do not need it.
|
7
|
+
#
|
8
|
+
# `ruby2_keywords` should only be called on methods that accept an argument splat
|
9
|
+
# (`*args`) but do not explicit keyword arguments (`k:` or `k: true`) or
|
10
|
+
# a keyword splat (`**kwargs`).
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
# # good (splat argument without keyword arguments)
|
14
|
+
# ruby2_keywords def foo(*args); end
|
15
|
+
#
|
16
|
+
# # bad (no arguments)
|
17
|
+
# ruby2_keywords def foo; end
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# def foo; end
|
21
|
+
#
|
22
|
+
# # bad (positional argument)
|
23
|
+
# ruby2_keywords def foo(arg); end
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# def foo(arg); end
|
27
|
+
#
|
28
|
+
# # bad (double splatted argument)
|
29
|
+
# ruby2_keywords def foo(**args); end
|
30
|
+
#
|
31
|
+
# # good
|
32
|
+
# def foo(**args); end
|
33
|
+
#
|
34
|
+
# # bad (keyword arguments)
|
35
|
+
# ruby2_keywords def foo(i:, j:); end
|
36
|
+
#
|
37
|
+
# # good
|
38
|
+
# def foo(i:, j:); end
|
39
|
+
#
|
40
|
+
# # bad (splat argument with keyword arguments)
|
41
|
+
# ruby2_keywords def foo(*args, i:, j:); end
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# def foo(*args, i:, j:); end
|
45
|
+
#
|
46
|
+
# # bad (splat argument with double splat)
|
47
|
+
# ruby2_keywords def foo(*args, **kwargs); end
|
48
|
+
#
|
49
|
+
# # good
|
50
|
+
# def foo(*args, **kwargs); end
|
51
|
+
#
|
52
|
+
# # bad (ruby2_keywords given a symbol)
|
53
|
+
# def foo; end
|
54
|
+
# ruby2_keywords :foo
|
55
|
+
#
|
56
|
+
# # good
|
57
|
+
# def foo; end
|
58
|
+
#
|
59
|
+
# # bad (ruby2_keywords with dynamic method)
|
60
|
+
# define_method(:foo) { |arg| }
|
61
|
+
# ruby2_keywords :foo
|
62
|
+
#
|
63
|
+
# # good
|
64
|
+
# define_method(:foo) { |arg| }
|
65
|
+
#
|
66
|
+
class UselessRuby2Keywords < Base
|
67
|
+
MSG = '`ruby2_keywords` is unnecessary for method `%<method_name>s`.'
|
68
|
+
RESTRICT_ON_SEND = %i[ruby2_keywords].freeze
|
69
|
+
|
70
|
+
# Looks for statically or dynamically defined methods with a given name
|
71
|
+
# @!method method_definition(node, method_name)
|
72
|
+
def_node_matcher :method_definition, <<~PATTERN
|
73
|
+
{
|
74
|
+
(def %1 ...)
|
75
|
+
({block numblock} (send _ :define_method (sym %1)) ...)
|
76
|
+
}
|
77
|
+
PATTERN
|
78
|
+
|
79
|
+
def on_send(node)
|
80
|
+
if node.first_argument.def_type?
|
81
|
+
inspect_def(node, node.first_argument)
|
82
|
+
elsif node.first_argument.sym_type?
|
83
|
+
inspect_sym(node, node.first_argument)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
|
89
|
+
def inspect_def(node, def_node)
|
90
|
+
return if allowed_arguments(def_node.arguments)
|
91
|
+
|
92
|
+
add_offense(node.loc.selector, message: format(MSG, method_name: def_node.method_name))
|
93
|
+
end
|
94
|
+
|
95
|
+
def inspect_sym(node, sym_node)
|
96
|
+
return unless node.parent
|
97
|
+
|
98
|
+
method_name = sym_node.value
|
99
|
+
definition = node.parent.each_child_node.detect { |n| method_definition(n, method_name) }
|
100
|
+
|
101
|
+
return unless definition
|
102
|
+
return if allowed_arguments(definition.arguments)
|
103
|
+
|
104
|
+
add_offense(node, message: format(MSG, method_name: method_name))
|
105
|
+
end
|
106
|
+
|
107
|
+
# `ruby2_keywords` is only allowed if there's a `restarg` and no keyword arguments
|
108
|
+
def allowed_arguments(arguments)
|
109
|
+
return false if arguments.empty?
|
110
|
+
|
111
|
+
arguments.each_child_node(:restarg).any? &&
|
112
|
+
arguments.each_child_node(:kwarg, :kwoptarg, :kwrestarg).none?
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -46,15 +46,6 @@ module RuboCop
|
|
46
46
|
1
|
47
47
|
end
|
48
48
|
|
49
|
-
def block_method(node)
|
50
|
-
case node.type
|
51
|
-
when :block
|
52
|
-
node.method_name
|
53
|
-
when :block_pass
|
54
|
-
node.parent.method_name
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
49
|
def count_block?(block)
|
59
50
|
KNOWN_ITERATING_METHODS.include? block.method_name
|
60
51
|
end
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
|
45
45
|
# @!method module_definition?(node)
|
46
46
|
def_node_matcher :module_definition?, <<~PATTERN
|
47
|
-
(casgn nil? _ (block (send (const {nil? cbase} :Module) :new) ...))
|
47
|
+
(casgn nil? _ ({block numblock} (send (const {nil? cbase} :Module) :new) ...))
|
48
48
|
PATTERN
|
49
49
|
|
50
50
|
def message(length, max_length)
|
@@ -9,6 +9,9 @@ module RuboCop
|
|
9
9
|
# Keyword arguments can optionally be excluded from the total count,
|
10
10
|
# as they add less complexity than positional or optional parameters.
|
11
11
|
#
|
12
|
+
# NOTE: Explicit block argument `&block` is not counted to prevent
|
13
|
+
# erroneous change that is avoided by making block argument implicit.
|
14
|
+
#
|
12
15
|
# @example Max: 3
|
13
16
|
# # good
|
14
17
|
# def foo(a, b, c = 1)
|
@@ -94,9 +97,9 @@ module RuboCop
|
|
94
97
|
|
95
98
|
def args_count(node)
|
96
99
|
if count_keyword_args?
|
97
|
-
node.children.
|
100
|
+
node.children.count { |a| !a.blockarg_type? }
|
98
101
|
else
|
99
|
-
node.children.count { |a| !NAMED_KEYWORD_TYPES.include?(a.type) }
|
102
|
+
node.children.count { |a| !NAMED_KEYWORD_TYPES.include?(a.type) && !a.blockarg_type? }
|
100
103
|
end
|
101
104
|
end
|
102
105
|
|
@@ -34,8 +34,7 @@ module RuboCop
|
|
34
34
|
|
35
35
|
def matching_ranges(end_loc, align_ranges)
|
36
36
|
align_ranges.select do |_, range|
|
37
|
-
range
|
38
|
-
column_offset_between(range, end_loc).zero?
|
37
|
+
same_line?(range, end_loc) || column_offset_between(range, end_loc).zero?
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|
@@ -13,6 +13,11 @@ module RuboCop
|
|
13
13
|
# @api private
|
14
14
|
module EnforceSuperclass
|
15
15
|
def self.included(base)
|
16
|
+
warn Rainbow(
|
17
|
+
'`RuboCop::Cop::EnforceSuperclass` is deprecated and will be removed in RuboCop 2.0. ' \
|
18
|
+
'Please upgrade to RuboCop Rails 2.9 or newer to continue.'
|
19
|
+
).yellow
|
20
|
+
|
16
21
|
# @!method class_definition(node)
|
17
22
|
base.def_node_matcher :class_definition, <<~PATTERN
|
18
23
|
(class (const _ !:#{base::SUPERCLASS}) #{base::BASE_PATTERN} ...)
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for checking gem declarations.
|
6
|
+
module GemspecHelp
|
7
|
+
extend NodePattern::Macros
|
8
|
+
|
9
|
+
# @!method gem_specification?(node)
|
10
|
+
def_node_matcher :gem_specification?, <<~PATTERN
|
11
|
+
(block
|
12
|
+
(send
|
13
|
+
(const
|
14
|
+
(const {cbase nil?} :Gem) :Specification) :new)
|
15
|
+
(args
|
16
|
+
(arg $_)) ...)
|
17
|
+
PATTERN
|
18
|
+
|
19
|
+
# @!method gem_specification(node)
|
20
|
+
def_node_search :gem_specification, <<~PATTERN
|
21
|
+
(block
|
22
|
+
(send
|
23
|
+
(const
|
24
|
+
(const {cbase nil?} :Gem) :Specification) :new)
|
25
|
+
(args
|
26
|
+
(arg $_)) ...)
|
27
|
+
PATTERN
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -43,7 +43,7 @@ module RuboCop
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def value_delta(pair)
|
46
|
-
return 0 if pair.value_on_new_line?
|
46
|
+
return 0 if pair.value_on_new_line? || pair.value_omission?
|
47
47
|
|
48
48
|
correct_value_column = pair.loc.operator.end.column + 1
|
49
49
|
actual_value_column = pair.value.loc.column
|
@@ -111,7 +111,8 @@ module RuboCop
|
|
111
111
|
correct_value_column = first_pair.key.loc.column +
|
112
112
|
current_pair.delimiter(true).length +
|
113
113
|
max_key_width
|
114
|
-
|
114
|
+
|
115
|
+
current_pair.value_omission? ? 0 : correct_value_column - current_pair.value.loc.column
|
115
116
|
end
|
116
117
|
end
|
117
118
|
|
@@ -134,7 +135,7 @@ module RuboCop
|
|
134
135
|
end
|
135
136
|
|
136
137
|
def value_delta(first_pair, current_pair)
|
137
|
-
first_pair.value_delta(current_pair)
|
138
|
+
current_pair.value_omission? ? 0 : first_pair.value_delta(current_pair)
|
138
139
|
end
|
139
140
|
end
|
140
141
|
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# This module checks for Ruby 3.1's hash value omission syntax.
|
6
|
+
module HashShorthandSyntax
|
7
|
+
OMIT_HASH_VALUE_MSG = 'Omit the hash value.'
|
8
|
+
EXPLICIT_HASH_VALUE_MSG = 'Explicit the hash value.'
|
9
|
+
|
10
|
+
def on_pair(node)
|
11
|
+
return if target_ruby_version <= 3.0
|
12
|
+
|
13
|
+
hash_key_source = node.key.source
|
14
|
+
|
15
|
+
if enforced_shorthand_syntax == 'always'
|
16
|
+
return if node.value_omission? || require_hash_value?(hash_key_source, node)
|
17
|
+
|
18
|
+
message = OMIT_HASH_VALUE_MSG
|
19
|
+
replacement = "#{hash_key_source}:"
|
20
|
+
else
|
21
|
+
return unless node.value_omission?
|
22
|
+
|
23
|
+
message = EXPLICIT_HASH_VALUE_MSG
|
24
|
+
replacement = "#{hash_key_source}: #{hash_key_source}"
|
25
|
+
end
|
26
|
+
|
27
|
+
add_offense(node.value, message: message) do |corrector|
|
28
|
+
corrector.replace(node, replacement)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def enforced_shorthand_syntax
|
35
|
+
cop_config.fetch('EnforcedShorthandSyntax', 'always')
|
36
|
+
end
|
37
|
+
|
38
|
+
def require_hash_value?(hash_key_source, node)
|
39
|
+
return true if without_parentheses_call_expr_follows?(node)
|
40
|
+
|
41
|
+
hash_value = node.value
|
42
|
+
return true unless hash_value.send_type? || hash_value.lvar_type?
|
43
|
+
|
44
|
+
hash_key_source != hash_value.source || hash_key_source.end_with?('!', '?')
|
45
|
+
end
|
46
|
+
|
47
|
+
def without_parentheses_call_expr_follows?(node)
|
48
|
+
return false unless (ancestor = node.parent.parent)
|
49
|
+
return false unless (right_sibling = ancestor.right_sibling)
|
50
|
+
|
51
|
+
ancestor.respond_to?(:parenthesized?) && !ancestor.parenthesized? &&
|
52
|
+
right_sibling.respond_to?(:parenthesized?) && !right_sibling.parenthesized?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -139,9 +139,9 @@ module RuboCop
|
|
139
139
|
end
|
140
140
|
|
141
141
|
def self.from_map_to_h(node, match)
|
142
|
-
|
143
|
-
|
144
|
-
|
142
|
+
if node.parent&.block_type? && node.parent.send_node == node
|
143
|
+
strip_trailing_chars = 0
|
144
|
+
else
|
145
145
|
map_range = node.children.first.source_range
|
146
146
|
node_range = node.source_range
|
147
147
|
strip_trailing_chars = node_range.end_pos - map_range.end_pos
|
@@ -15,7 +15,7 @@ module RuboCop
|
|
15
15
|
node.arguments.each do |arg|
|
16
16
|
on_node(type, arg, :send) do |type_node|
|
17
17
|
left_brace = type_node.loc.begin
|
18
|
-
if left_brace && left_brace
|
18
|
+
if left_brace && same_line?(left_brace, left_parenthesis)
|
19
19
|
yield type_node, left_parenthesis
|
20
20
|
ignore_node(type_node)
|
21
21
|
end
|
@@ -90,7 +90,7 @@ module RuboCop
|
|
90
90
|
# This method depends on the fact that we have guarded
|
91
91
|
# against implicit and empty literals.
|
92
92
|
def opening_brace_on_same_line?(node)
|
93
|
-
node.loc.begin
|
93
|
+
same_line?(node.loc.begin, children(node).first)
|
94
94
|
end
|
95
95
|
|
96
96
|
# This method depends on the fact that we have guarded
|
@@ -54,7 +54,7 @@ module RuboCop
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def first_line_comment(node)
|
57
|
-
comment = processed_source.find_comment { |c| c
|
57
|
+
comment = processed_source.find_comment { |c| same_line?(c, node) }
|
58
58
|
return unless comment
|
59
59
|
|
60
60
|
comment_source = comment.loc.expression.source
|
@@ -13,11 +13,7 @@ module RuboCop
|
|
13
13
|
if style == :single_quotes
|
14
14
|
!double_quotes_required?(src)
|
15
15
|
else
|
16
|
-
|
17
|
-
# 1. It contains a double quote
|
18
|
-
# 2. It contains text that would become an escape sequence with double quotes
|
19
|
-
# 3. It contains text that would become an interpolation with double quotes
|
20
|
-
!/" | (?<!\\)\\[abcefMnrtuUx0-7] | \#[@{$]/x.match?(src)
|
16
|
+
!/" | \\[^'\\] | \#[@{$]/x.match?(src)
|
21
17
|
end
|
22
18
|
end
|
23
19
|
end
|