rubocop 1.30.1 → 1.31.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +41 -8
- data/config/obsoletion.yml +2 -0
- data/exe/rubocop +15 -7
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +3 -3
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader.rb +1 -0
- data/lib/rubocop/config_validator.rb +3 -3
- data/lib/rubocop/cop/base.rb +4 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +1 -1
- data/lib/rubocop/cop/bundler/gem_filename.rb +4 -4
- data/lib/rubocop/cop/bundler/ordered_gems.rb +2 -2
- data/lib/rubocop/cop/corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +3 -3
- data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +1 -1
- data/lib/rubocop/cop/gemspec/deprecated_attribute_assignment.rb +31 -16
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/require_mfa.rb +20 -20
- data/lib/rubocop/cop/generator.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -5
- data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +1 -1
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +25 -4
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +17 -11
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +49 -10
- data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +68 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +120 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +5 -3
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +51 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +1 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +121 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +3 -3
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +5 -5
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -1
- data/lib/rubocop/cop/lint/regexp_as_condition.rb +2 -2
- data/lib/rubocop/cop/lint/struct_new_override.rb +2 -2
- data/lib/rubocop/cop/lint/trailing_comma_in_attribute_declaration.rb +1 -1
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +44 -0
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +36 -12
- data/lib/rubocop/cop/mixin/range_help.rb +7 -3
- data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +4 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -0
- data/lib/rubocop/cop/style/empty_method.rb +16 -1
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/format_string_token.rb +48 -17
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +8 -6
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +1 -1
- data/lib/rubocop/cop/style/hash_except.rb +88 -8
- data/lib/rubocop/cop/style/hash_syntax.rb +2 -2
- data/lib/rubocop/cop/style/implicit_runtime_error.rb +2 -2
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +1 -1
- data/lib/rubocop/cop/style/map_to_hash.rb +1 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +2 -2
- data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -3
- data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +1 -3
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +1 -1
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +19 -7
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -1
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +1 -1
- data/lib/rubocop/cop/style/redundant_return.rb +1 -1
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +2 -2
- data/lib/rubocop/cop/style/struct_inheritance.rb +2 -2
- data/lib/rubocop/cop/style/swap_values.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +1 -1
- data/lib/rubocop/cop/style/unpack_first.rb +1 -1
- data/lib/rubocop/cop/util.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +20 -19
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +15 -2
- data/lib/rubocop/formatter/html_formatter.rb +0 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +2 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +6 -9
- data/lib/rubocop/formatter.rb +31 -0
- data/lib/rubocop/options.rb +24 -1
- data/lib/rubocop/rake_task.rb +30 -9
- data/lib/rubocop/server/cache.rb +109 -0
- data/lib/rubocop/server/cli.rb +104 -0
- data/lib/rubocop/server/client_command/base.rb +44 -0
- data/lib/rubocop/server/client_command/exec.rb +59 -0
- data/lib/rubocop/server/client_command/restart.rb +25 -0
- data/lib/rubocop/server/client_command/start.rb +43 -0
- data/lib/rubocop/server/client_command/status.rb +28 -0
- data/lib/rubocop/server/client_command/stop.rb +31 -0
- data/lib/rubocop/server/client_command.rb +26 -0
- data/lib/rubocop/server/core.rb +79 -0
- data/lib/rubocop/server/errors.rb +23 -0
- data/lib/rubocop/server/helper.rb +34 -0
- data/lib/rubocop/server/server_command/base.rb +50 -0
- data/lib/rubocop/server/server_command/exec.rb +34 -0
- data/lib/rubocop/server/server_command/stop.rb +24 -0
- data/lib/rubocop/server/server_command.rb +21 -0
- data/lib/rubocop/server/socket_reader.rb +65 -0
- data/lib/rubocop/server.rb +53 -0
- data/lib/rubocop/version.rb +15 -8
- data/lib/rubocop.rb +7 -26
- metadata +27 -4
- data/lib/rubocop/cop/gemspec/date_assignment.rb +0 -49
@@ -71,16 +71,16 @@ module RuboCop
|
|
71
71
|
processed_source.comment_config.comment_only_line?(directive_comment_range.line) &&
|
72
72
|
directive_comment_range.begin_pos == line_comment_range.begin_pos
|
73
73
|
# When the previous line is blank, it should be retained
|
74
|
-
range_with_surrounding_space(
|
74
|
+
range_with_surrounding_space(directive_comment_range, side: :right)
|
75
75
|
else
|
76
76
|
# Eat the entire comment, the preceding space, and the preceding
|
77
77
|
# newline if there is one.
|
78
78
|
original_begin = directive_comment_range.begin_pos
|
79
79
|
range = range_with_surrounding_space(
|
80
|
-
|
80
|
+
directive_comment_range, side: :left, newlines: true
|
81
81
|
)
|
82
82
|
|
83
|
-
range_with_surrounding_space(range
|
83
|
+
range_with_surrounding_space(range,
|
84
84
|
side: :right,
|
85
85
|
# Special for a comment that
|
86
86
|
# begins the file: remove
|
@@ -94,13 +94,13 @@ module RuboCop
|
|
94
94
|
# is NOT being removed?
|
95
95
|
if ends_its_line?(ranges.last) && trailing_range?(ranges, range)
|
96
96
|
# Eat the comma on the left.
|
97
|
-
range = range_with_surrounding_space(range
|
97
|
+
range = range_with_surrounding_space(range, side: :left)
|
98
98
|
range = range_with_surrounding_comma(range, :left)
|
99
99
|
end
|
100
100
|
|
101
101
|
range = range_with_surrounding_comma(range, :right)
|
102
102
|
# Eat following spaces up to EOL, but not the newline itself.
|
103
|
-
range_with_surrounding_space(range
|
103
|
+
range_with_surrounding_space(range, side: :right, newlines: false)
|
104
104
|
end
|
105
105
|
|
106
106
|
def each_redundant_disable(&block)
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
60
60
|
message: format(MSG, cop: all_or_name(name))
|
61
61
|
) do |corrector|
|
62
62
|
if directive.match?(cop_names)
|
63
|
-
corrector.remove(range_with_surrounding_space(
|
63
|
+
corrector.remove(range_with_surrounding_space(directive.range, side: :right))
|
64
64
|
else
|
65
65
|
corrector.remove(range_with_comma(comment, name))
|
66
66
|
end
|
@@ -41,7 +41,7 @@ module RuboCop
|
|
41
41
|
return unless unnecessary_require_statement?(node)
|
42
42
|
|
43
43
|
add_offense(node) do |corrector|
|
44
|
-
range = range_with_surrounding_space(
|
44
|
+
range = range_with_surrounding_space(node.loc.expression, side: :right)
|
45
45
|
|
46
46
|
corrector.remove(range)
|
47
47
|
end
|
@@ -19,8 +19,8 @@ module RuboCop
|
|
19
19
|
class RegexpAsCondition < Base
|
20
20
|
extend AutoCorrector
|
21
21
|
|
22
|
-
MSG = 'Do not use regexp literal as a condition.' \
|
23
|
-
'
|
22
|
+
MSG = 'Do not use regexp literal as a condition. ' \
|
23
|
+
'The regexp literal matches `$_` implicitly.'
|
24
24
|
|
25
25
|
def on_match_current_line(node)
|
26
26
|
add_offense(node) { |corrector| corrector.replace(node, "#{node.source} =~ $_") }
|
@@ -22,8 +22,8 @@ module RuboCop
|
|
22
22
|
# g.count #=> 2
|
23
23
|
#
|
24
24
|
class StructNewOverride < Base
|
25
|
-
MSG = '`%<member_name>s` member overrides `Struct#%<method_name>s`' \
|
26
|
-
'
|
25
|
+
MSG = '`%<member_name>s` member overrides `Struct#%<method_name>s` ' \
|
26
|
+
'and it may be unexpected.'
|
27
27
|
RESTRICT_ON_SEND = %i[new].freeze
|
28
28
|
|
29
29
|
STRUCT_METHOD_NAMES = Struct.instance_methods
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# Checks for useless `else` in `begin..end` without `rescue`.
|
7
|
+
#
|
8
|
+
# NOTE: This syntax is no longer valid on Ruby 2.6 or higher.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
#
|
14
|
+
# begin
|
15
|
+
# do_something
|
16
|
+
# else
|
17
|
+
# do_something_else # This will never be run.
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
#
|
22
|
+
# # good
|
23
|
+
#
|
24
|
+
# begin
|
25
|
+
# do_something
|
26
|
+
# rescue
|
27
|
+
# handle_errors
|
28
|
+
# else
|
29
|
+
# do_something_else
|
30
|
+
# end
|
31
|
+
class UselessElseWithoutRescue < Base
|
32
|
+
MSG = '`else` without `rescue` is useless.'
|
33
|
+
|
34
|
+
def on_new_investigation
|
35
|
+
processed_source.diagnostics.each do |diagnostic|
|
36
|
+
next unless diagnostic.reason == :useless_else
|
37
|
+
|
38
|
+
add_offense(diagnostic.location, severity: diagnostic.level)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -49,7 +49,7 @@ module RuboCop
|
|
49
49
|
when :heredoc
|
50
50
|
->(node) { heredoc_node?(node) }
|
51
51
|
else
|
52
|
-
raise ArgumentError, "Unknown foldable type: #{type.inspect}. "\
|
52
|
+
raise ArgumentError, "Unknown foldable type: #{type.inspect}. " \
|
53
53
|
"Valid foldable types are: #{FOLDABLE_TYPES.join(', ')}."
|
54
54
|
end
|
55
55
|
end
|
@@ -25,15 +25,17 @@ module RuboCop
|
|
25
25
|
|
26
26
|
def check_first(first, left_brace, left_parenthesis, offset)
|
27
27
|
actual_column = first.source_range.column
|
28
|
-
|
29
|
-
|
28
|
+
|
29
|
+
indent_base_column, indent_base_type = indent_base(left_brace, left_parenthesis)
|
30
|
+
expected_column = indent_base_column + configured_indentation_width + offset
|
31
|
+
|
30
32
|
@column_delta = expected_column - actual_column
|
31
33
|
styles = detected_styles(actual_column, offset, left_parenthesis, left_brace)
|
32
34
|
|
33
35
|
if @column_delta.zero?
|
34
36
|
check_expected_style(styles)
|
35
37
|
else
|
36
|
-
incorrect_style_detected(styles, first,
|
38
|
+
incorrect_style_detected(styles, first, indent_base_type)
|
37
39
|
end
|
38
40
|
end
|
39
41
|
|
@@ -45,14 +47,36 @@ module RuboCop
|
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
def
|
49
|
-
if style == brace_alignment_style
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
left_brace.source_line =~ /\S/
|
50
|
+
def indent_base(left_brace, left_parenthesis)
|
51
|
+
return [left_brace.column, :left_brace_or_bracket] if style == brace_alignment_style
|
52
|
+
|
53
|
+
pair = hash_pair_where_value_beginning_with(left_brace)
|
54
|
+
if pair && key_and_value_begin_on_same_line?(pair) && pair.right_sibling
|
55
|
+
return [pair.loc.column, :parent_hash_key]
|
55
56
|
end
|
57
|
+
|
58
|
+
if left_parenthesis && style == :special_inside_parentheses
|
59
|
+
return [left_parenthesis.column + 1, :first_colmn_after_left_parenthesis]
|
60
|
+
end
|
61
|
+
|
62
|
+
[left_brace.source_line =~ /\S/, :start_of_line]
|
63
|
+
end
|
64
|
+
|
65
|
+
def hash_pair_where_value_beginning_with(left_brace)
|
66
|
+
node = node_beginning_with(left_brace)
|
67
|
+
node.parent&.pair_type? ? node.parent : nil
|
68
|
+
end
|
69
|
+
|
70
|
+
def node_beginning_with(left_brace)
|
71
|
+
processed_source.ast.each_descendant do |node|
|
72
|
+
if node.loc.is_a?(Parser::Source::Map::Collection) && (node.loc.begin == left_brace)
|
73
|
+
break node
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def key_and_value_begin_on_same_line?(pair)
|
79
|
+
same_line?(pair.key, pair.value)
|
56
80
|
end
|
57
81
|
|
58
82
|
def detected_styles(actual_column, offset, left_parenthesis, left_brace)
|
@@ -73,8 +97,8 @@ module RuboCop
|
|
73
97
|
styles
|
74
98
|
end
|
75
99
|
|
76
|
-
def incorrect_style_detected(styles, first,
|
77
|
-
msg = message(base_description(
|
100
|
+
def incorrect_style_detected(styles, first, base_column_type)
|
101
|
+
msg = message(base_description(base_column_type))
|
78
102
|
|
79
103
|
add_offense(first, message: msg) do |corrector|
|
80
104
|
autocorrect(corrector, first)
|
@@ -51,9 +51,13 @@ module RuboCop
|
|
51
51
|
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
52
52
|
end
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
54
|
+
NOT_GIVEN = Module.new
|
55
|
+
def range_with_surrounding_space(range_positional = NOT_GIVEN, # rubocop:disable Metrics/ParameterLists
|
56
|
+
range: NOT_GIVEN, side: :both, newlines: true,
|
57
|
+
whitespace: false, continuations: false)
|
58
|
+
|
59
|
+
range = range_positional unless range_positional == NOT_GIVEN
|
60
|
+
|
57
61
|
buffer = @processed_source.buffer
|
58
62
|
src = buffer.source
|
59
63
|
|
@@ -72,7 +72,7 @@ module RuboCop
|
|
72
72
|
if (preferred_accessors = preferred_accessors(node))
|
73
73
|
corrector.replace(node, preferred_accessors)
|
74
74
|
else
|
75
|
-
range = range_with_surrounding_space(
|
75
|
+
range = range_with_surrounding_space(node.loc.expression, side: :left)
|
76
76
|
corrector.remove(range)
|
77
77
|
end
|
78
78
|
end
|
@@ -133,7 +133,7 @@ module RuboCop
|
|
133
133
|
def register_offense_to_method_definition_arguments(method_definition)
|
134
134
|
add_offense(arguments_range(method_definition)) do |corrector|
|
135
135
|
arguments_range = range_with_surrounding_space(
|
136
|
-
|
136
|
+
method_definition.arguments.source_range, side: :left
|
137
137
|
)
|
138
138
|
corrector.replace(arguments_range, '(...)')
|
139
139
|
end
|
@@ -184,6 +184,8 @@ module RuboCop
|
|
184
184
|
end
|
185
185
|
end
|
186
186
|
|
187
|
+
alias on_numblock on_block
|
188
|
+
|
187
189
|
private
|
188
190
|
|
189
191
|
def autocorrect(corrector, node)
|
@@ -281,7 +283,7 @@ module RuboCop
|
|
281
283
|
def move_comment_before_block(corrector, comment, block_node, closing_brace)
|
282
284
|
range = block_node.chained? ? end_of_chain(block_node.parent).source_range : closing_brace
|
283
285
|
comment_range = range_between(range.end_pos, comment.loc.expression.end_pos)
|
284
|
-
corrector.remove(range_with_surrounding_space(
|
286
|
+
corrector.remove(range_with_surrounding_space(comment_range, side: :right))
|
285
287
|
corrector.insert_after(range, "\n")
|
286
288
|
|
287
289
|
corrector.insert_before(block_node, "#{comment.text}\n")
|
@@ -300,7 +302,7 @@ module RuboCop
|
|
300
302
|
|
301
303
|
def get_blocks(node, &block)
|
302
304
|
case node.type
|
303
|
-
when :block
|
305
|
+
when :block, :numblock
|
304
306
|
yield node
|
305
307
|
when :send
|
306
308
|
get_blocks(node.receiver, &block) if node.receiver
|
@@ -66,7 +66,7 @@ module RuboCop
|
|
66
66
|
|
67
67
|
def register_offense(comment, matched_keyword)
|
68
68
|
add_offense(comment, message: format(MSG, keyword: matched_keyword)) do |corrector|
|
69
|
-
range = range_with_surrounding_space(
|
69
|
+
range = range_with_surrounding_space(comment.loc.expression, newlines: false)
|
70
70
|
corrector.remove(range)
|
71
71
|
|
72
72
|
unless matched_keyword == 'end'
|
@@ -11,6 +11,10 @@ module RuboCop
|
|
11
11
|
# NOTE: A method definition is not considered empty if it contains
|
12
12
|
# comments.
|
13
13
|
#
|
14
|
+
# NOTE: Autocorrection will not be applied for the `compact` style
|
15
|
+
# if the resulting code is longer than the `Max` configuration for
|
16
|
+
# `Layout/LineLength`, but an offense will still be registered.
|
17
|
+
#
|
14
18
|
# @example EnforcedStyle: compact (default)
|
15
19
|
# # bad
|
16
20
|
# def foo(bar)
|
@@ -51,7 +55,12 @@ module RuboCop
|
|
51
55
|
return if node.body || comment_lines?(node)
|
52
56
|
return if correct_style?(node)
|
53
57
|
|
54
|
-
add_offense(node)
|
58
|
+
add_offense(node) do |corrector|
|
59
|
+
correction = corrected(node)
|
60
|
+
next if compact_style? && max_line_length && correction.size > max_line_length
|
61
|
+
|
62
|
+
corrector.replace(node, correction)
|
63
|
+
end
|
55
64
|
end
|
56
65
|
alias on_defs on_def
|
57
66
|
|
@@ -98,6 +107,12 @@ module RuboCop
|
|
98
107
|
def expanded_style?
|
99
108
|
style == :expanded
|
100
109
|
end
|
110
|
+
|
111
|
+
def max_line_length
|
112
|
+
return unless config.for_cop('Layout/LineLength')['Enabled']
|
113
|
+
|
114
|
+
config.for_cop('Layout/LineLength')['Max']
|
115
|
+
end
|
101
116
|
end
|
102
117
|
end
|
103
118
|
end
|
@@ -51,7 +51,7 @@ module RuboCop
|
|
51
51
|
text = comment.without(:encoding)
|
52
52
|
|
53
53
|
if text.blank?
|
54
|
-
corrector.remove(range_with_surrounding_space(range
|
54
|
+
corrector.remove(range_with_surrounding_space(range, side: :right))
|
55
55
|
else
|
56
56
|
corrector.replace(range, text)
|
57
57
|
end
|
@@ -42,7 +42,7 @@ module RuboCop
|
|
42
42
|
include RangeHelp
|
43
43
|
extend AutoCorrector
|
44
44
|
|
45
|
-
MSG = 'Consider using explicit block argument in the '\
|
45
|
+
MSG = 'Consider using explicit block argument in the ' \
|
46
46
|
"surrounding method's signature over `yield`."
|
47
47
|
|
48
48
|
# @!method yielding_block?(node)
|
@@ -69,6 +69,7 @@ module RuboCop
|
|
69
69
|
class FormatStringToken < Base
|
70
70
|
include ConfigurableEnforcedStyle
|
71
71
|
include IgnoredMethods
|
72
|
+
extend AutoCorrector
|
72
73
|
|
73
74
|
def on_str(node)
|
74
75
|
return if format_string_token?(node) || use_ignored_method?(node)
|
@@ -77,13 +78,8 @@ module RuboCop
|
|
77
78
|
return if detections.empty?
|
78
79
|
return if allowed_unannotated?(detections)
|
79
80
|
|
80
|
-
detections.each do |
|
81
|
-
|
82
|
-
correct_style_detected
|
83
|
-
else
|
84
|
-
style_detected(detected_style)
|
85
|
-
add_offense(token_range, message: message(detected_style))
|
86
|
-
end
|
81
|
+
detections.each do |detected_sequence, token_range|
|
82
|
+
check_sequence(detected_sequence, token_range)
|
87
83
|
end
|
88
84
|
end
|
89
85
|
|
@@ -106,6 +102,38 @@ module RuboCop
|
|
106
102
|
send_parent && ignored_method?(send_parent.method_name)
|
107
103
|
end
|
108
104
|
|
105
|
+
def check_sequence(detected_sequence, token_range)
|
106
|
+
if detected_sequence.style == style
|
107
|
+
correct_style_detected
|
108
|
+
elsif correctable_sequence?(detected_sequence.type)
|
109
|
+
style_detected(detected_sequence.style)
|
110
|
+
add_offense(token_range, message: message(detected_sequence.style)) do |corrector|
|
111
|
+
autocorrect_sequence(corrector, detected_sequence, token_range)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def correctable_sequence?(detected_type)
|
117
|
+
detected_type == 's' || style == :annotated || style == :unannotated
|
118
|
+
end
|
119
|
+
|
120
|
+
def autocorrect_sequence(corrector, detected_sequence, token_range)
|
121
|
+
return if style == :unannotated
|
122
|
+
|
123
|
+
name = detected_sequence.name
|
124
|
+
return if name.nil?
|
125
|
+
|
126
|
+
flags = detected_sequence.flags
|
127
|
+
width = detected_sequence.width
|
128
|
+
precision = detected_sequence.precision
|
129
|
+
type = detected_sequence.style == :template ? 's' : detected_sequence.type
|
130
|
+
correction = case style
|
131
|
+
when :annotated then "%<#{name}>#{flags}#{width}#{precision}#{type}"
|
132
|
+
when :template then "%#{flags}#{width}#{precision}{#{name}}"
|
133
|
+
end
|
134
|
+
corrector.replace(token_range, correction)
|
135
|
+
end
|
136
|
+
|
109
137
|
def unannotated_format?(node, detected_style)
|
110
138
|
detected_style == :unannotated && !format_string_in_typical_context?(node)
|
111
139
|
end
|
@@ -143,30 +171,33 @@ module RuboCop
|
|
143
171
|
def token_ranges(contents)
|
144
172
|
format_string = RuboCop::Cop::Utils::FormatString.new(contents.source)
|
145
173
|
|
146
|
-
format_string.format_sequences.each do |
|
147
|
-
next if
|
174
|
+
format_string.format_sequences.each do |detected_sequence|
|
175
|
+
next if detected_sequence.percent?
|
148
176
|
|
149
|
-
|
150
|
-
|
177
|
+
token = contents.begin.adjust(begin_pos: detected_sequence.begin_pos,
|
178
|
+
end_pos: detected_sequence.end_pos)
|
151
179
|
|
152
|
-
yield(
|
180
|
+
yield(detected_sequence, token)
|
153
181
|
end
|
154
182
|
end
|
155
183
|
|
156
184
|
def collect_detections(node)
|
157
185
|
detections = []
|
158
|
-
tokens(node) do |
|
159
|
-
unless unannotated_format?(node,
|
160
|
-
detections << [
|
186
|
+
tokens(node) do |detected_sequence, token_range|
|
187
|
+
unless unannotated_format?(node, detected_sequence.style)
|
188
|
+
detections << [detected_sequence, token_range]
|
161
189
|
end
|
162
190
|
end
|
163
191
|
detections
|
164
192
|
end
|
165
193
|
|
166
194
|
def allowed_unannotated?(detections)
|
167
|
-
return false
|
195
|
+
return false unless detections.all? do |detected_sequence,|
|
196
|
+
detected_sequence.style == :unannotated
|
197
|
+
end
|
198
|
+
return true if detections.size <= max_unannotated_placeholders_allowed
|
168
199
|
|
169
|
-
detections.
|
200
|
+
detections.any? { |detected_sequence,| !correctable_sequence?(detected_sequence.type) }
|
170
201
|
end
|
171
202
|
|
172
203
|
def max_unannotated_placeholders_allowed
|
@@ -182,7 +182,7 @@ module RuboCop
|
|
182
182
|
end
|
183
183
|
|
184
184
|
def remove_comment(corrector, node)
|
185
|
-
corrector.remove(range_with_surrounding_space(
|
185
|
+
corrector.remove(range_with_surrounding_space(node.pos, side: :right))
|
186
186
|
end
|
187
187
|
|
188
188
|
def enable_comment(corrector)
|
@@ -110,7 +110,7 @@ module RuboCop
|
|
110
110
|
kw = if guard_clause_in_if
|
111
111
|
node.loc.keyword.source
|
112
112
|
else
|
113
|
-
|
113
|
+
node.inverse_keyword
|
114
114
|
end
|
115
115
|
|
116
116
|
register_offense(node, guard_clause_source(guard_clause), kw)
|
@@ -123,7 +123,7 @@ module RuboCop
|
|
123
123
|
return if allowed_consecutive_conditionals? &&
|
124
124
|
consecutive_conditionals?(node.parent, node)
|
125
125
|
|
126
|
-
register_offense(node, 'return',
|
126
|
+
register_offense(node, 'return', node.inverse_keyword)
|
127
127
|
end
|
128
128
|
|
129
129
|
def consecutive_conditionals?(parent, node)
|
@@ -134,14 +134,12 @@ module RuboCop
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
-
def opposite_keyword(node)
|
138
|
-
node.if? ? 'unless' : 'if'
|
139
|
-
end
|
140
|
-
|
141
137
|
def register_offense(node, scope_exiting_keyword, conditional_keyword)
|
142
138
|
condition, = node.node_parts
|
143
139
|
example = [scope_exiting_keyword, conditional_keyword, condition.source].join(' ')
|
144
140
|
if too_long_for_single_line?(node, example)
|
141
|
+
return if trivial?(node)
|
142
|
+
|
145
143
|
example = "#{conditional_keyword} #{condition.source}; #{scope_exiting_keyword}; end"
|
146
144
|
end
|
147
145
|
|
@@ -167,6 +165,10 @@ module RuboCop
|
|
167
165
|
accepted_if?(node, ending) || node.condition.multiline? || node.parent&.assignment?
|
168
166
|
end
|
169
167
|
|
168
|
+
def trivial?(node)
|
169
|
+
node.branches.one? && !node.if_branch.if_type? && !node.if_branch.begin_type?
|
170
|
+
end
|
171
|
+
|
170
172
|
def accepted_if?(node, ending)
|
171
173
|
return true if node.modifier_form? || node.ternary?
|
172
174
|
|