rubocop 0.92.0 → 1.2.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 +21 -7
- data/config/default.yml +169 -59
- data/exe/rubocop +1 -1
- data/lib/rubocop.rb +15 -3
- data/lib/rubocop/cached_data.rb +2 -1
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/version.rb +1 -1
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +4 -0
- data/lib/rubocop/config_loader.rb +19 -2
- data/lib/rubocop/config_loader_resolver.rb +7 -5
- data/lib/rubocop/config_validator.rb +7 -6
- data/lib/rubocop/cop/badge.rb +9 -24
- data/lib/rubocop/cop/base.rb +16 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +23 -3
- data/lib/rubocop/cop/commissioner.rb +36 -22
- data/lib/rubocop/cop/corrector.rb +3 -1
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/force.rb +1 -1
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +10 -10
- data/lib/rubocop/cop/layout/class_structure.rb +7 -0
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +6 -9
- data/lib/rubocop/cop/layout/else_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -7
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +24 -18
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -11
- data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +0 -4
- data/lib/rubocop/cop/layout/space_inside_parens.rb +35 -13
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +37 -13
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -0
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +18 -1
- data/lib/rubocop/cop/lint/boolean_symbol.rb +3 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -3
- data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +77 -0
- data/lib/rubocop/cop/lint/else_layout.rb +29 -3
- data/lib/rubocop/cop/lint/empty_block.rb +59 -0
- data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +37 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +17 -3
- data/lib/rubocop/cop/lint/loop.rb +0 -4
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
- data/lib/rubocop/cop/lint/nested_percent_literal.rb +14 -0
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +58 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +46 -13
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +27 -8
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +78 -0
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +95 -0
- data/lib/rubocop/cop/lint/to_json.rb +1 -1
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +185 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_setter_call.rb +6 -1
- data/lib/rubocop/cop/metrics/block_length.rb +3 -1
- data/lib/rubocop/cop/metrics/class_length.rb +14 -6
- data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -1
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +3 -3
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +12 -2
- data/lib/rubocop/cop/naming/heredoc_delimiter_case.rb +11 -5
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +67 -18
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -1
- data/lib/rubocop/cop/naming/variable_number.rb +82 -8
- data/lib/rubocop/cop/offense.rb +18 -5
- data/lib/rubocop/cop/security/open.rb +12 -10
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +6 -2
- data/lib/rubocop/cop/style/accessor_grouping.rb +3 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +142 -0
- data/lib/rubocop/cop/style/bisected_attr_accessor.rb +0 -4
- data/lib/rubocop/cop/style/case_like_if.rb +18 -6
- data/lib/rubocop/cop/style/class_equality_comparison.rb +64 -0
- data/lib/rubocop/cop/style/collection_compact.rb +85 -0
- data/lib/rubocop/cop/style/combinable_loops.rb +8 -1
- data/lib/rubocop/cop/style/comment_annotation.rb +6 -0
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +67 -0
- data/lib/rubocop/cop/style/double_negation.rb +6 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +6 -2
- data/lib/rubocop/cop/style/for.rb +0 -4
- data/lib/rubocop/cop/style/format_string_token.rb +48 -3
- data/lib/rubocop/cop/style/hash_syntax.rb +3 -3
- data/lib/rubocop/cop/style/keyword_parameters_order.rb +12 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +10 -13
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -11
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +7 -11
- data/lib/rubocop/cop/style/method_def_parentheses.rb +0 -4
- data/lib/rubocop/cop/style/mixin_grouping.rb +0 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +54 -7
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +99 -0
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -0
- data/lib/rubocop/cop/style/raise_args.rb +21 -9
- data/lib/rubocop/cop/style/redundant_begin.rb +36 -8
- data/lib/rubocop/cop/style/redundant_condition.rb +5 -1
- data/lib/rubocop/cop/style/redundant_interpolation.rb +6 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +45 -24
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -15
- data/lib/rubocop/cop/style/redundant_self.rb +3 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +16 -4
- data/lib/rubocop/cop/style/semicolon.rb +3 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +14 -2
- data/lib/rubocop/cop/style/swap_values.rb +108 -0
- data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
- data/lib/rubocop/cop/team.rb +6 -1
- data/lib/rubocop/cop/util.rb +5 -1
- data/lib/rubocop/cop/variable_force/branch.rb +0 -4
- data/lib/rubocop/ext/regexp_node.rb +35 -11
- data/lib/rubocop/ext/regexp_parser.rb +84 -0
- data/lib/rubocop/formatter/formatter_set.rb +2 -1
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +47 -0
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +2 -2
- data/lib/rubocop/options.rb +6 -1
- data/lib/rubocop/result_cache.rb +8 -2
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/runner.rb +4 -4
- data/lib/rubocop/target_finder.rb +23 -25
- data/lib/rubocop/version.rb +56 -6
- metadata +22 -8
- data/lib/rubocop/cop/mixin/regexp_literal_help.rb +0 -43
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop enforces the use of `Object#instance_of?` instead of class comparison
|
7
|
+
# for equality.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# var.class == Date
|
12
|
+
# var.class.equal?(Date)
|
13
|
+
# var.class.eql?(Date)
|
14
|
+
# var.class.name == 'Date'
|
15
|
+
#
|
16
|
+
# # good
|
17
|
+
# var.instance_of?(Date)
|
18
|
+
#
|
19
|
+
class ClassEqualityComparison < Base
|
20
|
+
include RangeHelp
|
21
|
+
include IgnoredMethods
|
22
|
+
extend AutoCorrector
|
23
|
+
|
24
|
+
MSG = 'Use `instance_of?(%<class_name>s)` instead of comparing classes.'
|
25
|
+
|
26
|
+
RESTRICT_ON_SEND = %i[== equal? eql?].freeze
|
27
|
+
|
28
|
+
def_node_matcher :class_comparison_candidate?, <<~PATTERN
|
29
|
+
(send
|
30
|
+
{$(send _ :class) (send $(send _ :class) :name)}
|
31
|
+
{:== :equal? :eql?} $_)
|
32
|
+
PATTERN
|
33
|
+
|
34
|
+
def on_send(node)
|
35
|
+
def_node = node.each_ancestor(:def, :defs).first
|
36
|
+
return if def_node && ignored_method?(def_node.method_name)
|
37
|
+
|
38
|
+
class_comparison_candidate?(node) do |receiver_node, class_node|
|
39
|
+
range = offense_range(receiver_node, node)
|
40
|
+
class_name = class_name(class_node, node)
|
41
|
+
|
42
|
+
add_offense(range, message: format(MSG, class_name: class_name)) do |corrector|
|
43
|
+
corrector.replace(range, "instance_of?(#{class_name})")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def class_name(class_node, node)
|
51
|
+
if node.children.first.method?(:name)
|
52
|
+
class_node.source.delete('"').delete("'")
|
53
|
+
else
|
54
|
+
class_node.source
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def offense_range(receiver_node, node)
|
59
|
+
range_between(receiver_node.loc.selector.begin_pos, node.source_range.end_pos)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for places where custom logic on rejection nils from arrays
|
7
|
+
# and hashes can be replaced with `{Array,Hash}#{compact,compact!}`.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# array.reject { |e| e.nil? }
|
12
|
+
# array.select { |e| !e.nil? }
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# array.compact
|
16
|
+
#
|
17
|
+
# # bad
|
18
|
+
# hash.reject! { |k, v| v.nil? }
|
19
|
+
# hash.select! { |k, v| !v.nil? }
|
20
|
+
#
|
21
|
+
# # good
|
22
|
+
# hash.compact!
|
23
|
+
#
|
24
|
+
class CollectionCompact < Base
|
25
|
+
include RangeHelp
|
26
|
+
extend AutoCorrector
|
27
|
+
|
28
|
+
MSG = 'Use `%<good>s` instead of `%<bad>s`.'
|
29
|
+
|
30
|
+
RESTRICT_ON_SEND = %i[reject reject! select select!].freeze
|
31
|
+
|
32
|
+
def_node_matcher :reject_method?, <<~PATTERN
|
33
|
+
(block
|
34
|
+
(send
|
35
|
+
_ ${:reject :reject!})
|
36
|
+
$(args ...)
|
37
|
+
(send
|
38
|
+
$(lvar _) :nil?))
|
39
|
+
PATTERN
|
40
|
+
|
41
|
+
def_node_matcher :select_method?, <<~PATTERN
|
42
|
+
(block
|
43
|
+
(send
|
44
|
+
_ ${:select :select!})
|
45
|
+
$(args ...)
|
46
|
+
(send
|
47
|
+
(send
|
48
|
+
$(lvar _) :nil?) :!))
|
49
|
+
PATTERN
|
50
|
+
|
51
|
+
def on_send(node)
|
52
|
+
block_node = node.parent
|
53
|
+
return unless block_node&.block_type?
|
54
|
+
|
55
|
+
return unless (method_name, args, receiver =
|
56
|
+
reject_method?(block_node) || select_method?(block_node))
|
57
|
+
|
58
|
+
return unless args.last.source == receiver.source
|
59
|
+
|
60
|
+
range = offense_range(node, block_node)
|
61
|
+
good = good_method_name(method_name)
|
62
|
+
message = format(MSG, good: good, bad: range.source)
|
63
|
+
|
64
|
+
add_offense(range, message: message) do |corrector|
|
65
|
+
corrector.replace(range, good)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def good_method_name(method_name)
|
72
|
+
if method_name.to_s.end_with?('!')
|
73
|
+
'compact!'
|
74
|
+
else
|
75
|
+
'compact'
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def offense_range(send_node, block_node)
|
80
|
+
range_between(send_node.loc.selector.begin_pos, block_node.loc.end.end_pos)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -49,6 +49,12 @@ module RuboCop
|
|
49
49
|
# end
|
50
50
|
# end
|
51
51
|
#
|
52
|
+
# # good
|
53
|
+
# def method
|
54
|
+
# each_slice(2) { |slice| do_something(slice) }
|
55
|
+
# each_slice(3) { |slice| do_something(slice) }
|
56
|
+
# end
|
57
|
+
#
|
52
58
|
class CombinableLoops < Base
|
53
59
|
MSG = 'Combine this loop with the previous loop.'
|
54
60
|
|
@@ -76,7 +82,8 @@ module RuboCop
|
|
76
82
|
def same_collection_looping?(node, sibling)
|
77
83
|
sibling&.block_type? &&
|
78
84
|
sibling.send_node.method?(node.method_name) &&
|
79
|
-
sibling.send_node.receiver == node.send_node.receiver
|
85
|
+
sibling.send_node.receiver == node.send_node.receiver &&
|
86
|
+
sibling.send_node.arguments == node.send_node.arguments
|
80
87
|
end
|
81
88
|
end
|
82
89
|
end
|
@@ -6,6 +6,12 @@ module RuboCop
|
|
6
6
|
# This cop checks that comment annotation keywords are written according
|
7
7
|
# to guidelines.
|
8
8
|
#
|
9
|
+
# NOTE: With a multiline comment block (where each line is only a
|
10
|
+
# comment), only the first line will be able to register an offense, even
|
11
|
+
# if an annotation keyword starts another line. This is done to prevent
|
12
|
+
# incorrect registering of keywords (eg. `review`) inside a paragraph as an
|
13
|
+
# annotation.
|
14
|
+
#
|
9
15
|
# @example
|
10
16
|
# # bad
|
11
17
|
# # TODO make better
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# When using `class_eval` (or other `eval`) with string interpolation,
|
7
|
+
# add a comment block showing its appearance if interpolated (a practice used in Rails code).
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # from activesupport/lib/active_support/core_ext/string/output_safety.rb
|
11
|
+
#
|
12
|
+
# # bad
|
13
|
+
# UNSAFE_STRING_METHODS.each do |unsafe_method|
|
14
|
+
# if 'String'.respond_to?(unsafe_method)
|
15
|
+
# class_eval <<-EOT, __FILE__, __LINE__ + 1
|
16
|
+
# def #{unsafe_method}(*params, &block)
|
17
|
+
# to_str.#{unsafe_method}(*params, &block)
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# def #{unsafe_method}!(*params)
|
21
|
+
# @dirty = true
|
22
|
+
# super
|
23
|
+
# end
|
24
|
+
# EOT
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # good
|
29
|
+
# UNSAFE_STRING_METHODS.each do |unsafe_method|
|
30
|
+
# if 'String'.respond_to?(unsafe_method)
|
31
|
+
# class_eval <<-EOT, __FILE__, __LINE__ + 1
|
32
|
+
# def #{unsafe_method}(*params, &block) # def capitalize(*params, &block)
|
33
|
+
# to_str.#{unsafe_method}(*params, &block) # to_str.capitalize(*params, &block)
|
34
|
+
# end # end
|
35
|
+
#
|
36
|
+
# def #{unsafe_method}!(*params) # def capitalize!(*params)
|
37
|
+
# @dirty = true # @dirty = true
|
38
|
+
# super # super
|
39
|
+
# end # end
|
40
|
+
# EOT
|
41
|
+
# end
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
class DocumentDynamicEvalDefinition < Base
|
45
|
+
MSG = 'Add a comment block showing its appearance if interpolated.'
|
46
|
+
|
47
|
+
RESTRICT_ON_SEND = %i[eval class_eval module_eval instance_eval].freeze
|
48
|
+
|
49
|
+
def on_send(node)
|
50
|
+
arg_node = node.first_argument
|
51
|
+
return unless arg_node&.dstr_type?
|
52
|
+
|
53
|
+
add_offense(node.loc.selector) unless comment_docs?(arg_node)
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def comment_docs?(node)
|
59
|
+
node.each_child_node(:begin).all? do |begin_node|
|
60
|
+
source_line = processed_source.lines[begin_node.first_line - 1]
|
61
|
+
source_line.match?(/\s*#[^{]+/)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -34,6 +34,7 @@ module RuboCop
|
|
34
34
|
# this is rarely a problem in practice.
|
35
35
|
class DoubleNegation < Base
|
36
36
|
include ConfigurableEnforcedStyle
|
37
|
+
extend AutoCorrector
|
37
38
|
|
38
39
|
MSG = 'Avoid the use of double negation (`!!`).'
|
39
40
|
RESTRICT_ON_SEND = %i[!].freeze
|
@@ -44,7 +45,11 @@ module RuboCop
|
|
44
45
|
return unless double_negative?(node) && node.prefix_bang?
|
45
46
|
return if style == :allowed_in_returns && allowed_in_returns?(node)
|
46
47
|
|
47
|
-
|
48
|
+
location = node.loc.selector
|
49
|
+
add_offense(location) do |corrector|
|
50
|
+
corrector.remove(location)
|
51
|
+
corrector.insert_after(node, '.nil?')
|
52
|
+
end
|
48
53
|
end
|
49
54
|
|
50
55
|
private
|
@@ -57,12 +57,16 @@ module RuboCop
|
|
57
57
|
yielding_block?(block_node) do |send_node, block_args, yield_args|
|
58
58
|
return unless yielding_arguments?(block_args, yield_args)
|
59
59
|
|
60
|
+
def_node = block_node.each_ancestor(:def, :defs).first
|
61
|
+
# if `yield` is being called outside of a method context, ignore
|
62
|
+
# this is not a valid ruby pattern, but can happen in haml or erb,
|
63
|
+
# so this can cause crashes in haml_lint
|
64
|
+
return unless def_node
|
65
|
+
|
60
66
|
add_offense(block_node) do |corrector|
|
61
67
|
corrector.remove(block_body_range(block_node, send_node))
|
62
68
|
|
63
69
|
add_block_argument(send_node, corrector)
|
64
|
-
|
65
|
-
def_node = block_node.each_ancestor(:def, :defs).first
|
66
70
|
add_block_argument(def_node, corrector) if @def_nodes.add?(def_node)
|
67
71
|
end
|
68
72
|
end
|
@@ -49,8 +49,6 @@ module RuboCop
|
|
49
49
|
|
50
50
|
def on_for(node)
|
51
51
|
if style == :each
|
52
|
-
return unless opposite_style_detected
|
53
|
-
|
54
52
|
add_offense(node, message: PREFER_EACH) do |corrector|
|
55
53
|
ForToEachCorrector.new(node).call(corrector)
|
56
54
|
end
|
@@ -63,8 +61,6 @@ module RuboCop
|
|
63
61
|
return unless suspect_enumerable?(node)
|
64
62
|
|
65
63
|
if style == :for
|
66
|
-
return unless opposite_style_detected
|
67
|
-
|
68
64
|
add_offense(node, message: PREFER_FOR) do |corrector|
|
69
65
|
EachToForCorrector.new(node).call(corrector)
|
70
66
|
end
|
@@ -33,10 +33,31 @@ module RuboCop
|
|
33
33
|
#
|
34
34
|
# # bad
|
35
35
|
# format('%<greeting>s', greeting: 'Hello')
|
36
|
-
# format('%{greeting}', 'Hello')
|
36
|
+
# format('%{greeting}', greeting: 'Hello')
|
37
37
|
#
|
38
38
|
# # good
|
39
39
|
# format('%s', 'Hello')
|
40
|
+
#
|
41
|
+
# It is allowed to contain unannotated token
|
42
|
+
# if the number of them is less than or equals to
|
43
|
+
# `MaxUnannotatedPlaceholdersAllowed`.
|
44
|
+
#
|
45
|
+
# @example MaxUnannotatedPlaceholdersAllowed: 0
|
46
|
+
#
|
47
|
+
# # bad
|
48
|
+
# format('%06d', 10)
|
49
|
+
# format('%s %s.', 'Hello', 'world')
|
50
|
+
#
|
51
|
+
# # good
|
52
|
+
# format('%<number>06d', number: 10)
|
53
|
+
#
|
54
|
+
# @example MaxUnannotatedPlaceholdersAllowed: 1 (default)
|
55
|
+
#
|
56
|
+
# # bad
|
57
|
+
# format('%s %s.', 'Hello', 'world')
|
58
|
+
#
|
59
|
+
# # good
|
60
|
+
# format('%06d', 10)
|
40
61
|
class FormatStringToken < Base
|
41
62
|
include ConfigurableEnforcedStyle
|
42
63
|
|
@@ -44,8 +65,12 @@ module RuboCop
|
|
44
65
|
return unless node.value.include?('%')
|
45
66
|
return if node.each_ancestor(:xstr, :regexp).any?
|
46
67
|
|
47
|
-
|
48
|
-
|
68
|
+
detections = collect_detections(node)
|
69
|
+
return if detections.empty?
|
70
|
+
return if allowed_unannotated?(detections)
|
71
|
+
|
72
|
+
detections.each do |detected_style, token_range|
|
73
|
+
if detected_style == style
|
49
74
|
correct_style_detected
|
50
75
|
else
|
51
76
|
style_detected(detected_style)
|
@@ -112,6 +137,26 @@ module RuboCop
|
|
112
137
|
yield(detected_style, token)
|
113
138
|
end
|
114
139
|
end
|
140
|
+
|
141
|
+
def collect_detections(node)
|
142
|
+
detections = []
|
143
|
+
tokens(node) do |detected_style, token_range|
|
144
|
+
unless unannotated_format?(node, detected_style)
|
145
|
+
detections << [detected_style, token_range]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
detections
|
149
|
+
end
|
150
|
+
|
151
|
+
def allowed_unannotated?(detections)
|
152
|
+
return false if detections.size > max_unannotated_placeholders_allowed
|
153
|
+
|
154
|
+
detections.all? { |detected_style,| detected_style == :unannotated }
|
155
|
+
end
|
156
|
+
|
157
|
+
def max_unannotated_placeholders_allowed
|
158
|
+
cop_config['MaxUnannotatedPlaceholdersAllowed']
|
159
|
+
end
|
115
160
|
end
|
116
161
|
end
|
117
162
|
end
|
@@ -97,10 +97,10 @@ module RuboCop
|
|
97
97
|
end
|
98
98
|
|
99
99
|
def no_mixed_keys_check(pairs)
|
100
|
-
if
|
101
|
-
check(pairs, ':', MSG_NO_MIXED_KEYS)
|
102
|
-
else
|
100
|
+
if sym_indices?(pairs)
|
103
101
|
check(pairs, pairs.first.inverse_delimiter, MSG_NO_MIXED_KEYS)
|
102
|
+
else
|
103
|
+
check(pairs, ':', MSG_NO_MIXED_KEYS)
|
104
104
|
end
|
105
105
|
end
|
106
106
|
|
@@ -34,6 +34,10 @@ module RuboCop
|
|
34
34
|
add_offense(node) do |corrector|
|
35
35
|
if node.parent.find(&:kwoptarg_type?) == node
|
36
36
|
corrector.insert_before(node, "#{kwarg_nodes.map(&:source).join(', ')}, ")
|
37
|
+
|
38
|
+
arguments = node.each_ancestor(:def, :defs).first.arguments
|
39
|
+
append_newline_to_last_kwoptarg(arguments, corrector) unless parentheses?(arguments)
|
40
|
+
|
37
41
|
remove_kwargs(kwarg_nodes, corrector)
|
38
42
|
end
|
39
43
|
end
|
@@ -41,6 +45,14 @@ module RuboCop
|
|
41
45
|
|
42
46
|
private
|
43
47
|
|
48
|
+
def append_newline_to_last_kwoptarg(arguments, corrector)
|
49
|
+
last_argument = arguments.last
|
50
|
+
return if last_argument.kwrestarg_type? || last_argument.blockarg_type?
|
51
|
+
|
52
|
+
last_kwoptarg = arguments.reverse.find(&:kwoptarg_type?)
|
53
|
+
corrector.insert_after(last_kwoptarg, "\n")
|
54
|
+
end
|
55
|
+
|
44
56
|
def remove_kwargs(kwarg_nodes, corrector)
|
45
57
|
kwarg_nodes.each do |kwarg|
|
46
58
|
with_space = range_with_surrounding_space(range: kwarg.source_range)
|
@@ -144,25 +144,22 @@ module RuboCop
|
|
144
144
|
# # good
|
145
145
|
# Array 1
|
146
146
|
class MethodCallWithArgsParentheses < Base
|
147
|
+
require_relative 'method_call_with_args_parentheses/omit_parentheses'
|
148
|
+
require_relative 'method_call_with_args_parentheses/require_parentheses'
|
149
|
+
|
147
150
|
include ConfigurableEnforcedStyle
|
148
151
|
include IgnoredMethods
|
149
152
|
include IgnoredPattern
|
153
|
+
include RequireParentheses
|
154
|
+
include OmitParentheses
|
150
155
|
extend AutoCorrector
|
151
156
|
|
152
|
-
def
|
153
|
-
|
154
|
-
return unless style_configured?
|
155
|
-
|
156
|
-
case style
|
157
|
-
when :require_parentheses
|
158
|
-
extend RequireParentheses
|
159
|
-
when :omit_parentheses
|
160
|
-
extend OmitParentheses
|
161
|
-
end
|
157
|
+
def on_send(node)
|
158
|
+
send(style, node) # call require_parentheses or omit_parentheses
|
162
159
|
end
|
163
|
-
|
164
|
-
|
165
|
-
|
160
|
+
alias on_csend on_send
|
161
|
+
alias on_super on_send
|
162
|
+
alias on_yield on_send
|
166
163
|
|
167
164
|
private
|
168
165
|
|