rubocop 1.18.1 → 1.22.3
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 +116 -23
- data/lib/rubocop/cli.rb +18 -0
- data/lib/rubocop/config.rb +5 -0
- data/lib/rubocop/config_loader.rb +5 -3
- data/lib/rubocop/config_loader_resolver.rb +22 -7
- data/lib/rubocop/config_validator.rb +27 -6
- data/lib/rubocop/cop/base.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
- data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
- data/lib/rubocop/cop/correctors/require_library_corrector.rb +23 -0
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +31 -24
- data/lib/rubocop/cop/generator.rb +14 -8
- data/lib/rubocop/cop/internal_affairs/inherit_deprecated_cop_class.rb +34 -0
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +60 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +71 -0
- data/lib/rubocop/cop/internal_affairs.rb +3 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/class_structure.rb +7 -2
- data/lib/rubocop/cop/layout/dot_position.rb +34 -5
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +9 -0
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
- data/lib/rubocop/cop/layout/end_alignment.rb +9 -2
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +22 -18
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -7
- data/lib/rubocop/cop/layout/indentation_style.rb +2 -2
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +2 -2
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +36 -17
- data/lib/rubocop/cop/layout/line_length.rb +9 -7
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -3
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +23 -10
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
- data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
- data/lib/rubocop/cop/layout/space_around_operators.rb +12 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_comment.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_parens.rb +78 -32
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +24 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
- data/lib/rubocop/cop/lint/ambiguous_range.rb +105 -0
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +5 -2
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
- data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
- data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +2 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +8 -5
- data/lib/rubocop/cop/lint/else_layout.rb +10 -6
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
- data/lib/rubocop/cop/lint/loop.rb +4 -3
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +12 -1
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
- data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
- data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
- data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
- data/lib/rubocop/cop/lint/useless_times.rb +5 -4
- data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
- data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +2 -2
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +9 -4
- data/lib/rubocop/cop/mixin/heredoc.rb +5 -0
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
- data/lib/rubocop/cop/mixin/percent_array.rb +18 -7
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
- data/lib/rubocop/cop/mixin/require_library.rb +59 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -2
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +5 -1
- data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
- data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +1 -1
- data/lib/rubocop/cop/naming/inclusive_language.rb +27 -10
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
- data/lib/rubocop/cop/security/io_methods.rb +49 -0
- data/lib/rubocop/cop/security/json_load.rb +8 -7
- data/lib/rubocop/cop/security/open.rb +4 -0
- data/lib/rubocop/cop/security/yaml_load.rb +4 -0
- data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
- data/lib/rubocop/cop/style/and_or.rb +5 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
- data/lib/rubocop/cop/style/array_coercion.rb +21 -3
- data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +50 -2
- data/lib/rubocop/cop/style/case_equality.rb +6 -9
- data/lib/rubocop/cop/style/case_like_if.rb +5 -0
- data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
- data/lib/rubocop/cop/style/collection_compact.rb +7 -5
- data/lib/rubocop/cop/style/collection_methods.rb +8 -6
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
- data/lib/rubocop/cop/style/comment_annotation.rb +55 -25
- data/lib/rubocop/cop/style/commented_keyword.rb +9 -3
- data/lib/rubocop/cop/style/conditional_assignment.rb +19 -5
- data/lib/rubocop/cop/style/date_time.rb +5 -0
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +23 -8
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -7
- data/lib/rubocop/cop/style/double_negation.rb +27 -6
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/encoding.rb +26 -15
- data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
- data/lib/rubocop/cop/style/explicit_block_argument.rb +46 -11
- data/lib/rubocop/cop/style/float_division.rb +10 -2
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +14 -3
- data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
- data/lib/rubocop/cop/style/hash_except.rb +4 -3
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -9
- data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +32 -5
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
- data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
- data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
- data/lib/rubocop/cop/style/lambda_call.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
- data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -1
- data/lib/rubocop/cop/style/missing_else.rb +7 -0
- data/lib/rubocop/cop/style/module_function.rb +8 -9
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +79 -14
- data/lib/rubocop/cop/style/negated_if.rb +1 -1
- data/lib/rubocop/cop/style/negated_unless.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
- data/lib/rubocop/cop/style/not.rb +2 -2
- data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
- data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
- data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
- data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
- data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
- data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +10 -6
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
- data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
- data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
- data/lib/rubocop/cop/style/redundant_self.rb +10 -0
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +83 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +53 -20
- data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
- data/lib/rubocop/cop/style/return_nil.rb +2 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
- data/lib/rubocop/cop/style/select_by_regexp.rb +139 -0
- data/lib/rubocop/cop/style/semicolon.rb +32 -24
- data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
- data/lib/rubocop/cop/style/single_line_block_params.rb +3 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +25 -15
- data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +25 -0
- data/lib/rubocop/cop/style/static_class.rb +5 -5
- data/lib/rubocop/cop/style/string_chars.rb +4 -2
- data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
- data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
- data/lib/rubocop/cop/style/swap_values.rb +4 -2
- data/lib/rubocop/cop/style/symbol_array.rb +3 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +23 -5
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
- data/lib/rubocop/cop/util.rb +22 -6
- data/lib/rubocop/cops_documentation_generator.rb +17 -5
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +44 -15
- data/lib/rubocop/options.rb +127 -113
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/result_cache.rb +3 -3
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/runner.rb +2 -3
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +14 -2
- metadata +21 -5
@@ -88,7 +88,7 @@ module RuboCop
|
|
88
88
|
end
|
89
89
|
|
90
90
|
def check_new_line_offense(node, rhs)
|
91
|
-
return unless node.loc.operator
|
91
|
+
return unless same_line?(node.loc.operator, rhs)
|
92
92
|
|
93
93
|
add_offense(node, message: NEW_LINE_OFFENSE) do |corrector|
|
94
94
|
corrector.insert_after(node.loc.operator, "\n")
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
add_offense_for_expression(node, node.arguments, ARG_MSG)
|
64
64
|
end
|
65
65
|
|
66
|
-
return unless node.body && node.loc.begin
|
66
|
+
return unless node.body && same_line?(node.loc.begin, node.body)
|
67
67
|
|
68
68
|
add_offense_for_expression(node, node.body, MSG)
|
69
69
|
end
|
@@ -89,7 +89,7 @@ module RuboCop
|
|
89
89
|
if node.source.lines.first.end_with?("|\n")
|
90
90
|
PIPE_SIZE
|
91
91
|
else
|
92
|
-
1 + PIPE_SIZE * 2
|
92
|
+
1 + (PIPE_SIZE * 2)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -110,7 +110,7 @@ module RuboCop
|
|
110
110
|
|
111
111
|
expr_before_body ||= node.loc.begin
|
112
112
|
|
113
|
-
return unless expr_before_body
|
113
|
+
return unless same_line?(expr_before_body, node.body)
|
114
114
|
|
115
115
|
autocorrect_body(corrector, node, node.body)
|
116
116
|
end
|
@@ -6,6 +6,9 @@ module RuboCop
|
|
6
6
|
# This cop ensures that each argument in a multi-line method call
|
7
7
|
# starts on a separate line.
|
8
8
|
#
|
9
|
+
# NOTE: this cop does not move the first argument, if you want that to
|
10
|
+
# be on a separate line, see `Layout/FirstMethodArgumentLineBreak`.
|
11
|
+
#
|
9
12
|
# @example
|
10
13
|
#
|
11
14
|
# # bad
|
@@ -75,7 +75,7 @@ module RuboCop
|
|
75
75
|
def right_hand_side(send_node)
|
76
76
|
dot = send_node.loc.dot
|
77
77
|
selector = send_node.loc.selector
|
78
|
-
if send_node.dot? && selector && dot
|
78
|
+
if send_node.dot? && selector && same_line?(dot, selector)
|
79
79
|
dot.join(selector)
|
80
80
|
elsif selector
|
81
81
|
selector
|
@@ -127,6 +127,7 @@ module RuboCop
|
|
127
127
|
.gsub(/" *\\\n\s*'/, %q(" + ')) # Double quote, backslash, and then single quote
|
128
128
|
.gsub(/' *\\\n\s*"/, %q(' + ")) # Single quote, backslash, and then double quote
|
129
129
|
.gsub(/(["']) *\\\n\s*\1/, '') # Double or single quote, backslash, then same quote
|
130
|
+
.gsub(/\n\s*(?=\.\w)/, '') # Extra space within method chaining
|
130
131
|
.gsub(/\s*\\?\n\s*/, ' ') # Any other line break, with or without backslash
|
131
132
|
end
|
132
133
|
|
@@ -29,8 +29,7 @@ module RuboCop
|
|
29
29
|
MSG = '`%<kw_loc>s` at %<kw_loc_line>d, %<kw_loc_column>d is not ' \
|
30
30
|
'aligned with `%<beginning>s` at ' \
|
31
31
|
'%<begin_loc_line>d, %<begin_loc_column>d.'
|
32
|
-
ANCESTOR_TYPES = %i[kwbegin def defs class module].freeze
|
33
|
-
RUBY_2_5_ANCESTOR_TYPES = (ANCESTOR_TYPES + %i[block]).freeze
|
32
|
+
ANCESTOR_TYPES = %i[kwbegin def defs class module block].freeze
|
34
33
|
ANCESTOR_TYPES_WITH_ACCESS_MODIFIERS = %i[def defs].freeze
|
35
34
|
ALTERNATIVE_ACCESS_MODIFIERS = %i[public_class_method private_class_method].freeze
|
36
35
|
|
@@ -62,7 +61,7 @@ module RuboCop
|
|
62
61
|
alignment_loc = alignment_location(alignment_node)
|
63
62
|
kw_loc = node.loc.keyword
|
64
63
|
|
65
|
-
return if alignment_loc.column == kw_loc.column || alignment_loc
|
64
|
+
return if alignment_loc.column == kw_loc.column || same_line?(alignment_loc, kw_loc)
|
66
65
|
|
67
66
|
add_offense(
|
68
67
|
kw_loc, message: format_message(alignment_node, alignment_loc, kw_loc)
|
@@ -118,6 +117,8 @@ module RuboCop
|
|
118
117
|
ancestor_node = ancestor_node(node)
|
119
118
|
|
120
119
|
return ancestor_node if ancestor_node.nil? || ancestor_node.kwbegin_type?
|
120
|
+
return if ancestor_node.respond_to?(:send_node) &&
|
121
|
+
aligned_with_line_break_method?(ancestor_node, node)
|
121
122
|
|
122
123
|
assignment_node = assignment_node(ancestor_node)
|
123
124
|
return assignment_node if same_line?(ancestor_node, assignment_node)
|
@@ -129,14 +130,26 @@ module RuboCop
|
|
129
130
|
end
|
130
131
|
|
131
132
|
def ancestor_node(node)
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
133
|
+
node.each_ancestor(*ANCESTOR_TYPES).first
|
134
|
+
end
|
135
|
+
|
136
|
+
def aligned_with_line_break_method?(ancestor_node, node)
|
137
|
+
send_node_loc = ancestor_node.send_node.loc
|
138
|
+
do_keyword_line = ancestor_node.loc.begin.line
|
139
|
+
rescue_keyword_column = node.loc.keyword.column
|
140
|
+
selector = send_node_loc.respond_to?(:selector) ? send_node_loc.selector : send_node_loc
|
141
|
+
|
142
|
+
if aligned_with_leading_dot?(do_keyword_line, send_node_loc, rescue_keyword_column)
|
143
|
+
return true
|
144
|
+
end
|
145
|
+
|
146
|
+
do_keyword_line == selector.line && rescue_keyword_column == selector.column
|
147
|
+
end
|
148
|
+
|
149
|
+
def aligned_with_leading_dot?(do_keyword_line, send_node_loc, rescue_keyword_column)
|
150
|
+
return false unless send_node_loc.respond_to?(:dot) && (dot = send_node_loc.dot)
|
138
151
|
|
139
|
-
|
152
|
+
do_keyword_line == dot.line && rescue_keyword_column == dot.column
|
140
153
|
end
|
141
154
|
|
142
155
|
def assignment_node(node)
|
@@ -37,15 +37,26 @@ module RuboCop
|
|
37
37
|
return unless receiver&.block_type?
|
38
38
|
|
39
39
|
receiver_location = receiver.loc
|
40
|
-
|
41
|
-
return if receiver_location.begin.line <
|
40
|
+
closing_block_delimiter_line_num = receiver_location.end.line
|
41
|
+
return if receiver_location.begin.line < closing_block_delimiter_line_num
|
42
42
|
|
43
43
|
node_location = node.loc
|
44
44
|
dot_range = node_location.dot
|
45
45
|
return unless dot_range
|
46
|
-
return
|
46
|
+
return unless call_method_after_block?(node, dot_range, closing_block_delimiter_line_num)
|
47
47
|
|
48
|
-
range_between(dot_range.begin_pos,
|
48
|
+
range_between(dot_range.begin_pos, selector_range(node).end_pos)
|
49
|
+
end
|
50
|
+
|
51
|
+
def call_method_after_block?(node, dot_range, closing_block_delimiter_line_num)
|
52
|
+
return false if dot_range.line > closing_block_delimiter_line_num
|
53
|
+
|
54
|
+
dot_range.column < selector_range(node).column
|
55
|
+
end
|
56
|
+
|
57
|
+
def selector_range(node)
|
58
|
+
# l.(1) has no selector, so we use the opening parenthesis instead
|
59
|
+
node.loc.selector || node.loc.begin
|
49
60
|
end
|
50
61
|
end
|
51
62
|
end
|
@@ -47,7 +47,8 @@ module RuboCop
|
|
47
47
|
space_on_both_sides = space_on_both_sides?(arg, equals)
|
48
48
|
no_surrounding_space = no_surrounding_space?(arg, equals)
|
49
49
|
|
50
|
-
if style == :space && space_on_both_sides ||
|
50
|
+
if (style == :space && space_on_both_sides) ||
|
51
|
+
(style == :no_space && no_surrounding_space)
|
51
52
|
correct_style_detected
|
52
53
|
else
|
53
54
|
incorrect_style_detected(arg, value)
|
@@ -228,8 +228,8 @@ module RuboCop
|
|
228
228
|
def accepted_opening_delimiter?(range, char)
|
229
229
|
return true unless char
|
230
230
|
|
231
|
-
accept_left_square_bracket?(range) && char == '[' ||
|
232
|
-
accept_left_parenthesis?(range) && char == '('
|
231
|
+
(accept_left_square_bracket?(range) && char == '[') ||
|
232
|
+
(accept_left_parenthesis?(range) && char == '(')
|
233
233
|
end
|
234
234
|
|
235
235
|
def accept_left_parenthesis?(range)
|
@@ -63,6 +63,10 @@ module RuboCop
|
|
63
63
|
[Style::SelfAssignment]
|
64
64
|
end
|
65
65
|
|
66
|
+
def on_sclass(node)
|
67
|
+
check_operator(:sclass, node.loc.operator, node.source_range)
|
68
|
+
end
|
69
|
+
|
66
70
|
def on_pair(node)
|
67
71
|
return unless node.hash_rocket?
|
68
72
|
|
@@ -104,6 +108,14 @@ module RuboCop
|
|
104
108
|
check_operator(:assignment, node.loc.operator, rhs.source_range)
|
105
109
|
end
|
106
110
|
|
111
|
+
def on_casgn(node)
|
112
|
+
_, _, right, = *node
|
113
|
+
|
114
|
+
return unless right
|
115
|
+
|
116
|
+
check_operator(:assignment, node.loc.operator, right.source_range)
|
117
|
+
end
|
118
|
+
|
107
119
|
def on_binary(node)
|
108
120
|
_, rhs, = *node
|
109
121
|
|
@@ -130,7 +142,6 @@ module RuboCop
|
|
130
142
|
alias on_and on_binary
|
131
143
|
alias on_lvasgn on_assignment
|
132
144
|
alias on_masgn on_assignment
|
133
|
-
alias on_casgn on_special_asgn
|
134
145
|
alias on_ivasgn on_assignment
|
135
146
|
alias on_cvasgn on_assignment
|
136
147
|
alias on_gvasgn on_assignment
|
@@ -18,9 +18,9 @@ module RuboCop
|
|
18
18
|
MSG = 'Put a space before an end-of-line comment.'
|
19
19
|
|
20
20
|
def on_new_investigation
|
21
|
-
processed_source.
|
21
|
+
processed_source.sorted_tokens.each_cons(2) do |token1, token2|
|
22
22
|
next unless token2.comment?
|
23
|
-
next unless token1
|
23
|
+
next unless same_line?(token1, token2)
|
24
24
|
next unless token1.pos.end == token2.pos.begin
|
25
25
|
|
26
26
|
range = token2.pos
|
@@ -33,6 +33,27 @@ module RuboCop
|
|
33
33
|
# g = ( a + 3 )
|
34
34
|
# y()
|
35
35
|
#
|
36
|
+
# @example EnforcedStyle: compact
|
37
|
+
# # The `compact` style enforces that parentheses have a space at the
|
38
|
+
# # beginning with the exception that successive parentheses are allowed.
|
39
|
+
# # Note: Empty parentheses should not have spaces.
|
40
|
+
#
|
41
|
+
# # bad
|
42
|
+
# f(3)
|
43
|
+
# g = (a + 3)
|
44
|
+
# y( )
|
45
|
+
# g( f( x ) )
|
46
|
+
# g( f( x( 3 ) ), 5 )
|
47
|
+
# g( ( ( 3 + 5 ) * f) ** x, 5 )
|
48
|
+
#
|
49
|
+
# # good
|
50
|
+
# f( 3 )
|
51
|
+
# g = ( a + 3 )
|
52
|
+
# y()
|
53
|
+
# g( f( x ))
|
54
|
+
# g( f( x( 3 )), 5 )
|
55
|
+
# g((( 3 + 5 ) * f ) ** x, 5 )
|
56
|
+
#
|
36
57
|
class SpaceInsideParens < Base
|
37
58
|
include SurroundingSpace
|
38
59
|
include RangeHelp
|
@@ -43,37 +64,39 @@ module RuboCop
|
|
43
64
|
MSG_SPACE = 'No space inside parentheses detected.'
|
44
65
|
|
45
66
|
def on_new_investigation
|
46
|
-
|
67
|
+
tokens = processed_source.sorted_tokens
|
47
68
|
|
48
|
-
|
49
|
-
|
69
|
+
case style
|
70
|
+
when :space
|
71
|
+
process_with_space_style(tokens)
|
72
|
+
when :compact
|
73
|
+
process_with_compact_style(tokens)
|
50
74
|
else
|
51
|
-
|
52
|
-
add_offense(range) do |corrector|
|
53
|
-
corrector.remove(range)
|
54
|
-
end
|
55
|
-
end
|
75
|
+
correct_extraneous_space(tokens)
|
56
76
|
end
|
57
77
|
end
|
58
78
|
|
59
79
|
private
|
60
80
|
|
61
|
-
def process_with_space_style(
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
81
|
+
def process_with_space_style(tokens)
|
82
|
+
tokens.each_cons(2) do |token1, token2|
|
83
|
+
correct_extraneous_space_in_empty_parens(token1, token2)
|
84
|
+
correct_missing_space(token1, token2)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def process_with_compact_style(tokens)
|
89
|
+
tokens.each_cons(2) do |token1, token2|
|
90
|
+
correct_extraneous_space_in_empty_parens(token1, token2)
|
91
|
+
if !left_parens?(token1, token2) && !right_parens?(token1, token2)
|
92
|
+
correct_missing_space(token1, token2)
|
93
|
+
else
|
94
|
+
correct_extaneus_space_between_consecutive_parens(token1, token2)
|
72
95
|
end
|
73
96
|
end
|
74
97
|
end
|
75
98
|
|
76
|
-
def
|
99
|
+
def correct_extraneous_space(tokens)
|
77
100
|
tokens.each_cons(2) do |token1, token2|
|
78
101
|
next unless parens?(token1, token2)
|
79
102
|
|
@@ -82,36 +105,59 @@ module RuboCop
|
|
82
105
|
next if token2.comment?
|
83
106
|
next unless same_line?(token1, token2) && token1.space_after?
|
84
107
|
|
85
|
-
|
108
|
+
range = range_between(token1.end_pos, token2.begin_pos)
|
109
|
+
add_offense(range) do |corrector|
|
110
|
+
corrector.remove(range)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def correct_extaneus_space_between_consecutive_parens(token1, token2)
|
116
|
+
return if range_between(token1.end_pos, token2.begin_pos).source != ' '
|
117
|
+
|
118
|
+
range = range_between(token1.end_pos, token2.begin_pos)
|
119
|
+
add_offense(range) do |corrector|
|
120
|
+
corrector.remove(range)
|
86
121
|
end
|
87
122
|
end
|
88
123
|
|
89
|
-
def
|
124
|
+
def correct_extraneous_space_in_empty_parens(token1, token2)
|
90
125
|
return unless token1.left_parens? && token2.right_parens?
|
91
126
|
|
92
127
|
return if range_between(token1.begin_pos, token2.end_pos).source == '()'
|
93
128
|
|
94
|
-
|
129
|
+
range = range_between(token1.end_pos, token2.begin_pos)
|
130
|
+
add_offense(range) do |corrector|
|
131
|
+
corrector.remove(range)
|
132
|
+
end
|
95
133
|
end
|
96
134
|
|
97
|
-
def
|
135
|
+
def correct_missing_space(token1, token2)
|
98
136
|
return if can_be_ignored?(token1, token2)
|
99
137
|
|
100
|
-
if token1.left_parens?
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
138
|
+
range = if token1.left_parens?
|
139
|
+
range_between(token2.begin_pos, token2.begin_pos + 1)
|
140
|
+
elsif token2.right_parens?
|
141
|
+
range_between(token2.begin_pos, token2.end_pos)
|
142
|
+
end
|
106
143
|
|
107
|
-
|
108
|
-
|
144
|
+
add_offense(range, message: MSG_SPACE) do |corrector|
|
145
|
+
corrector.insert_before(range, ' ')
|
146
|
+
end
|
109
147
|
end
|
110
148
|
|
111
149
|
def parens?(token1, token2)
|
112
150
|
token1.left_parens? || token2.right_parens?
|
113
151
|
end
|
114
152
|
|
153
|
+
def left_parens?(token1, token2)
|
154
|
+
token1.left_parens? && token2.left_parens?
|
155
|
+
end
|
156
|
+
|
157
|
+
def right_parens?(token1, token2)
|
158
|
+
token1.right_parens? && token2.right_parens?
|
159
|
+
end
|
160
|
+
|
115
161
|
def can_be_ignored?(token1, token2)
|
116
162
|
return true unless parens?(token1, token2)
|
117
163
|
|
@@ -107,7 +107,7 @@ module RuboCop
|
|
107
107
|
current_token = tokens.reverse.find(&:left_ref_bracket?)
|
108
108
|
previous_token = previous_token(current_token)
|
109
109
|
|
110
|
-
if node.method?(:[]=) || previous_token && !previous_token.right_bracket?
|
110
|
+
if node.method?(:[]=) || (previous_token && !previous_token.right_bracket?)
|
111
111
|
tokens.find(&:left_ref_bracket?)
|
112
112
|
else
|
113
113
|
current_token
|
@@ -41,6 +41,7 @@ module RuboCop
|
|
41
41
|
#
|
42
42
|
class TrailingWhitespace < Base
|
43
43
|
include RangeHelp
|
44
|
+
include Heredoc
|
44
45
|
extend AutoCorrector
|
45
46
|
|
46
47
|
MSG = 'Trailing whitespace detected.'
|
@@ -54,6 +55,8 @@ module RuboCop
|
|
54
55
|
end
|
55
56
|
end
|
56
57
|
|
58
|
+
def on_heredoc(_node); end
|
59
|
+
|
57
60
|
private
|
58
61
|
|
59
62
|
def process_line(line, lineno)
|
@@ -63,13 +66,33 @@ module RuboCop
|
|
63
66
|
range = offense_range(lineno, line)
|
64
67
|
add_offense(range) do |corrector|
|
65
68
|
if heredoc
|
66
|
-
corrector
|
69
|
+
process_line_in_heredoc(corrector, range, heredoc)
|
67
70
|
else
|
68
71
|
corrector.remove(range)
|
69
72
|
end
|
70
73
|
end
|
71
74
|
end
|
72
75
|
|
76
|
+
def process_line_in_heredoc(corrector, range, heredoc)
|
77
|
+
indent_level = indent_level(find_heredoc(range.line).loc.heredoc_body.source)
|
78
|
+
whitespace_only = whitespace_only?(range)
|
79
|
+
if whitespace_only && whitespace_is_indentation?(range, indent_level)
|
80
|
+
corrector.remove(range)
|
81
|
+
elsif !static?(heredoc)
|
82
|
+
range = range_between(range.begin_pos + indent_level, range.end_pos) if whitespace_only
|
83
|
+
corrector.wrap(range, "\#{'", "'}")
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def whitespace_is_indentation?(range, level)
|
88
|
+
range.source[/ +/].length <= level
|
89
|
+
end
|
90
|
+
|
91
|
+
def whitespace_only?(range)
|
92
|
+
source = range_with_surrounding_space(range: range).source
|
93
|
+
source.start_with?("\n") && source.end_with?("\n")
|
94
|
+
end
|
95
|
+
|
73
96
|
def static?(heredoc)
|
74
97
|
heredoc.loc.expression.source.end_with? "'"
|
75
98
|
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Lint
|
6
|
+
# This cop looks for expressions containing multiple binary operators
|
7
|
+
# where precedence is ambiguous due to lack of parentheses. For example,
|
8
|
+
# in `1 + 2 * 3`, the multiplication will happen before the addition, but
|
9
|
+
# lexically it appears that the addition will happen first.
|
10
|
+
#
|
11
|
+
# The cop does not consider unary operators (ie. `!a` or `-b`) or comparison
|
12
|
+
# operators (ie. `a =~ b`) because those are not ambiguous.
|
13
|
+
#
|
14
|
+
# NOTE: Ranges are handled by `Lint/AmbiguousRange`.
|
15
|
+
#
|
16
|
+
# @example
|
17
|
+
# # bad
|
18
|
+
# a + b * c
|
19
|
+
# a || b && c
|
20
|
+
# a ** b + c
|
21
|
+
#
|
22
|
+
# # good (different precedence)
|
23
|
+
# a + (b * c)
|
24
|
+
# a || (b && c)
|
25
|
+
# (a ** b) + c
|
26
|
+
#
|
27
|
+
# # good (same precedence)
|
28
|
+
# a + b + c
|
29
|
+
# a * b / c % d
|
30
|
+
class AmbiguousOperatorPrecedence < Base
|
31
|
+
extend AutoCorrector
|
32
|
+
|
33
|
+
# See https://ruby-doc.org/core-3.0.2/doc/syntax/precedence_rdoc.html
|
34
|
+
PRECEDENCE = [
|
35
|
+
%i[**],
|
36
|
+
%i[* / %],
|
37
|
+
%i[+ -],
|
38
|
+
%i[<< >>],
|
39
|
+
%i[&],
|
40
|
+
%i[| ^],
|
41
|
+
%i[&&],
|
42
|
+
%i[||]
|
43
|
+
].freeze
|
44
|
+
RESTRICT_ON_SEND = PRECEDENCE.flatten.freeze
|
45
|
+
MSG = 'Wrap expressions with varying precedence with parentheses to avoid ambiguity.'
|
46
|
+
|
47
|
+
def on_new_investigation
|
48
|
+
# Cache the precedence of each node being investigated
|
49
|
+
# so that we only need to calculate it once
|
50
|
+
@node_precedences = {}
|
51
|
+
super
|
52
|
+
end
|
53
|
+
|
54
|
+
def on_and(node)
|
55
|
+
return unless (parent = node.parent)
|
56
|
+
|
57
|
+
return if parent.begin_type? # if the `and` is in a `begin`, it's parenthesized already
|
58
|
+
return unless parent.or_type?
|
59
|
+
|
60
|
+
add_offense(node) do |corrector|
|
61
|
+
autocorrect(corrector, node)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def on_send(node)
|
66
|
+
return if node.parenthesized?
|
67
|
+
|
68
|
+
return unless (parent = node.parent)
|
69
|
+
return unless operator?(parent)
|
70
|
+
return unless greater_precedence?(node, parent)
|
71
|
+
|
72
|
+
add_offense(node) do |corrector|
|
73
|
+
autocorrect(corrector, node)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def precedence(node)
|
80
|
+
@node_precedences.fetch(node) do
|
81
|
+
PRECEDENCE.index { |operators| operators.include?(operator_name(node)) }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def operator?(node)
|
86
|
+
(node.send_type? && RESTRICT_ON_SEND.include?(node.method_name)) || node.operator_keyword?
|
87
|
+
end
|
88
|
+
|
89
|
+
def greater_precedence?(node1, node2)
|
90
|
+
node1_precedence = precedence(node1)
|
91
|
+
node2_precedence = precedence(node2)
|
92
|
+
return false unless node1_precedence && node2_precedence
|
93
|
+
|
94
|
+
node2_precedence > node1_precedence
|
95
|
+
end
|
96
|
+
|
97
|
+
def operator_name(node)
|
98
|
+
if node.send_type?
|
99
|
+
node.method_name
|
100
|
+
else
|
101
|
+
node.operator.to_sym
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def autocorrect(corrector, node)
|
106
|
+
corrector.wrap(node, '(', ')')
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|