rubocop 0.35.1 → 0.36.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +164 -0
- data/LICENSE.txt +1 -1
- data/README.md +72 -21
- data/bin/rubocop +1 -0
- data/config/default.yml +167 -18
- data/config/disabled.yml +19 -6
- data/config/enabled.yml +159 -14
- data/lib/rubocop.rb +67 -26
- data/lib/rubocop/ast_node.rb +488 -14
- data/lib/rubocop/ast_node/builder.rb +24 -0
- data/lib/rubocop/ast_node/sexp.rb +13 -0
- data/lib/rubocop/cached_data.rb +58 -0
- data/lib/rubocop/cli.rb +47 -10
- data/lib/rubocop/comment_config.rb +9 -2
- data/lib/rubocop/config.rb +99 -31
- data/lib/rubocop/config_loader.rb +23 -14
- data/lib/rubocop/config_store.rb +1 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +2 -1
- data/lib/rubocop/cop/commissioner.rb +3 -5
- data/lib/rubocop/cop/cop.rb +23 -17
- data/lib/rubocop/cop/corrector.rb +25 -0
- data/lib/rubocop/cop/force.rb +1 -0
- data/lib/rubocop/cop/ignored_node.rb +3 -2
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +2 -1
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +2 -1
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +4 -3
- data/lib/rubocop/cop/lint/block_alignment.rb +29 -91
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -1
- data/lib/rubocop/cop/lint/condition_position.rb +2 -1
- data/lib/rubocop/cop/lint/debugger.rb +29 -12
- data/lib/rubocop/cop/lint/def_end_alignment.rb +16 -18
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +6 -6
- data/lib/rubocop/cop/lint/duplicate_methods.rb +98 -74
- data/lib/rubocop/cop/lint/duplicated_key.rb +3 -2
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +3 -2
- data/lib/rubocop/cop/lint/else_layout.rb +2 -1
- data/lib/rubocop/cop/lint/empty_ensure.rb +2 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +2 -1
- data/lib/rubocop/cop/lint/end_alignment.rb +77 -39
- data/lib/rubocop/cop/lint/end_in_method.rb +2 -1
- data/lib/rubocop/cop/lint/ensure_return.rb +2 -1
- data/lib/rubocop/cop/lint/eval.rb +2 -1
- data/lib/rubocop/cop/lint/float_out_of_range.rb +31 -0
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -30
- data/lib/rubocop/cop/lint/handle_exceptions.rb +2 -1
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +85 -0
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +120 -0
- data/lib/rubocop/cop/lint/invalid_character_literal.rb +3 -1
- data/lib/rubocop/cop/lint/literal_in_condition.rb +6 -9
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +6 -9
- data/lib/rubocop/cop/lint/loop.rb +2 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +19 -3
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +38 -0
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +5 -8
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +8 -6
- data/lib/rubocop/cop/lint/rand_one.rb +36 -0
- data/lib/rubocop/cop/lint/require_parentheses.rb +6 -5
- data/lib/rubocop/cop/lint/rescue_exception.rb +3 -2
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +2 -1
- data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +6 -4
- data/lib/rubocop/cop/lint/syntax.rb +9 -5
- data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +3 -2
- data/lib/rubocop/cop/lint/unneeded_disable.rb +121 -18
- data/lib/rubocop/cop/lint/unreachable_code.rb +5 -4
- data/lib/rubocop/cop/lint/unused_block_argument.rb +9 -7
- data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +56 -29
- data/lib/rubocop/cop/lint/useless_assignment.rb +4 -16
- data/lib/rubocop/cop/lint/useless_comparison.rb +3 -2
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +2 -1
- data/lib/rubocop/cop/lint/useless_setter_call.rb +14 -20
- data/lib/rubocop/cop/lint/void.rb +10 -11
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +2 -1
- data/lib/rubocop/cop/metrics/class_length.rb +1 -0
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +4 -2
- data/lib/rubocop/cop/metrics/line_length.rb +35 -13
- data/lib/rubocop/cop/metrics/method_length.rb +2 -1
- data/lib/rubocop/cop/metrics/module_length.rb +1 -0
- data/lib/rubocop/cop/metrics/parameter_lists.rb +2 -1
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +4 -2
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +3 -10
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -0
- data/lib/rubocop/cop/mixin/array_hash_indentation.rb +80 -0
- data/lib/rubocop/cop/mixin/array_syntax.rb +2 -1
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +14 -20
- data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +5 -4
- data/lib/rubocop/cop/mixin/check_assignment.rb +20 -15
- data/lib/rubocop/cop/mixin/classish_length.rb +1 -0
- data/lib/rubocop/cop/mixin/code_length.rb +1 -0
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +17 -15
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -0
- data/lib/rubocop/cop/mixin/configurable_naming.rb +4 -0
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +9 -4
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +24 -16
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +3 -2
- data/lib/rubocop/cop/mixin/hash_node.rb +15 -0
- data/lib/rubocop/cop/mixin/if_node.rb +1 -0
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -0
- data/lib/rubocop/cop/mixin/method_preference.rb +1 -0
- data/lib/rubocop/cop/mixin/min_body_length.rb +1 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +177 -0
- data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -0
- data/lib/rubocop/cop/mixin/on_method_def.rb +6 -5
- data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -0
- data/lib/rubocop/cop/mixin/parentheses.rb +22 -0
- data/lib/rubocop/cop/mixin/parser_diagnostic.rb +1 -0
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -0
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +79 -0
- data/lib/rubocop/cop/mixin/safe_assignment.rb +1 -0
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +2 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -1
- data/lib/rubocop/cop/mixin/space_inside.rb +2 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +6 -5
- data/lib/rubocop/cop/mixin/string_help.rb +2 -9
- data/lib/rubocop/cop/mixin/string_literals_help.rb +13 -7
- data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -2
- data/lib/rubocop/cop/mixin/trailing_comma.rb +134 -0
- data/lib/rubocop/cop/mixin/unused_argument.rb +1 -0
- data/lib/rubocop/cop/offense.rb +19 -14
- data/lib/rubocop/cop/performance/case_when_splat.rb +8 -8
- data/lib/rubocop/cop/performance/casecmp.rb +54 -0
- data/lib/rubocop/cop/performance/count.rb +10 -9
- data/lib/rubocop/cop/performance/detect.rb +6 -5
- data/lib/rubocop/cop/performance/double_start_end_with.rb +65 -0
- data/lib/rubocop/cop/performance/end_with.rb +55 -0
- data/lib/rubocop/cop/performance/fixed_size.rb +1 -0
- data/lib/rubocop/cop/performance/flat_map.rb +9 -8
- data/lib/rubocop/cop/performance/hash_each.rb +86 -0
- data/lib/rubocop/cop/performance/lstrip_rstrip.rb +44 -0
- data/lib/rubocop/cop/performance/range_include.rb +40 -0
- data/lib/rubocop/cop/performance/redundant_block_call.rb +57 -0
- data/lib/rubocop/cop/performance/redundant_match.rb +51 -0
- data/lib/rubocop/cop/performance/redundant_merge.rb +85 -0
- data/lib/rubocop/cop/performance/redundant_sort_by.rb +45 -0
- data/lib/rubocop/cop/performance/reverse_each.rb +3 -2
- data/lib/rubocop/cop/performance/sample.rb +6 -5
- data/lib/rubocop/cop/performance/size.rb +2 -1
- data/lib/rubocop/cop/performance/start_with.rb +58 -0
- data/lib/rubocop/cop/performance/string_replacement.rb +18 -23
- data/lib/rubocop/cop/performance/times_map.rb +49 -0
- data/lib/rubocop/cop/rails/action_filter.rb +4 -3
- data/lib/rubocop/cop/rails/date.rb +5 -4
- data/lib/rubocop/cop/rails/delegate.rb +3 -2
- data/lib/rubocop/cop/rails/find_by.rb +20 -14
- data/lib/rubocop/cop/rails/find_each.rb +23 -2
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +3 -2
- data/lib/rubocop/cop/rails/output.rb +4 -2
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +3 -2
- data/lib/rubocop/cop/rails/read_write_attribute.rb +5 -7
- data/lib/rubocop/cop/rails/scope_args.rb +3 -2
- data/lib/rubocop/cop/rails/time_zone.rb +14 -10
- data/lib/rubocop/cop/rails/validation.rb +4 -3
- data/lib/rubocop/cop/severity.rb +8 -7
- data/lib/rubocop/cop/style/access_modifier_indentation.rb +5 -4
- data/lib/rubocop/cop/style/accessor_method_name.rb +1 -0
- data/lib/rubocop/cop/style/alias.rb +84 -24
- data/lib/rubocop/cop/style/align_array.rb +2 -1
- data/lib/rubocop/cop/style/align_hash.rb +13 -14
- data/lib/rubocop/cop/style/align_parameters.rb +3 -2
- data/lib/rubocop/cop/style/and_or.rb +9 -7
- data/lib/rubocop/cop/style/array_join.rb +5 -5
- data/lib/rubocop/cop/style/ascii_comments.rb +2 -1
- data/lib/rubocop/cop/style/ascii_identifiers.rb +2 -1
- data/lib/rubocop/cop/style/attr.rb +30 -5
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +3 -3
- data/lib/rubocop/cop/style/bare_percent_literals.rb +2 -1
- data/lib/rubocop/cop/style/begin_block.rb +2 -1
- data/lib/rubocop/cop/style/block_comments.rb +2 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +10 -9
- data/lib/rubocop/cop/style/block_end_newline.rb +3 -2
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +9 -8
- data/lib/rubocop/cop/style/case_equality.rb +2 -1
- data/lib/rubocop/cop/style/case_indentation.rb +2 -1
- data/lib/rubocop/cop/style/character_literal.rb +11 -7
- data/lib/rubocop/cop/style/class_and_module_camel_case.rb +2 -1
- data/lib/rubocop/cop/style/class_and_module_children.rb +3 -2
- data/lib/rubocop/cop/style/class_check.rb +2 -1
- data/lib/rubocop/cop/style/class_methods.rb +2 -1
- data/lib/rubocop/cop/style/class_vars.rb +2 -1
- data/lib/rubocop/cop/style/closing_parenthesis_indentation.rb +3 -2
- data/lib/rubocop/cop/style/collection_methods.rb +2 -1
- data/lib/rubocop/cop/style/colon_method_call.rb +3 -2
- data/lib/rubocop/cop/style/command_literal.rb +8 -7
- data/lib/rubocop/cop/style/comment_annotation.rb +3 -2
- data/lib/rubocop/cop/style/comment_indentation.rb +4 -6
- data/lib/rubocop/cop/style/conditional_assignment.rb +362 -0
- data/lib/rubocop/cop/style/constant_name.rb +2 -1
- data/lib/rubocop/cop/style/copyright.rb +7 -6
- data/lib/rubocop/cop/style/def_with_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/deprecated_hash_methods.rb +3 -2
- data/lib/rubocop/cop/style/documentation.rb +7 -11
- data/lib/rubocop/cop/style/dot_position.rb +3 -2
- data/lib/rubocop/cop/style/double_negation.rb +2 -1
- data/lib/rubocop/cop/style/each_with_object.rb +4 -3
- data/lib/rubocop/cop/style/else_alignment.rb +3 -2
- data/lib/rubocop/cop/style/empty_else.rb +4 -3
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +2 -1
- data/lib/rubocop/cop/style/empty_lines.rb +10 -4
- data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +13 -5
- data/lib/rubocop/cop/style/empty_lines_around_block_body.rb +7 -3
- data/lib/rubocop/cop/style/empty_lines_around_class_body.rb +6 -3
- data/lib/rubocop/cop/style/empty_lines_around_method_body.rb +4 -3
- data/lib/rubocop/cop/style/empty_lines_around_module_body.rb +4 -2
- data/lib/rubocop/cop/style/empty_literal.rb +20 -5
- data/lib/rubocop/cop/style/encoding.rb +8 -11
- data/lib/rubocop/cop/style/end_block.rb +3 -1
- data/lib/rubocop/cop/style/end_of_line.rb +2 -1
- data/lib/rubocop/cop/style/even_odd.rb +4 -3
- data/lib/rubocop/cop/style/extra_spacing.rb +110 -74
- data/lib/rubocop/cop/style/file_name.rb +103 -6
- data/lib/rubocop/cop/style/first_array_element_line_break.rb +3 -2
- data/lib/rubocop/cop/style/first_hash_element_line_break.rb +5 -6
- data/lib/rubocop/cop/style/first_method_argument_line_break.rb +14 -1
- data/lib/rubocop/cop/style/first_method_parameter_line_break.rb +2 -1
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +6 -4
- data/lib/rubocop/cop/style/flip_flop.rb +2 -1
- data/lib/rubocop/cop/style/for.rb +2 -1
- data/lib/rubocop/cop/style/format_string.rb +1 -0
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +89 -0
- data/lib/rubocop/cop/style/global_vars.rb +2 -1
- data/lib/rubocop/cop/style/guard_clause.rb +63 -11
- data/lib/rubocop/cop/style/hash_syntax.rb +10 -10
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +93 -0
- data/lib/rubocop/cop/style/if_inside_else.rb +49 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +6 -5
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -1
- data/lib/rubocop/cop/style/indent_array.rb +89 -38
- data/lib/rubocop/cop/style/indent_assignment.rb +43 -0
- data/lib/rubocop/cop/style/indent_hash.rb +16 -77
- data/lib/rubocop/cop/style/indentation_consistency.rb +2 -1
- data/lib/rubocop/cop/style/indentation_width.rb +11 -11
- data/lib/rubocop/cop/style/infinite_loop.rb +5 -9
- data/lib/rubocop/cop/style/initial_indentation.rb +2 -1
- data/lib/rubocop/cop/style/inline_comment.rb +2 -1
- data/lib/rubocop/cop/style/lambda.rb +14 -11
- data/lib/rubocop/cop/style/lambda_call.rb +4 -4
- data/lib/rubocop/cop/style/leading_comment_space.rb +2 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +3 -1
- data/lib/rubocop/cop/style/method_call_parentheses.rb +9 -1
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -2
- data/lib/rubocop/cop/style/method_def_parentheses.rb +4 -4
- data/lib/rubocop/cop/style/method_name.rb +1 -0
- data/lib/rubocop/cop/style/missing_else.rb +5 -3
- data/lib/rubocop/cop/style/module_function.rb +2 -1
- data/lib/rubocop/cop/style/multiline_array_brace_layout.rb +95 -0
- data/lib/rubocop/cop/style/multiline_assignment_layout.rb +91 -0
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -2
- data/lib/rubocop/cop/style/multiline_block_layout.rb +11 -9
- data/lib/rubocop/cop/style/multiline_if_then.rb +1 -0
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +137 -0
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +25 -135
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +2 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +4 -5
- data/lib/rubocop/cop/style/negated_if.rb +3 -3
- data/lib/rubocop/cop/style/negated_while.rb +3 -3
- data/lib/rubocop/cop/style/nested_modifier.rb +6 -5
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +48 -0
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +2 -1
- data/lib/rubocop/cop/style/next.rb +79 -15
- data/lib/rubocop/cop/style/nil_comparison.rb +5 -5
- data/lib/rubocop/cop/style/non_nil_check.rb +5 -5
- data/lib/rubocop/cop/style/not.rb +5 -9
- data/lib/rubocop/cop/style/numeric_literals.rb +5 -4
- data/lib/rubocop/cop/style/one_line_conditional.rb +3 -2
- data/lib/rubocop/cop/style/op_method.rb +7 -4
- data/lib/rubocop/cop/style/option_hash.rb +13 -7
- data/lib/rubocop/cop/style/optional_arguments.rb +3 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +40 -16
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +3 -16
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +3 -2
- data/lib/rubocop/cop/style/percent_q_literals.rb +3 -6
- data/lib/rubocop/cop/style/perl_backrefs.rb +4 -3
- data/lib/rubocop/cop/style/predicate_name.rb +1 -0
- data/lib/rubocop/cop/style/proc.rb +3 -2
- data/lib/rubocop/cop/style/raise_args.rb +2 -1
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +5 -5
- data/lib/rubocop/cop/style/redundant_freeze.rb +5 -4
- data/lib/rubocop/cop/style/redundant_parentheses.rb +80 -0
- data/lib/rubocop/cop/style/redundant_return.rb +5 -4
- data/lib/rubocop/cop/style/redundant_self.rb +7 -8
- data/lib/rubocop/cop/style/regexp_literal.rb +9 -8
- data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +3 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +11 -9
- data/lib/rubocop/cop/style/self_assignment.rb +4 -5
- data/lib/rubocop/cop/style/semicolon.rb +3 -2
- data/lib/rubocop/cop/style/send.rb +3 -1
- data/lib/rubocop/cop/style/signal_exception.rb +5 -3
- data/lib/rubocop/cop/style/single_line_block_params.rb +2 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +7 -7
- data/lib/rubocop/cop/style/space_after_colon.rb +2 -1
- data/lib/rubocop/cop/style/space_after_comma.rb +1 -0
- data/lib/rubocop/cop/style/space_after_control_keyword.rb +5 -5
- data/lib/rubocop/cop/style/space_after_method_name.rb +3 -2
- data/lib/rubocop/cop/style/space_after_not.rb +4 -3
- data/lib/rubocop/cop/style/space_after_semicolon.rb +1 -0
- data/lib/rubocop/cop/style/space_around_block_parameters.rb +8 -7
- data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +1 -0
- data/lib/rubocop/cop/style/space_around_operators.rb +72 -32
- data/lib/rubocop/cop/style/space_before_block_braces.rb +2 -1
- data/lib/rubocop/cop/style/space_before_comma.rb +1 -0
- data/lib/rubocop/cop/style/space_before_comment.rb +2 -1
- data/lib/rubocop/cop/style/{single_space_before_first_arg.rb → space_before_first_arg.rb} +13 -4
- data/lib/rubocop/cop/style/space_before_modifier_keyword.rb +4 -3
- data/lib/rubocop/cop/style/space_before_semicolon.rb +1 -0
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +3 -2
- data/lib/rubocop/cop/style/space_inside_brackets.rb +1 -0
- data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +4 -1
- data/lib/rubocop/cop/style/space_inside_parens.rb +1 -0
- data/lib/rubocop/cop/style/space_inside_range_literal.rb +5 -4
- data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +8 -17
- data/lib/rubocop/cop/style/special_global_vars.rb +97 -52
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +16 -9
- data/lib/rubocop/cop/style/string_literals.rb +41 -1
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +2 -1
- data/lib/rubocop/cop/style/string_methods.rb +2 -1
- data/lib/rubocop/cop/style/struct_inheritance.rb +3 -2
- data/lib/rubocop/cop/style/symbol_array.rb +74 -7
- data/lib/rubocop/cop/style/symbol_literal.rb +4 -7
- data/lib/rubocop/cop/style/symbol_proc.rb +11 -7
- data/lib/rubocop/cop/style/tab.rb +25 -2
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +1 -2
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +56 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +8 -7
- data/lib/rubocop/cop/style/trailing_whitespace.rb +2 -1
- data/lib/rubocop/cop/style/trivial_accessors.rb +18 -9
- data/lib/rubocop/cop/style/unless_else.rb +2 -1
- data/lib/rubocop/cop/style/unneeded_capital_w.rb +4 -3
- data/lib/rubocop/cop/style/unneeded_interpolation.rb +87 -0
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +23 -7
- data/lib/rubocop/cop/style/variable_interpolation.rb +8 -6
- data/lib/rubocop/cop/style/variable_name.rb +1 -0
- data/lib/rubocop/cop/style/when_then.rb +2 -1
- data/lib/rubocop/cop/style/while_until_do.rb +3 -2
- data/lib/rubocop/cop/style/while_until_modifier.rb +3 -4
- data/lib/rubocop/cop/style/word_array.rb +74 -51
- data/lib/rubocop/cop/team.rb +21 -15
- data/lib/rubocop/cop/util.rb +102 -69
- data/lib/rubocop/cop/variable_force.rb +2 -1
- data/lib/rubocop/cop/variable_force/assignment.rb +2 -1
- data/lib/rubocop/cop/variable_force/locatable.rb +1 -0
- data/lib/rubocop/cop/variable_force/reference.rb +1 -0
- data/lib/rubocop/cop/variable_force/scope.rb +2 -1
- data/lib/rubocop/cop/variable_force/variable.rb +2 -1
- data/lib/rubocop/cop/variable_force/variable_table.rb +2 -1
- data/lib/rubocop/error.rb +12 -0
- data/lib/rubocop/formatter/base_formatter.rb +10 -1
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -0
- data/lib/rubocop/formatter/colorizable.rb +6 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +29 -15
- data/lib/rubocop/formatter/disabled_lines_formatter.rb +3 -1
- data/lib/rubocop/formatter/emacs_style_formatter.rb +7 -3
- data/lib/rubocop/formatter/file_list_formatter.rb +1 -0
- data/lib/rubocop/formatter/formatter_set.rb +10 -19
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +2 -1
- data/lib/rubocop/formatter/html_formatter.rb +15 -14
- data/lib/rubocop/formatter/json_formatter.rb +2 -1
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -0
- data/lib/rubocop/formatter/progress_formatter.rb +3 -3
- data/lib/rubocop/formatter/simple_text_formatter.rb +50 -17
- data/lib/rubocop/formatter/text_util.rb +8 -10
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +61 -0
- data/lib/rubocop/name_similarity.rb +22 -0
- data/lib/rubocop/node_pattern.rb +126 -35
- data/lib/rubocop/options.rb +28 -19
- data/lib/rubocop/path_util.rb +1 -0
- data/lib/rubocop/processed_source.rb +41 -16
- data/lib/rubocop/rake_task.rb +6 -9
- data/lib/rubocop/remote_config.rb +1 -0
- data/lib/rubocop/result_cache.rb +60 -43
- data/lib/rubocop/runner.rb +48 -45
- data/lib/rubocop/string_util.rb +1 -0
- data/lib/rubocop/target_finder.rb +2 -1
- data/lib/rubocop/token.rb +1 -0
- data/lib/rubocop/version.rb +3 -2
- data/lib/rubocop/warning.rb +1 -0
- data/relnotes/v0.36.0.md +306 -0
- data/rubocop.gemspec +3 -9
- metadata +48 -92
- data/lib/rubocop/cop/lint/space_before_first_arg.rb +0 -44
- data/lib/rubocop/cop/rails/default_scope.rb +0 -33
- data/lib/rubocop/cop/style/trailing_comma.rb +0 -182
@@ -1,11 +1,12 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
5
6
|
module Style
|
6
7
|
# This cop checks for uses of the case equality operator(===).
|
7
8
|
class CaseEquality < Cop
|
8
|
-
MSG = 'Avoid the use of the case equality operator `===`.'
|
9
|
+
MSG = 'Avoid the use of the case equality operator `===`.'.freeze
|
9
10
|
|
10
11
|
def on_send(node)
|
11
12
|
_receiver, method_name, *_args = *node
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -64,7 +65,7 @@ module RuboCop
|
|
64
65
|
|
65
66
|
def autocorrect(node)
|
66
67
|
when_column = node.location.keyword.column
|
67
|
-
source_buffer = node.
|
68
|
+
source_buffer = node.source_range.source_buffer
|
68
69
|
begin_pos = node.loc.keyword.begin_pos
|
69
70
|
whitespace = Parser::Source::Range.new(source_buffer,
|
70
71
|
begin_pos - when_column,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -7,22 +8,25 @@ module RuboCop
|
|
7
8
|
class CharacterLiteral < Cop
|
8
9
|
include StringHelp
|
9
10
|
|
10
|
-
MSG = 'Do not use the character literal -
|
11
|
+
MSG = 'Do not use the character literal - ' \
|
12
|
+
'use string literal instead.'.freeze
|
11
13
|
|
12
14
|
def offense?(node)
|
13
15
|
# we don't register an offense for things like ?\C-\M-d
|
14
16
|
node.loc.begin.is?('?') &&
|
15
|
-
node.
|
17
|
+
node.source.size.between?(2, 3)
|
16
18
|
end
|
17
19
|
|
18
20
|
def autocorrect(node)
|
19
21
|
lambda do |corrector|
|
20
|
-
string = node.
|
22
|
+
string = node.source[1..-1]
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
corrector.replace(node.
|
24
|
+
# special character like \n
|
25
|
+
# or ' which needs to use "" or be escaped.
|
26
|
+
if string.length == 2 || string == "'"
|
27
|
+
corrector.replace(node.source_range, %("#{string}"))
|
28
|
+
elsif string.length == 1 # normal character
|
29
|
+
corrector.replace(node.source_range, "'#{string}'")
|
26
30
|
end
|
27
31
|
end
|
28
32
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -6,7 +7,7 @@ module RuboCop
|
|
6
7
|
# This cops checks for class and module names with
|
7
8
|
# an underscore in them.
|
8
9
|
class ClassAndModuleCamelCase < Cop
|
9
|
-
MSG = 'Use CamelCase for classes and modules.'
|
10
|
+
MSG = 'Use CamelCase for classes and modules.'.freeze
|
10
11
|
|
11
12
|
def on_class(node)
|
12
13
|
check_name(node)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -21,10 +22,10 @@ module RuboCop
|
|
21
22
|
include ConfigurableEnforcedStyle
|
22
23
|
|
23
24
|
NESTED_MSG = 'Use nested module/class definitions instead of ' \
|
24
|
-
'compact style.'
|
25
|
+
'compact style.'.freeze
|
25
26
|
|
26
27
|
COMPACT_MSG = 'Use compact module/class definition instead of ' \
|
27
|
-
'nested style.'
|
28
|
+
'nested style.'.freeze
|
28
29
|
|
29
30
|
def on_class(node)
|
30
31
|
_name, _superclass, body = *node
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -7,7 +8,7 @@ module RuboCop
|
|
7
8
|
class ClassCheck < Cop
|
8
9
|
include ConfigurableEnforcedStyle
|
9
10
|
|
10
|
-
MSG = 'Prefer `Object#%s` over `Object#%s`.'
|
11
|
+
MSG = 'Prefer `Object#%s` over `Object#%s`.'.freeze
|
11
12
|
|
12
13
|
def on_send(node)
|
13
14
|
_receiver, method_name, *_args = *node
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -21,7 +22,7 @@ module RuboCop
|
|
21
22
|
# end
|
22
23
|
# end
|
23
24
|
class ClassMethods < Cop
|
24
|
-
MSG = 'Use `self.%s` instead of `%s.%s`.'
|
25
|
+
MSG = 'Use `self.%s` instead of `%s.%s`.'.freeze
|
25
26
|
|
26
27
|
def on_class(node)
|
27
28
|
name, _superclass, body = *node
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -7,7 +8,7 @@ module RuboCop
|
|
7
8
|
# are signaled only on assignment to class variables to
|
8
9
|
# reduced the number of offenses that would be reported.
|
9
10
|
class ClassVars < Cop
|
10
|
-
MSG = 'Replace class var %s with a class instance var.'
|
11
|
+
MSG = 'Replace class var %s with a class instance var.'.freeze
|
11
12
|
|
12
13
|
def on_cvasgn(node)
|
13
14
|
add_offense(node, :name)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -30,8 +31,8 @@ module RuboCop
|
|
30
31
|
include OnMethodDef
|
31
32
|
|
32
33
|
MSG_INDENT =
|
33
|
-
'Indent `)` the same as the start of the line where `(` is.'
|
34
|
-
MSG_ALIGN = 'Align `)` with `(`.'
|
34
|
+
'Indent `)` the same as the start of the line where `(` is.'.freeze
|
35
|
+
MSG_ALIGN = 'Align `)` with `(`.'.freeze
|
35
36
|
|
36
37
|
def on_send(node)
|
37
38
|
_receiver, _method_name, *args = *node
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -12,7 +13,7 @@ module RuboCop
|
|
12
13
|
class CollectionMethods < Cop
|
13
14
|
include MethodPreference
|
14
15
|
|
15
|
-
MSG = 'Prefer `%s` over `%s`.'
|
16
|
+
MSG = 'Prefer `%s` over `%s`.'.freeze
|
16
17
|
|
17
18
|
def on_block(node)
|
18
19
|
method, _args, _body = *node
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -6,10 +7,10 @@ module RuboCop
|
|
6
7
|
# This cop checks for methods invoked via the :: operator instead
|
7
8
|
# of the . operator (like FileUtils::rmdir instead of FileUtils.rmdir).
|
8
9
|
class ColonMethodCall < Cop
|
9
|
-
MSG = 'Do not use `::` for method calls.'
|
10
|
+
MSG = 'Do not use `::` for method calls.'.freeze
|
10
11
|
|
11
12
|
JAVA_TYPES = [:byte, :boolean, :byte, :short, :char,
|
12
|
-
:int, :long, :float, :double]
|
13
|
+
:int, :long, :float, :double].freeze
|
13
14
|
|
14
15
|
JAVA_TYPE_NODES =
|
15
16
|
JAVA_TYPES.map { |t| s(:send, s(:const, nil, :Java), t) }
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -29,8 +30,8 @@ module RuboCop
|
|
29
30
|
class CommandLiteral < Cop
|
30
31
|
include ConfigurableEnforcedStyle
|
31
32
|
|
32
|
-
MSG_USE_BACKTICKS = 'Use backticks around command string.'
|
33
|
-
MSG_USE_PERCENT_X = 'Use `%x` around command string.'
|
33
|
+
MSG_USE_BACKTICKS = 'Use backticks around command string.'.freeze
|
34
|
+
MSG_USE_PERCENT_X = 'Use `%x` around command string.'.freeze
|
34
35
|
|
35
36
|
def on_xstr(node)
|
36
37
|
return if heredoc_literal?(node)
|
@@ -95,11 +96,11 @@ module RuboCop
|
|
95
96
|
def autocorrect(node)
|
96
97
|
return if contains_backtick?(node)
|
97
98
|
|
98
|
-
if backtick_literal?(node)
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
99
|
+
replacement = if backtick_literal?(node)
|
100
|
+
['%x', ''].zip(preferred_delimiters).map(&:join)
|
101
|
+
else
|
102
|
+
%w(` `)
|
103
|
+
end
|
103
104
|
|
104
105
|
lambda do |corrector|
|
105
106
|
corrector.replace(node.loc.begin, replacement.first)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -10,9 +11,9 @@ module RuboCop
|
|
10
11
|
|
11
12
|
MSG = 'Annotation keywords like `%s` should be all upper case, ' \
|
12
13
|
'followed by a colon, and a space, ' \
|
13
|
-
'then a note describing the problem.'
|
14
|
+
'then a note describing the problem.'.freeze
|
14
15
|
MISSING_NOTE = 'Annotation comment, with keyword `%s`, ' \
|
15
|
-
'is missing a note.'
|
16
|
+
'is missing a note.'.freeze
|
16
17
|
|
17
18
|
def investigate(processed_source)
|
18
19
|
processed_source.comments.each_with_index do |comment, ix|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -7,7 +8,7 @@ module RuboCop
|
|
7
8
|
class CommentIndentation < Cop
|
8
9
|
include AutocorrectAlignment
|
9
10
|
|
10
|
-
MSG = 'Incorrect indentation detected (column %d instead of %d).'
|
11
|
+
MSG = 'Incorrect indentation detected (column %d instead of %d).'.freeze
|
11
12
|
|
12
13
|
def investigate(processed_source)
|
13
14
|
processed_source.comments.each { |comment| check(comment) }
|
@@ -51,14 +52,11 @@ module RuboCop
|
|
51
52
|
end
|
52
53
|
|
53
54
|
def less_indented?(line)
|
54
|
-
|
55
|
-
bracket = '[}\]]'
|
56
|
-
line =~ /^\s*(#{keyword}|#{bracket})/
|
55
|
+
line =~ /^\s*(end\b|[\}\]])/
|
57
56
|
end
|
58
57
|
|
59
58
|
def two_alternatives?(line)
|
60
|
-
|
61
|
-
line =~ /^\s*#{keyword}/
|
59
|
+
line =~ /^\s*(else|elsif|when|rescue|ensure)\b/
|
62
60
|
end
|
63
61
|
end
|
64
62
|
end
|
@@ -0,0 +1,362 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# Helper module to provide common methods to classes needed for the
|
8
|
+
# ConditionalAssignment Cop.
|
9
|
+
module ConditionalAssignmentHelper
|
10
|
+
EQUAL = '='.freeze
|
11
|
+
|
12
|
+
# `elsif` branches show up in the `node` as an `else`. We need
|
13
|
+
# to recursively iterate over all `else` branches and consider all
|
14
|
+
# but the last `node` an `elsif` branch and consider the last `node`
|
15
|
+
# the actual `else` branch.
|
16
|
+
def expand_elses(branch)
|
17
|
+
elsif_branches = expand_elsif(branch)
|
18
|
+
else_branch = elsif_branches.any? ? elsif_branches.pop : branch
|
19
|
+
[elsif_branches, else_branch]
|
20
|
+
end
|
21
|
+
|
22
|
+
# `when` nodes contain the entire branch including the condition.
|
23
|
+
# We only need the contents of the branch, not the condition.
|
24
|
+
def expand_when_branches(when_branches)
|
25
|
+
when_branches.map { |branch| branch.children[1] }
|
26
|
+
end
|
27
|
+
|
28
|
+
def correct_branches(corrector, branches)
|
29
|
+
branches.each do |branch|
|
30
|
+
*_, assignment = *branch
|
31
|
+
corrector.replace(branch.source_range, assignment.source)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def tail(branch)
|
36
|
+
branch.begin_type? ? [*branch].last : branch
|
37
|
+
end
|
38
|
+
|
39
|
+
def lhs(node)
|
40
|
+
case node.type
|
41
|
+
when :send
|
42
|
+
lhs_for_send(node)
|
43
|
+
when :op_asgn
|
44
|
+
"#{node.children[0].source} #{node.children[1]}= "
|
45
|
+
when :and_asgn
|
46
|
+
"#{node.children[0].source} &&= "
|
47
|
+
when :or_asgn
|
48
|
+
"#{node.children[0].source} ||= "
|
49
|
+
when *ConditionalAssignment::VARIABLE_ASSIGNMENT_TYPES
|
50
|
+
"#{node.children[0]} = "
|
51
|
+
else
|
52
|
+
node.source
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
|
58
|
+
def expand_elsif(node, elsif_branches = [])
|
59
|
+
return [] if node.nil? || !node.if_type?
|
60
|
+
_condition, elsif_branch, else_branch = *node
|
61
|
+
elsif_branches << elsif_branch
|
62
|
+
if else_branch && else_branch.if_type?
|
63
|
+
expand_elsif(else_branch, elsif_branches)
|
64
|
+
else
|
65
|
+
elsif_branches << else_branch
|
66
|
+
end
|
67
|
+
elsif_branches
|
68
|
+
end
|
69
|
+
|
70
|
+
def lhs_for_send(node)
|
71
|
+
receiver = node.receiver.nil? ? '' : node.receiver.source
|
72
|
+
|
73
|
+
if node.method_name == :[]=
|
74
|
+
indices = node.children[2...-1].map(&:source).join(', ')
|
75
|
+
"#{receiver}[#{indices}] = "
|
76
|
+
elsif node.method_name.to_s.end_with?(EQUAL) &&
|
77
|
+
![:!=, :==].include?(node.method_name)
|
78
|
+
"#{receiver}.#{node.method_name[0...-1]} = "
|
79
|
+
else
|
80
|
+
"#{receiver} #{node.method_name} "
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Check for `if` and `case` statements where each branch is used for
|
86
|
+
# assignment to the same variable when using the return of the
|
87
|
+
# condition can be used instead.
|
88
|
+
#
|
89
|
+
# @example
|
90
|
+
# # bad
|
91
|
+
# if foo
|
92
|
+
# bar = 1
|
93
|
+
# else
|
94
|
+
# bar = 2
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# case foo
|
98
|
+
# when 'a'
|
99
|
+
# bar += 1
|
100
|
+
# else
|
101
|
+
# bar += 2
|
102
|
+
# end
|
103
|
+
#
|
104
|
+
# if foo
|
105
|
+
# some_method
|
106
|
+
# bar = 1
|
107
|
+
# else
|
108
|
+
# some_other_method
|
109
|
+
# bar = 2
|
110
|
+
# end
|
111
|
+
#
|
112
|
+
# # good
|
113
|
+
# bar = if foo
|
114
|
+
# 1
|
115
|
+
# else
|
116
|
+
# 2
|
117
|
+
# end
|
118
|
+
#
|
119
|
+
# bar += case foo
|
120
|
+
# when 'a'
|
121
|
+
# 1
|
122
|
+
# else
|
123
|
+
# 2
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
# bar << if foo
|
127
|
+
# some_method
|
128
|
+
# 1
|
129
|
+
# else
|
130
|
+
# some_other_method
|
131
|
+
# 2
|
132
|
+
# end
|
133
|
+
class ConditionalAssignment < Cop
|
134
|
+
include IfNode
|
135
|
+
include ConditionalAssignmentHelper
|
136
|
+
|
137
|
+
MSG = 'Use the return of the conditional for variable assignment ' \
|
138
|
+
'and comparison.'.freeze
|
139
|
+
VARIABLE_ASSIGNMENT_TYPES =
|
140
|
+
[:casgn, :cvasgn, :gvasgn, :ivasgn, :lvasgn].freeze
|
141
|
+
ASSIGNMENT_TYPES =
|
142
|
+
VARIABLE_ASSIGNMENT_TYPES + [:and_asgn, :or_asgn, :op_asgn].freeze
|
143
|
+
IF = 'if'.freeze
|
144
|
+
UNLESS = 'unless'.freeze
|
145
|
+
LINE_LENGTH = 'Metrics/LineLength'.freeze
|
146
|
+
INDENTATION_WIDTH = 'Style/IndentationWidth'.freeze
|
147
|
+
ENABLED = 'Enabled'.freeze
|
148
|
+
MAX = 'Max'.freeze
|
149
|
+
SINGLE_LINE_CONDITIONS_ONLY = 'SingleLineConditionsOnly'.freeze
|
150
|
+
WIDTH = 'Width'.freeze
|
151
|
+
METHODS = [:[]=, :<<, :=~, :!~, :<=>].freeze
|
152
|
+
|
153
|
+
def lhs_all_match?(branches)
|
154
|
+
first_lhs = lhs(branches.first)
|
155
|
+
branches.all? { |branch| lhs(branch) == first_lhs }
|
156
|
+
end
|
157
|
+
|
158
|
+
def on_if(node)
|
159
|
+
return if elsif?(node)
|
160
|
+
|
161
|
+
_condition, if_branch, else_branch = *node
|
162
|
+
elsif_branches, else_branch = expand_elses(else_branch)
|
163
|
+
return unless else_branch # empty else
|
164
|
+
|
165
|
+
branches = [if_branch, *elsif_branches, else_branch]
|
166
|
+
|
167
|
+
check_node(node, branches)
|
168
|
+
end
|
169
|
+
|
170
|
+
def on_case(node)
|
171
|
+
_condition, *when_branches, else_branch = *node
|
172
|
+
return unless else_branch # empty else
|
173
|
+
|
174
|
+
when_branches = expand_when_branches(when_branches)
|
175
|
+
branches = [*when_branches, else_branch]
|
176
|
+
|
177
|
+
check_node(node, branches)
|
178
|
+
end
|
179
|
+
|
180
|
+
def autocorrect(node)
|
181
|
+
if ternary_op?(node)
|
182
|
+
TernaryCorrector.correct(node)
|
183
|
+
else
|
184
|
+
case node.loc.keyword.source
|
185
|
+
when IF
|
186
|
+
IfCorrector.correct(node)
|
187
|
+
when UNLESS
|
188
|
+
UnlessCorrector.correct(node)
|
189
|
+
else
|
190
|
+
CaseCorrector.correct(node)
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
private
|
196
|
+
|
197
|
+
def assignment_types_match?(*nodes)
|
198
|
+
return unless assignment_type?(nodes.first)
|
199
|
+
first_type = nodes.first.type
|
200
|
+
nodes.all? { |node| node.type == first_type }
|
201
|
+
end
|
202
|
+
|
203
|
+
# The shovel operator `<<` does not have its own type. It is a `send`
|
204
|
+
# type.
|
205
|
+
def assignment_type?(branch)
|
206
|
+
return true if ASSIGNMENT_TYPES.include?(branch.type)
|
207
|
+
|
208
|
+
if branch.send_type?
|
209
|
+
_variable, method, = *branch
|
210
|
+
return true if METHODS.include?(method)
|
211
|
+
return true if method.to_s.end_with?(EQUAL)
|
212
|
+
end
|
213
|
+
|
214
|
+
false
|
215
|
+
end
|
216
|
+
|
217
|
+
def check_node(node, branches)
|
218
|
+
return unless branches.all?
|
219
|
+
last_statements = branches.map { |branch| tail(branch) }
|
220
|
+
return unless lhs_all_match?(last_statements)
|
221
|
+
return if last_statements.any?(&:masgn_type?)
|
222
|
+
return unless assignment_types_match?(*last_statements)
|
223
|
+
|
224
|
+
return if single_line_conditions_only? && branches.any?(&:begin_type?)
|
225
|
+
return if correction_exceeds_line_limit?(node, branches)
|
226
|
+
|
227
|
+
add_offense(node, :expression)
|
228
|
+
end
|
229
|
+
|
230
|
+
# If `Metrics/LineLength` is enabled, we do not want to introduce an
|
231
|
+
# offense by auto-correcting this cop. Find the max configured line
|
232
|
+
# length. Find the longest line of condition. Remove the assignment
|
233
|
+
# from lines that contain the offending assignment because after
|
234
|
+
# correcting, this will not be on the line anymore. Check if the length
|
235
|
+
# of the longest line + the length of the corrected assignment is
|
236
|
+
# greater than the max configured line length
|
237
|
+
def correction_exceeds_line_limit?(node, branches)
|
238
|
+
return false unless config.for_cop(LINE_LENGTH)[ENABLED]
|
239
|
+
assignment = lhs(tail(branches[0]))
|
240
|
+
assignment_regex = /#{assignment.gsub(' ', '\s*')}/
|
241
|
+
max_line_length = config.for_cop(LINE_LENGTH)[MAX]
|
242
|
+
indentation_width = config.for_cop(INDENTATION_WIDTH)[WIDTH] || 2
|
243
|
+
return true if longest_rhs(branches) + indentation_width +
|
244
|
+
assignment.length > max_line_length
|
245
|
+
lines = node.source.lines.map do |line|
|
246
|
+
line.chomp.sub(assignment_regex, '')
|
247
|
+
end
|
248
|
+
longest_line = lines.max_by(&:length)
|
249
|
+
(longest_line + assignment).length > max_line_length
|
250
|
+
end
|
251
|
+
|
252
|
+
def longest_rhs(branches)
|
253
|
+
branches.map { |branch| branch.children.last.source.length }.max
|
254
|
+
end
|
255
|
+
|
256
|
+
def lines_with_numbers(node)
|
257
|
+
line_nos = node.loc.line..node.loc.last_line
|
258
|
+
node.source.lines.zip(line_nos)
|
259
|
+
end
|
260
|
+
|
261
|
+
def single_line_conditions_only?
|
262
|
+
cop_config[SINGLE_LINE_CONDITIONS_ONLY]
|
263
|
+
end
|
264
|
+
end
|
265
|
+
|
266
|
+
# Corrector to correct conditional assignment in ternary conditions.
|
267
|
+
class TernaryCorrector
|
268
|
+
class << self
|
269
|
+
include ConditionalAssignmentHelper
|
270
|
+
|
271
|
+
def correct(node)
|
272
|
+
condition, if_branch, else_branch = *node
|
273
|
+
_variable, *_operator, if_rhs = *if_branch
|
274
|
+
_else_variable, *_operator, else_rhs = *else_branch
|
275
|
+
condition = condition.source
|
276
|
+
if_rhs = if_rhs.source
|
277
|
+
else_rhs = else_rhs.source
|
278
|
+
|
279
|
+
ternary = "#{condition} ? #{if_rhs} : #{else_rhs}"
|
280
|
+
if if_branch.send_type? && if_branch.method_name != :[]=
|
281
|
+
ternary = "(#{ternary})"
|
282
|
+
end
|
283
|
+
correction = "#{lhs(if_branch)}#{ternary}"
|
284
|
+
|
285
|
+
lambda do |corrector|
|
286
|
+
corrector.replace(node.source_range, correction)
|
287
|
+
end
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
# Corrector to correct conditional assignment in `if` statements.
|
293
|
+
class IfCorrector
|
294
|
+
class << self
|
295
|
+
include ConditionalAssignmentHelper
|
296
|
+
|
297
|
+
def correct(node)
|
298
|
+
_condition, if_branch, else_branch = *node
|
299
|
+
if_branch = tail(if_branch)
|
300
|
+
_variable, *_operator, if_assignment = *if_branch
|
301
|
+
elsif_branches, else_branch = expand_elses(else_branch)
|
302
|
+
elsif_branches.map! { |branch| tail(branch) }
|
303
|
+
else_branch = tail(else_branch)
|
304
|
+
_else_variable, *_operator, else_assignment = *else_branch
|
305
|
+
|
306
|
+
lambda do |corrector|
|
307
|
+
corrector.insert_before(node.source_range, lhs(if_branch))
|
308
|
+
corrector.replace(if_branch.source_range, if_assignment.source)
|
309
|
+
correct_branches(corrector, elsif_branches)
|
310
|
+
corrector.replace(else_branch.source_range,
|
311
|
+
else_assignment.source)
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
# Corrector to correct conditional assignment in `case` statements.
|
318
|
+
class CaseCorrector
|
319
|
+
class << self
|
320
|
+
include ConditionalAssignmentHelper
|
321
|
+
|
322
|
+
def correct(node)
|
323
|
+
_condition, *when_branches, else_branch = *node
|
324
|
+
else_branch = tail(else_branch)
|
325
|
+
when_branches = expand_when_branches(when_branches)
|
326
|
+
when_branches.map! { |when_branch| tail(when_branch) }
|
327
|
+
_variable, *_operator, else_assignment = *else_branch
|
328
|
+
|
329
|
+
lambda do |corrector|
|
330
|
+
corrector.insert_before(node.source_range, lhs(else_branch))
|
331
|
+
correct_branches(corrector, when_branches)
|
332
|
+
corrector.replace(else_branch.source_range,
|
333
|
+
else_assignment.source)
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
# Corrector to correct conditional assignment in `unless` statements.
|
340
|
+
class UnlessCorrector
|
341
|
+
class << self
|
342
|
+
include ConditionalAssignmentHelper
|
343
|
+
|
344
|
+
def correct(node)
|
345
|
+
_condition, else_branch, if_branch = *node
|
346
|
+
if_branch = tail(if_branch)
|
347
|
+
else_branch = tail(else_branch)
|
348
|
+
_variable, *_operator, if_assignment = *if_branch
|
349
|
+
_else_variable, *_operator, else_assignment = *else_branch
|
350
|
+
|
351
|
+
lambda do |corrector|
|
352
|
+
corrector.insert_before(node.source_range, lhs(if_branch))
|
353
|
+
corrector.replace(if_branch.source_range, if_assignment.source)
|
354
|
+
corrector.replace(else_branch.source_range,
|
355
|
+
else_assignment.source)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
end
|
360
|
+
end
|
361
|
+
end
|
362
|
+
end
|