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
@@ -6,7 +6,12 @@ module RuboCop
|
|
6
6
|
module Utils
|
7
7
|
# @api private
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# Identifies repetitions `&.` on the same variable:
|
10
|
+
#
|
11
|
+
# my_var&.foo
|
12
|
+
# my_var&.bar # => repeated
|
13
|
+
# my_var = baz # => reset
|
14
|
+
# my_var&.qux # => not repeated
|
10
15
|
module RepeatedCsendDiscount
|
11
16
|
def reset_repeated_csend
|
12
17
|
@repeated_csend = {}
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
71
71
|
end
|
72
72
|
|
73
73
|
def qualified_legacy_cop_name(cop_name)
|
74
|
-
legacy_cop_names = RuboCop::ConfigObsoletion
|
74
|
+
legacy_cop_names = RuboCop::ConfigObsoletion.legacy_cop_names
|
75
75
|
|
76
76
|
legacy_cop_names.detect do |legacy_cop_name|
|
77
77
|
legacy_cop_name.split('/')[1] == cop_name
|
@@ -103,7 +103,7 @@ module RuboCop
|
|
103
103
|
# hashes wrapped in a set of curly braces like {foo: 1}.
|
104
104
|
# That is, not a kwargs hash. For method calls, this ensures
|
105
105
|
# the method call is made with parens.
|
106
|
-
starts_with_bracket = node.loc.begin
|
106
|
+
starts_with_bracket = !node.hash_type? || node.loc.begin
|
107
107
|
|
108
108
|
# If the call has a second argument, we can insert a line
|
109
109
|
# break before the second argument and the rest of the
|
@@ -7,10 +7,11 @@ module RuboCop
|
|
7
7
|
module ConfigurableNumbering
|
8
8
|
include ConfigurableFormatting
|
9
9
|
|
10
|
+
implicit_param = /\A_\d+\z/
|
10
11
|
FORMATS = {
|
11
|
-
snake_case: /(
|
12
|
-
normalcase: /(
|
13
|
-
non_integer: /
|
12
|
+
snake_case: /(?:\D|_\d+|\A\d+)\z/,
|
13
|
+
normalcase: /(?:\D|[^_\d]\d+|\A\d+)\z|#{implicit_param}/,
|
14
|
+
non_integer: /(\D|\A\d+)\z|#{implicit_param}/
|
14
15
|
}.freeze
|
15
16
|
end
|
16
17
|
end
|
@@ -2,7 +2,15 @@
|
|
2
2
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
|
-
# Common functionality for enforcing a specific superclass
|
5
|
+
# Common functionality for enforcing a specific superclass.
|
6
|
+
#
|
7
|
+
# IMPORTANT: RuboCop core depended on this module when it supported Rails department.
|
8
|
+
# Rails department has been extracted to RuboCop Rails gem.
|
9
|
+
# This module is deprecated and will be removed by RuboCop 2.0.
|
10
|
+
# It will not be updated to `RuboCop::Cop::Base` v1 API to maintain compatibility
|
11
|
+
# with existing RuboCop Rails 2.8 or lower.
|
12
|
+
#
|
13
|
+
# @api private
|
6
14
|
module EnforceSuperclass
|
7
15
|
def self.included(base)
|
8
16
|
base.def_node_matcher :class_definition, <<~PATTERN
|
@@ -4,15 +4,48 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
# This module encapsulates the ability to ignore certain methods when
|
6
6
|
# parsing.
|
7
|
+
# Cops that use `IgnoredMethods` can accept either strings or regexes to match
|
8
|
+
# against.
|
7
9
|
module IgnoredMethods
|
8
|
-
|
10
|
+
# Configuration for IgnoredMethods. It is added to classes that include
|
11
|
+
# the module so that configuration can be set using the `ignored_methods`
|
12
|
+
# class macro.
|
13
|
+
module Config
|
14
|
+
attr_accessor :deprecated_key
|
15
|
+
|
16
|
+
def ignored_methods(**config)
|
17
|
+
self.deprecated_key = config[:deprecated_key]
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.included(base)
|
22
|
+
base.extend(Config)
|
23
|
+
end
|
9
24
|
|
10
25
|
def ignored_method?(name)
|
11
|
-
ignored_methods.
|
26
|
+
ignored_methods.any? do |value|
|
27
|
+
case value
|
28
|
+
when Regexp
|
29
|
+
value.match? String(name)
|
30
|
+
else
|
31
|
+
value == String(name)
|
32
|
+
end
|
33
|
+
end
|
12
34
|
end
|
13
35
|
|
14
36
|
def ignored_methods
|
15
|
-
|
37
|
+
keys = %w[IgnoredMethods]
|
38
|
+
keys << deprecated_key if deprecated_key
|
39
|
+
|
40
|
+
cop_config.slice(*keys).values.reduce(&:concat)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def deprecated_key
|
46
|
+
return unless self.class.respond_to?(:deprecated_key)
|
47
|
+
|
48
|
+
self.class.deprecated_key&.to_s
|
16
49
|
end
|
17
50
|
end
|
18
51
|
end
|
@@ -11,6 +11,12 @@ module RuboCop
|
|
11
11
|
include Metrics::Utils::RepeatedCsendDiscount
|
12
12
|
extend NodePattern::Macros
|
13
13
|
|
14
|
+
# Ensure cops that include `MethodComplexity` have the config
|
15
|
+
# `attr_accessor`s that `ignored_method?` needs.
|
16
|
+
def self.included(base)
|
17
|
+
base.extend(IgnoredMethods::Config)
|
18
|
+
end
|
19
|
+
|
14
20
|
def on_def(node)
|
15
21
|
return if ignored_method?(node.method_name)
|
16
22
|
|
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
# b c { block }. <-- b is indented relative to a
|
32
32
|
# d <-- d is indented relative to a
|
33
33
|
def left_hand_side(lhs)
|
34
|
-
lhs = lhs.parent while lhs.parent&.send_type?
|
34
|
+
lhs = lhs.parent while lhs.parent&.send_type? && lhs.parent.loc.dot
|
35
35
|
lhs
|
36
36
|
end
|
37
37
|
|
@@ -19,7 +19,8 @@ module RuboCop
|
|
19
19
|
def non_eligible_node?(node)
|
20
20
|
node.modifier_form? ||
|
21
21
|
node.nonempty_line_count > 3 ||
|
22
|
-
processed_source.line_with_comment?(node.loc.last_line)
|
22
|
+
processed_source.line_with_comment?(node.loc.last_line) ||
|
23
|
+
(first_line_comment(node) && code_after(node))
|
23
24
|
end
|
24
25
|
|
25
26
|
def non_eligible_body?(body)
|
@@ -41,11 +42,9 @@ module RuboCop
|
|
41
42
|
|
42
43
|
def length_in_modifier_form(node)
|
43
44
|
keyword_element = node.loc.keyword
|
44
|
-
end_element = node.loc.end
|
45
45
|
code_before = keyword_element.source_line[0...keyword_element.column]
|
46
|
-
code_after = end_element.source_line[end_element.last_column..-1]
|
47
46
|
expression = to_modifier_form(node)
|
48
|
-
line_length("#{code_before}#{expression}#{code_after}")
|
47
|
+
line_length("#{code_before}#{expression}#{code_after(node)}")
|
49
48
|
end
|
50
49
|
|
51
50
|
def to_modifier_form(node)
|
@@ -64,6 +63,12 @@ module RuboCop
|
|
64
63
|
comment_source unless comment_disables_cop?(comment_source)
|
65
64
|
end
|
66
65
|
|
66
|
+
def code_after(node)
|
67
|
+
end_element = node.loc.end
|
68
|
+
code = end_element.source_line[end_element.last_column..-1]
|
69
|
+
code unless code.empty?
|
70
|
+
end
|
71
|
+
|
67
72
|
def parenthesize?(node)
|
68
73
|
# Parenthesize corrected expression if changing to modifier-if form
|
69
74
|
# would change the meaning of the parent expression
|
@@ -14,7 +14,10 @@ module RuboCop
|
|
14
14
|
return if part_of_ignored_node?(node)
|
15
15
|
|
16
16
|
if offense?(node)
|
17
|
-
add_offense(node)
|
17
|
+
add_offense(node) do |corrector|
|
18
|
+
opposite_style_detected
|
19
|
+
autocorrect(corrector, node) if respond_to?(:autocorrect, true)
|
20
|
+
end
|
18
21
|
else
|
19
22
|
correct_style_detected
|
20
23
|
end
|
@@ -16,9 +16,7 @@ module RuboCop
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def find_visibility_start(node)
|
19
|
-
node.left_siblings
|
20
|
-
.reverse
|
21
|
-
.find(&method(:visibility_block?))
|
19
|
+
node.left_siblings.reverse.find { |sibling| visibility_block?(sibling) }
|
22
20
|
end
|
23
21
|
|
24
22
|
# Navigate to find the last protected method
|
@@ -3,7 +3,13 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Naming
|
6
|
-
# This cop makes sure that accessor methods are named properly.
|
6
|
+
# This cop makes sure that accessor methods are named properly. Applies
|
7
|
+
# to both instance and class methods.
|
8
|
+
#
|
9
|
+
# NOTE: Offenses are only registered for methods with the expected
|
10
|
+
# arity. Getters (`get_attribute`) must have no arguments to be
|
11
|
+
# registered, and setters (`set_attribute(value)`) must have exactly
|
12
|
+
# one.
|
7
13
|
#
|
8
14
|
# @example
|
9
15
|
# # bad
|
@@ -21,6 +27,14 @@ module RuboCop
|
|
21
27
|
# # good
|
22
28
|
# def attribute
|
23
29
|
# end
|
30
|
+
#
|
31
|
+
# # accepted, incorrect arity for getter
|
32
|
+
# def get_value(attr)
|
33
|
+
# end
|
34
|
+
#
|
35
|
+
# # accepted, incorrect arity for setter
|
36
|
+
# def set_value
|
37
|
+
# end
|
24
38
|
class AccessorMethodName < Base
|
25
39
|
MSG_READER = 'Do not prefix reader method names with `get_`.'
|
26
40
|
MSG_WRITER = 'Do not prefix writer method names with `set_`.'
|
@@ -14,11 +14,13 @@ module RuboCop
|
|
14
14
|
# # good
|
15
15
|
# def +(other); end
|
16
16
|
class BinaryOperatorParameterName < Base
|
17
|
+
extend AutoCorrector
|
18
|
+
|
17
19
|
MSG = 'When defining the `%<opr>s` operator, ' \
|
18
20
|
'name its argument `other`.'
|
19
21
|
|
20
22
|
OP_LIKE_METHODS = %i[eql? equal?].freeze
|
21
|
-
EXCLUDED = %i[+@ -@ [] []= << === `].freeze
|
23
|
+
EXCLUDED = %i[+@ -@ [] []= << === ` =~].freeze
|
22
24
|
|
23
25
|
def_node_matcher :op_method_candidate?, <<~PATTERN
|
24
26
|
(def [#op_method? $_] (args $(arg [!:other !:_other])) _)
|
@@ -26,7 +28,15 @@ module RuboCop
|
|
26
28
|
|
27
29
|
def on_def(node)
|
28
30
|
op_method_candidate?(node) do |name, arg|
|
29
|
-
add_offense(arg, message: format(MSG, opr: name))
|
31
|
+
add_offense(arg, message: format(MSG, opr: name)) do |corrector|
|
32
|
+
corrector.replace(arg, 'other')
|
33
|
+
node.each_descendant(:lvar, :lvasgn) do |lvar|
|
34
|
+
lvar_location = lvar.loc.name
|
35
|
+
next unless lvar_location.source == arg.source
|
36
|
+
|
37
|
+
corrector.replace(lvar_location, 'other')
|
38
|
+
end
|
39
|
+
end
|
30
40
|
end
|
31
41
|
end
|
32
42
|
|
@@ -30,13 +30,19 @@ module RuboCop
|
|
30
30
|
class HeredocDelimiterCase < Base
|
31
31
|
include Heredoc
|
32
32
|
include ConfigurableEnforcedStyle
|
33
|
+
extend AutoCorrector
|
33
34
|
|
34
35
|
MSG = 'Use %<style>s heredoc delimiters.'
|
35
36
|
|
36
37
|
def on_heredoc(node)
|
37
38
|
return if correct_case_delimiters?(node)
|
38
39
|
|
39
|
-
add_offense(node.loc.heredoc_end)
|
40
|
+
add_offense(node.loc.heredoc_end) do |corrector|
|
41
|
+
expr = node.loc.expression
|
42
|
+
|
43
|
+
corrector.replace(expr, correct_delimiters(expr.source))
|
44
|
+
corrector.replace(node.loc.heredoc_end, correct_delimiters(delimiter_string(expr)))
|
45
|
+
end
|
40
46
|
end
|
41
47
|
|
42
48
|
private
|
@@ -46,14 +52,14 @@ module RuboCop
|
|
46
52
|
end
|
47
53
|
|
48
54
|
def correct_case_delimiters?(node)
|
49
|
-
delimiter_string(node) == correct_delimiters(node)
|
55
|
+
delimiter_string(node) == correct_delimiters(delimiter_string(node))
|
50
56
|
end
|
51
57
|
|
52
|
-
def correct_delimiters(
|
58
|
+
def correct_delimiters(source)
|
53
59
|
if style == :uppercase
|
54
|
-
|
60
|
+
source.upcase
|
55
61
|
else
|
56
|
-
|
62
|
+
source.downcase
|
57
63
|
end
|
58
64
|
end
|
59
65
|
end
|
@@ -20,6 +20,11 @@ module RuboCop
|
|
20
20
|
# @something ||= calculate_expensive_thing
|
21
21
|
# end
|
22
22
|
#
|
23
|
+
# def foo
|
24
|
+
# return @something if defined?(@something)
|
25
|
+
# @something = calculate_expensive_thing
|
26
|
+
# end
|
27
|
+
#
|
23
28
|
# # good
|
24
29
|
# def _foo
|
25
30
|
# @foo ||= calculate_expensive_thing
|
@@ -54,6 +59,11 @@ module RuboCop
|
|
54
59
|
# @foo ||= calculate_expensive_thing
|
55
60
|
# end
|
56
61
|
#
|
62
|
+
# def foo
|
63
|
+
# return @foo if defined?(@foo)
|
64
|
+
# @foo = calculate_expensive_thing
|
65
|
+
# end
|
66
|
+
#
|
57
67
|
# # good
|
58
68
|
# def foo
|
59
69
|
# @_foo ||= calculate_expensive_thing
|
@@ -64,6 +74,11 @@ module RuboCop
|
|
64
74
|
# @_foo ||= calculate_expensive_thing
|
65
75
|
# end
|
66
76
|
#
|
77
|
+
# def foo
|
78
|
+
# return @_foo if defined?(@_foo)
|
79
|
+
# @_foo = calculate_expensive_thing
|
80
|
+
# end
|
81
|
+
#
|
67
82
|
# @example EnforcedStyleForLeadingUnderscores :optional
|
68
83
|
# # bad
|
69
84
|
# def foo
|
@@ -84,6 +99,12 @@ module RuboCop
|
|
84
99
|
# def _foo
|
85
100
|
# @_foo ||= calculate_expensive_thing
|
86
101
|
# end
|
102
|
+
#
|
103
|
+
# # good
|
104
|
+
# def foo
|
105
|
+
# return @_foo if defined?(@_foo)
|
106
|
+
# @_foo = calculate_expensive_thing
|
107
|
+
# end
|
87
108
|
class MemoizedInstanceVariableName < Base
|
88
109
|
include ConfigurableEnforcedStyle
|
89
110
|
|
@@ -92,32 +113,60 @@ module RuboCop
|
|
92
113
|
UNDERSCORE_REQUIRED = 'Memoized variable `%<var>s` does not start ' \
|
93
114
|
'with `_`. Use `@%<suggested_var>s` instead.'
|
94
115
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
class_method =
|
101
|
-
"(defs self $_ _ {#{memo_assign} #{memoized_at_end_of_method}})"
|
102
|
-
"{#{instance_method} #{class_method}}"
|
103
|
-
end
|
116
|
+
# rubocop:disable Metrics/AbcSize
|
117
|
+
def on_or_asgn(node)
|
118
|
+
lhs, _value = *node
|
119
|
+
return unless lhs.ivasgn_type?
|
120
|
+
return unless (method_node = node.each_ancestor(:def, :defs).first)
|
104
121
|
|
105
|
-
|
106
|
-
|
122
|
+
body = method_node.body
|
123
|
+
return unless body == node || body.children.last == node
|
107
124
|
|
108
|
-
|
109
|
-
(method_name,
|
110
|
-
return if matches?(method_name, ivar_assign)
|
125
|
+
method_name = method_node.method_name
|
126
|
+
return if matches?(method_name, lhs)
|
111
127
|
|
112
128
|
msg = format(
|
113
|
-
message(
|
114
|
-
var:
|
129
|
+
message(lhs.children.first.to_s),
|
130
|
+
var: lhs.children.first.to_s,
|
115
131
|
suggested_var: suggested_var(method_name),
|
116
132
|
method: method_name
|
117
133
|
)
|
118
|
-
add_offense(
|
134
|
+
add_offense(lhs, message: msg)
|
135
|
+
end
|
136
|
+
# rubocop:enable Metrics/AbcSize
|
137
|
+
|
138
|
+
def_node_matcher :defined_memoized?, <<~PATTERN
|
139
|
+
(begin
|
140
|
+
(if (defined $(ivar %1)) (return $(ivar %1)) nil?)
|
141
|
+
...
|
142
|
+
$(ivasgn %1 _))
|
143
|
+
PATTERN
|
144
|
+
|
145
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
146
|
+
def on_defined?(node)
|
147
|
+
arg = node.arguments.first
|
148
|
+
return unless arg.ivar_type?
|
149
|
+
|
150
|
+
method_node = node.each_ancestor(:def, :defs).first
|
151
|
+
return unless method_node
|
152
|
+
|
153
|
+
var_name = arg.children.first
|
154
|
+
method_name = method_node.method_name
|
155
|
+
defined_memoized?(method_node.body, var_name) do |defined_ivar, return_ivar, ivar_assign|
|
156
|
+
return if matches?(method_name, ivar_assign)
|
157
|
+
|
158
|
+
msg = format(
|
159
|
+
message(var_name.to_s),
|
160
|
+
var: var_name.to_s,
|
161
|
+
suggested_var: suggested_var(method_name),
|
162
|
+
method: method_name
|
163
|
+
)
|
164
|
+
add_offense(defined_ivar, message: msg)
|
165
|
+
add_offense(return_ivar, message: msg)
|
166
|
+
add_offense(ivar_assign.loc.name, message: msg)
|
167
|
+
end
|
119
168
|
end
|
120
|
-
|
169
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
121
170
|
|
122
171
|
private
|
123
172
|
|
@@ -67,7 +67,8 @@ module RuboCop
|
|
67
67
|
private
|
68
68
|
|
69
69
|
def allowed_method_name?(method_name, prefix)
|
70
|
-
!method_name.
|
70
|
+
!(method_name.start_with?(prefix) && # cheap check to avoid allocating Regexp
|
71
|
+
method_name.match?(/^#{prefix}[^0-9]/)) ||
|
71
72
|
method_name == expected_name(method_name, prefix) ||
|
72
73
|
method_name.end_with?('=') ||
|
73
74
|
allowed_method?(method_name)
|