rubocop 0.93.1 → 1.6.1
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 +36 -16
- data/config/default.yml +276 -82
- data/config/obsoletion.yml +196 -0
- data/exe/rubocop +1 -1
- data/lib/rubocop.rb +31 -2
- data/lib/rubocop/cli.rb +5 -1
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +1 -1
- data/lib/rubocop/cli/command/execute_runner.rb +26 -11
- data/lib/rubocop/cli/command/suggest_extensions.rb +80 -0
- 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 +34 -8
- data/lib/rubocop/config_loader_resolver.rb +12 -6
- data/lib/rubocop/config_obsoletion.rb +65 -247
- data/lib/rubocop/config_obsoletion/changed_enforced_styles.rb +33 -0
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +21 -0
- data/lib/rubocop/config_obsoletion/cop_rule.rb +34 -0
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +44 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +44 -0
- data/lib/rubocop/config_obsoletion/removed_cop.rb +41 -0
- data/lib/rubocop/config_obsoletion/renamed_cop.rb +34 -0
- data/lib/rubocop/config_obsoletion/rule.rb +41 -0
- data/lib/rubocop/config_obsoletion/split_cop.rb +27 -0
- data/lib/rubocop/config_regeneration.rb +1 -1
- data/lib/rubocop/config_validator.rb +25 -10
- data/lib/rubocop/cop/autocorrect_logic.rb +21 -6
- data/lib/rubocop/cop/badge.rb +9 -24
- data/lib/rubocop/cop/base.rb +33 -16
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +26 -6
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/commissioner.rb +37 -23
- data/lib/rubocop/cop/cop.rb +2 -2
- data/lib/rubocop/cop/corrector.rb +3 -1
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/string_literal_corrector.rb +6 -8
- data/lib/rubocop/cop/force.rb +1 -1
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +3 -3
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +4 -5
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +1 -1
- data/lib/rubocop/cop/generator.rb +3 -10
- data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -4
- data/lib/rubocop/cop/layout/class_structure.rb +22 -3
- data/lib/rubocop/cop/layout/def_end_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +15 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +80 -10
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +6 -1
- 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/end_of_line.rb +5 -5
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -2
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +7 -2
- data/lib/rubocop/cop/layout/hash_alignment.rb +4 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +12 -0
- data/lib/rubocop/cop/layout/line_length.rb +10 -13
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +7 -3
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +24 -18
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +4 -1
- 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_regexp_literal.rb +2 -1
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +26 -2
- data/lib/rubocop/cop/lint/debugger.rb +17 -28
- data/lib/rubocop/cop/lint/duplicate_branch.rb +93 -0
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +2 -12
- 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 +82 -0
- data/lib/rubocop/cop/lint/empty_class.rb +93 -0
- data/lib/rubocop/cop/lint/flip_flop.rb +8 -2
- data/lib/rubocop/cop/lint/interpolation_check.rb +7 -2
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +39 -7
- data/lib/rubocop/cop/lint/loop.rb +4 -4
- data/lib/rubocop/cop/lint/missing_super.rb +7 -4
- 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/redundant_cop_enable_directive.rb +19 -16
- data/lib/rubocop/cop/lint/shadowed_exception.rb +4 -5
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +13 -0
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +86 -0
- data/lib/rubocop/cop/lint/to_json.rb +1 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +85 -0
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +199 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +2 -2
- data/lib/rubocop/cop/lint/useless_method_definition.rb +2 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +6 -1
- data/lib/rubocop/cop/metrics/abc_size.rb +25 -1
- data/lib/rubocop/cop/metrics/block_length.rb +13 -7
- data/lib/rubocop/cop/metrics/method_length.rb +7 -2
- data/lib/rubocop/cop/metrics/parameter_lists.rb +68 -2
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +20 -10
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +146 -0
- data/lib/rubocop/cop/metrics/utils/repeated_csend_discount.rb +6 -1
- data/lib/rubocop/cop/migration/department_name.rb +1 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +4 -3
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +9 -1
- data/lib/rubocop/cop/mixin/ignored_methods.rb +36 -3
- data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +6 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +9 -4
- data/lib/rubocop/cop/mixin/string_help.rb +4 -1
- data/lib/rubocop/cop/mixin/visibility_help.rb +1 -3
- data/lib/rubocop/cop/naming/accessor_method_name.rb +15 -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 +100 -8
- data/lib/rubocop/cop/offense.rb +3 -3
- data/lib/rubocop/cop/security/open.rb +12 -10
- data/lib/rubocop/cop/style/accessor_grouping.rb +1 -1
- data/lib/rubocop/cop/style/and_or.rb +11 -3
- 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 +0 -4
- data/lib/rubocop/cop/style/character_literal.rb +10 -11
- data/lib/rubocop/cop/style/class_and_module_children.rb +8 -3
- data/lib/rubocop/cop/style/collection_compact.rb +91 -0
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +169 -0
- data/lib/rubocop/cop/style/documentation.rb +12 -1
- data/lib/rubocop/cop/style/double_negation.rb +6 -1
- data/lib/rubocop/cop/style/float_division.rb +44 -1
- data/lib/rubocop/cop/style/format_string.rb +8 -3
- data/lib/rubocop/cop/style/format_string_token.rb +47 -2
- data/lib/rubocop/cop/style/hash_syntax.rb +3 -3
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +7 -2
- data/lib/rubocop/cop/style/if_inside_else.rb +37 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +11 -3
- data/lib/rubocop/cop/style/if_with_semicolon.rb +39 -4
- data/lib/rubocop/cop/style/infinite_loop.rb +4 -0
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -1
- 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 +8 -13
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +7 -11
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -2
- data/lib/rubocop/cop/style/mixin_grouping.rb +0 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +55 -7
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +106 -0
- data/lib/rubocop/cop/style/nil_lambda.rb +52 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +14 -11
- data/lib/rubocop/cop/style/perl_backrefs.rb +86 -9
- data/lib/rubocop/cop/style/raise_args.rb +21 -6
- data/lib/rubocop/cop/style/redundant_argument.rb +88 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +4 -0
- data/lib/rubocop/cop/style/redundant_regexp_character_class.rb +7 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +24 -8
- 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/single_line_block_params.rb +30 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +65 -3
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -13
- data/lib/rubocop/cop/style/static_class.rb +97 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +39 -2
- data/lib/rubocop/cop/style/string_literals.rb +14 -8
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +4 -3
- data/lib/rubocop/cop/style/swap_values.rb +108 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +5 -3
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +3 -1
- data/lib/rubocop/cop/style/while_until_modifier.rb +9 -0
- data/lib/rubocop/cop/team.rb +6 -1
- data/lib/rubocop/cop/util.rb +6 -2
- data/lib/rubocop/cop/variable_force/branch.rb +1 -1
- data/lib/rubocop/cop/variable_force/scope.rb +1 -1
- data/lib/rubocop/core_ext/hash.rb +20 -0
- data/lib/rubocop/ext/regexp_node.rb +36 -11
- data/lib/rubocop/ext/regexp_parser.rb +95 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +21 -6
- data/lib/rubocop/formatter/emacs_style_formatter.rb +2 -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/simple_text_formatter.rb +2 -0
- data/lib/rubocop/formatter/tap_formatter.rb +2 -0
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/lockfile.rb +40 -0
- data/lib/rubocop/magic_comment.rb +2 -2
- data/lib/rubocop/options.rb +11 -1
- data/lib/rubocop/rake_task.rb +2 -2
- data/lib/rubocop/rspec/shared_contexts.rb +4 -0
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/target_ruby.rb +65 -1
- data/lib/rubocop/version.rb +56 -6
- metadata +50 -9
- data/bin/console +0 -10
- data/bin/rubocop-profile +0 -32
- data/bin/setup +0 -7
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for uses of `if-else` and ternary operators with a negated condition
|
7
|
+
# which can be simplified by inverting condition and swapping branches.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# if !x
|
12
|
+
# do_something
|
13
|
+
# else
|
14
|
+
# do_something_else
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# if x
|
19
|
+
# do_something_else
|
20
|
+
# else
|
21
|
+
# do_something
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
# # bad
|
25
|
+
# !x ? do_something : do_something_else
|
26
|
+
#
|
27
|
+
# # good
|
28
|
+
# x ? do_something_else : do_something
|
29
|
+
#
|
30
|
+
class NegatedIfElseCondition < Base
|
31
|
+
include RangeHelp
|
32
|
+
extend AutoCorrector
|
33
|
+
|
34
|
+
MSG = 'Invert the negated condition and swap the %<type>s branches.'
|
35
|
+
|
36
|
+
NEGATED_EQUALITY_METHODS = %i[!= !~].freeze
|
37
|
+
|
38
|
+
def_node_matcher :double_negation?, '(send (send _ :!) :!)'
|
39
|
+
|
40
|
+
def self.autocorrect_incompatible_with
|
41
|
+
[Style::InverseMethods, Style::Not]
|
42
|
+
end
|
43
|
+
|
44
|
+
def on_new_investigation
|
45
|
+
@corrected_nodes = nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def on_if(node)
|
49
|
+
return unless if_else?(node)
|
50
|
+
|
51
|
+
condition = node.condition
|
52
|
+
return if double_negation?(condition) || !negated_condition?(condition)
|
53
|
+
|
54
|
+
type = node.ternary? ? 'ternary' : 'if-else'
|
55
|
+
add_offense(node, message: format(MSG, type: type)) do |corrector|
|
56
|
+
unless corrected_ancestor?(node)
|
57
|
+
correct_negated_condition(corrector, condition)
|
58
|
+
swap_branches(corrector, node)
|
59
|
+
|
60
|
+
@corrected_nodes ||= Set.new.compare_by_identity
|
61
|
+
@corrected_nodes.add(node)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def if_else?(node)
|
69
|
+
else_branch = node.else_branch
|
70
|
+
!node.elsif? && else_branch && (!else_branch.if_type? || !else_branch.elsif?)
|
71
|
+
end
|
72
|
+
|
73
|
+
def negated_condition?(node)
|
74
|
+
node.send_type? &&
|
75
|
+
(node.negation_method? || NEGATED_EQUALITY_METHODS.include?(node.method_name))
|
76
|
+
end
|
77
|
+
|
78
|
+
def corrected_ancestor?(node)
|
79
|
+
node.each_ancestor(:if).any? { |ancestor| @corrected_nodes&.include?(ancestor) }
|
80
|
+
end
|
81
|
+
|
82
|
+
def correct_negated_condition(corrector, node)
|
83
|
+
receiver, method_name, rhs = *node
|
84
|
+
replacement =
|
85
|
+
if node.negation_method?
|
86
|
+
receiver.source
|
87
|
+
else
|
88
|
+
inverted_method = method_name.to_s.sub('!', '=')
|
89
|
+
"#{receiver.source} #{inverted_method} #{rhs.source}"
|
90
|
+
end
|
91
|
+
|
92
|
+
corrector.replace(node, replacement)
|
93
|
+
end
|
94
|
+
|
95
|
+
def swap_branches(corrector, node)
|
96
|
+
if node.if_branch.nil?
|
97
|
+
corrector.remove(range_by_whole_lines(node.loc.else, include_final_newline: true))
|
98
|
+
else
|
99
|
+
corrector.replace(node.if_branch, node.else_branch.source)
|
100
|
+
corrector.replace(node.else_branch, node.if_branch.source)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for lambdas that always return nil, which can be replaced
|
7
|
+
# with an empty lambda instead.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # bad
|
11
|
+
# -> { nil }
|
12
|
+
#
|
13
|
+
# lambda do
|
14
|
+
# next nil
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# # good
|
18
|
+
# -> {}
|
19
|
+
#
|
20
|
+
# lambda do
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# -> (x) { nil if x }
|
24
|
+
#
|
25
|
+
class NilLambda < Base
|
26
|
+
extend AutoCorrector
|
27
|
+
include RangeHelp
|
28
|
+
|
29
|
+
MSG = 'Use an empty lambda instead of always returning nil.'
|
30
|
+
|
31
|
+
def_node_matcher :nil_return?, <<~PATTERN
|
32
|
+
{ ({return next break} nil) (nil) }
|
33
|
+
PATTERN
|
34
|
+
|
35
|
+
def on_block(node)
|
36
|
+
return unless node.lambda?
|
37
|
+
return unless nil_return?(node.body)
|
38
|
+
|
39
|
+
add_offense(node) do |corrector|
|
40
|
+
range = if node.single_line?
|
41
|
+
range_with_surrounding_space(range: node.body.loc.expression)
|
42
|
+
else
|
43
|
+
range_by_whole_lines(node.body.loc.expression, include_final_newline: true)
|
44
|
+
end
|
45
|
+
|
46
|
+
corrector.remove(range)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -27,12 +27,13 @@ module RuboCop
|
|
27
27
|
# # bad
|
28
28
|
# 10_000_00 # typical representation of $10,000 in cents
|
29
29
|
#
|
30
|
-
class NumericLiterals <
|
30
|
+
class NumericLiterals < Base
|
31
31
|
# The parameter is called MinDigits (meaning the minimum number of
|
32
32
|
# digits for which an offense can be registered), but essentially it's
|
33
33
|
# a Max parameter (the maximum number of something that's allowed).
|
34
34
|
include ConfigurableMax
|
35
35
|
include IntegerNode
|
36
|
+
extend AutoCorrector
|
36
37
|
|
37
38
|
MSG = 'Use underscores(_) as thousands separator and ' \
|
38
39
|
'separate every 3 digits with them.'
|
@@ -46,12 +47,6 @@ module RuboCop
|
|
46
47
|
check(node)
|
47
48
|
end
|
48
49
|
|
49
|
-
def autocorrect(node)
|
50
|
-
lambda do |corrector|
|
51
|
-
corrector.replace(node, format_number(node))
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
50
|
private
|
56
51
|
|
57
52
|
def max_parameter_name
|
@@ -67,11 +62,19 @@ module RuboCop
|
|
67
62
|
|
68
63
|
case int
|
69
64
|
when /^\d+$/
|
70
|
-
|
65
|
+
return unless (self.max = int.size + 1)
|
66
|
+
|
67
|
+
register_offense(node)
|
71
68
|
when /\d{4}/, short_group_regex
|
72
|
-
|
73
|
-
|
74
|
-
|
69
|
+
return unless (self.config_to_allow_offenses = { 'Enabled' => false })
|
70
|
+
|
71
|
+
register_offense(node)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def register_offense(node)
|
76
|
+
add_offense(node) do |corrector|
|
77
|
+
corrector.replace(node, format_number(node))
|
75
78
|
end
|
76
79
|
end
|
77
80
|
|
@@ -4,7 +4,8 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# This cop looks for uses of Perl-style regexp match
|
7
|
-
# backreferences
|
7
|
+
# backreferences and their English versions like
|
8
|
+
# $1, $2, $&, &+, $MATCH, $PREMATCH, etc.
|
8
9
|
#
|
9
10
|
# @example
|
10
11
|
# # bad
|
@@ -15,19 +16,95 @@ module RuboCop
|
|
15
16
|
class PerlBackrefs < Base
|
16
17
|
extend AutoCorrector
|
17
18
|
|
18
|
-
|
19
|
+
MESSAGE_FORMAT = 'Prefer `%<preferred_expression>s` over `%<original_expression>s`.'
|
20
|
+
|
21
|
+
def on_back_ref(node)
|
22
|
+
on_back_ref_or_gvar_or_nth_ref(node)
|
23
|
+
end
|
24
|
+
|
25
|
+
def on_gvar(node)
|
26
|
+
on_back_ref_or_gvar_or_nth_ref(node)
|
27
|
+
end
|
19
28
|
|
20
29
|
def on_nth_ref(node)
|
21
|
-
|
22
|
-
|
23
|
-
parent_type = node.parent ? node.parent.type : nil
|
30
|
+
on_back_ref_or_gvar_or_nth_ref(node)
|
31
|
+
end
|
24
32
|
|
25
|
-
|
26
|
-
|
33
|
+
private
|
34
|
+
|
35
|
+
# @private
|
36
|
+
# @param [RuboCop::AST::Node] node
|
37
|
+
# @return [Boolean]
|
38
|
+
def derived_from_braceless_interpolation?(node)
|
39
|
+
%i[
|
40
|
+
dstr
|
41
|
+
regexp
|
42
|
+
xstr
|
43
|
+
].include?(node.parent&.type)
|
44
|
+
end
|
45
|
+
|
46
|
+
# @private
|
47
|
+
# @param [RuboCop::AST::Node] node
|
48
|
+
# @param [String] preferred_expression
|
49
|
+
# @return [String]
|
50
|
+
def format_message(node:, preferred_expression:)
|
51
|
+
original_expression = original_expression_of(node)
|
52
|
+
format(
|
53
|
+
MESSAGE_FORMAT,
|
54
|
+
original_expression: original_expression,
|
55
|
+
preferred_expression: preferred_expression
|
56
|
+
)
|
57
|
+
end
|
27
58
|
|
28
|
-
|
29
|
-
|
59
|
+
# @private
|
60
|
+
# @param [RuboCop::AST::Node] node
|
61
|
+
# @return [String]
|
62
|
+
def original_expression_of(node)
|
63
|
+
first = node.to_a.first
|
64
|
+
if first.is_a?(::Integer)
|
65
|
+
"$#{first}"
|
66
|
+
else
|
67
|
+
first.to_s
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
# @private
|
72
|
+
# @param [RuboCop::AST::Node] node
|
73
|
+
# @return [String, nil]
|
74
|
+
def preferred_expression_to(node)
|
75
|
+
first = node.to_a.first
|
76
|
+
case first
|
77
|
+
when ::Integer
|
78
|
+
"Regexp.last_match(#{first})"
|
79
|
+
when :$&, :$MATCH
|
80
|
+
'Regexp.last_match(0)'
|
81
|
+
when :$`, :$PREMATCH
|
82
|
+
'Regexp.last_match.pre_match'
|
83
|
+
when :$', :$POSTMATCH
|
84
|
+
'Regexp.last_match.post_match'
|
85
|
+
when :$+, :$LAST_PAREN_MATCH
|
86
|
+
'Regexp.last_match(-1)'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# @private
|
91
|
+
# @param [RuboCop::AST::Node] node
|
92
|
+
def on_back_ref_or_gvar_or_nth_ref(node)
|
93
|
+
preferred_expression = preferred_expression_to(node)
|
94
|
+
return unless preferred_expression
|
95
|
+
|
96
|
+
add_offense(
|
97
|
+
node,
|
98
|
+
message: format_message(
|
99
|
+
node: node,
|
100
|
+
preferred_expression: preferred_expression
|
101
|
+
)
|
102
|
+
) do |corrector|
|
103
|
+
if derived_from_braceless_interpolation?(node)
|
104
|
+
preferred_expression = "{#{preferred_expression}}"
|
30
105
|
end
|
106
|
+
|
107
|
+
corrector.replace(node, preferred_expression)
|
31
108
|
end
|
32
109
|
end
|
33
110
|
end
|
@@ -13,25 +13,32 @@ module RuboCop
|
|
13
13
|
# will also suggest constructing error objects when the exception is
|
14
14
|
# passed multiple arguments.
|
15
15
|
#
|
16
|
+
# The exploded style has an `AllowedCompactTypes` configuration
|
17
|
+
# option that takes an Array of exception name Strings.
|
18
|
+
#
|
16
19
|
# @example EnforcedStyle: exploded (default)
|
17
20
|
# # bad
|
18
|
-
# raise StandardError.new(
|
21
|
+
# raise StandardError.new('message')
|
19
22
|
#
|
20
23
|
# # good
|
21
|
-
# raise StandardError,
|
22
|
-
# fail
|
24
|
+
# raise StandardError, 'message'
|
25
|
+
# fail 'message'
|
23
26
|
# raise MyCustomError.new(arg1, arg2, arg3)
|
24
27
|
# raise MyKwArgError.new(key1: val1, key2: val2)
|
25
28
|
#
|
29
|
+
# # With `AllowedCompactTypes` set to ['MyWrappedError']
|
30
|
+
# raise MyWrappedError.new(obj)
|
31
|
+
# raise MyWrappedError.new(obj), 'message'
|
32
|
+
#
|
26
33
|
# @example EnforcedStyle: compact
|
27
34
|
# # bad
|
28
|
-
# raise StandardError,
|
35
|
+
# raise StandardError, 'message'
|
29
36
|
# raise RuntimeError, arg1, arg2, arg3
|
30
37
|
#
|
31
38
|
# # good
|
32
|
-
# raise StandardError.new(
|
39
|
+
# raise StandardError.new('message')
|
33
40
|
# raise MyCustomError.new(arg1, arg2, arg3)
|
34
|
-
# fail
|
41
|
+
# fail 'message'
|
35
42
|
class RaiseArgs < Base
|
36
43
|
include ConfigurableEnforcedStyle
|
37
44
|
extend AutoCorrector
|
@@ -102,6 +109,8 @@ module RuboCop
|
|
102
109
|
return unless first_arg.send_type? && first_arg.method?(:new)
|
103
110
|
return if acceptable_exploded_args?(first_arg.arguments)
|
104
111
|
|
112
|
+
return if allowed_non_exploded_type?(first_arg)
|
113
|
+
|
105
114
|
add_offense(node, message: format(EXPLODED_MSG, method: node.method_name)) do |corrector|
|
106
115
|
replacement = correction_compact_to_exploded(node)
|
107
116
|
|
@@ -123,6 +132,12 @@ module RuboCop
|
|
123
132
|
arg.hash_type? || arg.splat_type?
|
124
133
|
end
|
125
134
|
|
135
|
+
def allowed_non_exploded_type?(arg)
|
136
|
+
type = arg.receiver.const_name
|
137
|
+
|
138
|
+
Array(cop_config['AllowedCompactTypes']).include?(type)
|
139
|
+
end
|
140
|
+
|
126
141
|
def requires_parens?(parent)
|
127
142
|
parent.and_type? || parent.or_type? ||
|
128
143
|
parent.if_type? && parent.ternary?
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'parser/current'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module Style
|
8
|
+
# This cop checks for a redundant argument passed to certain methods.
|
9
|
+
#
|
10
|
+
# Limitations:
|
11
|
+
#
|
12
|
+
# 1. This cop matches for method names only and hence cannot tell apart
|
13
|
+
# methods with same name in different classes.
|
14
|
+
# 2. This cop is limited to methods with single parameter.
|
15
|
+
# 3. This cop is unsafe if certain special global variables (e.g. `$;`) are set.
|
16
|
+
# That depends on the nature of the target methods, of course.
|
17
|
+
#
|
18
|
+
# Method names and their redundant arguments can be configured like this:
|
19
|
+
#
|
20
|
+
# Methods:
|
21
|
+
# join: ''
|
22
|
+
# split: ' '
|
23
|
+
# foo: 2
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# # bad
|
27
|
+
# array.join('')
|
28
|
+
# [1, 2, 3].join("")
|
29
|
+
# string.split(" ")
|
30
|
+
# "first\nsecond".split(" ")
|
31
|
+
# A.foo(2)
|
32
|
+
#
|
33
|
+
# # good
|
34
|
+
# array.join
|
35
|
+
# [1, 2, 3].join
|
36
|
+
# string.split
|
37
|
+
# "first second".split
|
38
|
+
# A.foo
|
39
|
+
class RedundantArgument < Base
|
40
|
+
include RangeHelp
|
41
|
+
extend AutoCorrector
|
42
|
+
|
43
|
+
MSG = 'Argument %<arg>s is redundant because it is implied by default.'
|
44
|
+
|
45
|
+
def on_send(node)
|
46
|
+
return if node.receiver.nil?
|
47
|
+
return if node.arguments.count != 1
|
48
|
+
return unless redundant_argument?(node)
|
49
|
+
|
50
|
+
add_offense(node, message: format(MSG, arg: node.arguments.first.source)) do |corrector|
|
51
|
+
corrector.remove(argument_range(node))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def redundant_argument?(node)
|
58
|
+
redundant_argument = redundant_arg_for_method(node.method_name.to_s)
|
59
|
+
return false if redundant_argument.nil?
|
60
|
+
|
61
|
+
node.arguments.first == redundant_argument
|
62
|
+
end
|
63
|
+
|
64
|
+
def redundant_arg_for_method(method_name)
|
65
|
+
return nil unless cop_config['Methods'].key?(method_name)
|
66
|
+
|
67
|
+
@mem ||= {}
|
68
|
+
@mem[method_name] ||=
|
69
|
+
begin
|
70
|
+
arg = cop_config['Methods'].fetch(method_name)
|
71
|
+
buffer = Parser::Source::Buffer.new('(string)', 1)
|
72
|
+
buffer.source = arg.inspect
|
73
|
+
builder = RuboCop::AST::Builder.new
|
74
|
+
Parser::CurrentRuby.new(builder).parse(buffer)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def argument_range(node)
|
79
|
+
if node.parenthesized?
|
80
|
+
range_between(node.loc.begin.begin_pos, node.loc.end.end_pos)
|
81
|
+
else
|
82
|
+
range_with_surrounding_space(range: node.first_argument.source_range, newlines: false)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|