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,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
|
include FirstElementLineBreak
|
22
23
|
|
23
24
|
MSG = 'Add a line break before the first element of a ' \
|
24
|
-
'multi-line array.'
|
25
|
+
'multi-line array.'.freeze
|
25
26
|
|
26
27
|
def on_array(node)
|
27
28
|
return if !node.loc.begin && !assignment_on_same_line?(node)
|
@@ -32,7 +33,7 @@ module RuboCop
|
|
32
33
|
private
|
33
34
|
|
34
35
|
def assignment_on_same_line?(node)
|
35
|
-
source = node.
|
36
|
+
source = node.source_range.source_line[0...node.loc.column]
|
36
37
|
source =~ /\s*\=\s*$/
|
37
38
|
end
|
38
39
|
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
|
@@ -20,14 +21,12 @@ module RuboCop
|
|
20
21
|
include FirstElementLineBreak
|
21
22
|
|
22
23
|
MSG = 'Add a line break before the first element of a ' \
|
23
|
-
'multi-line hash.'
|
24
|
+
'multi-line hash.'.freeze
|
24
25
|
|
25
26
|
def on_hash(node)
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
check_children_line_break(node, node.children, node.parent)
|
30
|
-
end
|
27
|
+
# node.loc.begin tells us whether the hash opens with a {
|
28
|
+
# If it doesn't, Style/FirstMethodArgumentLineBreak will handle it
|
29
|
+
check_children_line_break(node, node.children) if node.loc.begin
|
31
30
|
end
|
32
31
|
end
|
33
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
|
@@ -24,11 +25,23 @@ module RuboCop
|
|
24
25
|
include FirstElementLineBreak
|
25
26
|
|
26
27
|
MSG = 'Add a line break before the first argument of a ' \
|
27
|
-
'multi-line method argument list.'
|
28
|
+
'multi-line method argument list.'.freeze
|
28
29
|
|
29
30
|
def on_send(node)
|
30
31
|
_receiver, _name, *args = *node
|
31
32
|
|
33
|
+
# If there is a trailing hash arg without explicit braces, like this:
|
34
|
+
#
|
35
|
+
# method(1, 'key1' => value1, 'key2' => value2)
|
36
|
+
#
|
37
|
+
# ...then each key/value pair is treated as a method 'argument'
|
38
|
+
# when determining where line breaks should appear.
|
39
|
+
if (last_arg = args.last)
|
40
|
+
if last_arg.hash_type? && !last_arg.loc.begin # no explicit {
|
41
|
+
args = args.concat(args.pop.children)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
32
45
|
check_method_line_break(node, args)
|
33
46
|
end
|
34
47
|
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
|
@@ -31,7 +32,7 @@ module RuboCop
|
|
31
32
|
include FirstElementLineBreak
|
32
33
|
|
33
34
|
MSG = 'Add a line break before the first parameter of a ' \
|
34
|
-
'multi-line method parameter list.'
|
35
|
+
'multi-line method parameter list.'.freeze
|
35
36
|
|
36
37
|
def on_method_def(node, _method_name, args, _body)
|
37
38
|
check_method_line_break(node, args.to_a)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -69,13 +70,13 @@ module RuboCop
|
|
69
70
|
|
70
71
|
# The node must begin inside the parent, otherwise node is the first
|
71
72
|
# part of a chained method call.
|
72
|
-
node.
|
73
|
+
node.source_range.begin_pos > parent.source_range.begin_pos
|
73
74
|
end
|
74
75
|
|
75
76
|
def base_range(send_node, arg_node)
|
76
77
|
Parser::Source::Range.new(processed_source.buffer,
|
77
|
-
send_node.
|
78
|
-
arg_node.
|
78
|
+
send_node.source_range.begin_pos,
|
79
|
+
arg_node.source_range.begin_pos)
|
79
80
|
end
|
80
81
|
|
81
82
|
# Returns the column of the given range. For single line ranges, this
|
@@ -94,7 +95,8 @@ module RuboCop
|
|
94
95
|
# line.
|
95
96
|
def previous_code_line(line_number)
|
96
97
|
@comment_lines ||=
|
97
|
-
processed_source
|
98
|
+
processed_source
|
99
|
+
.comments
|
98
100
|
.select { |c| begins_its_line?(c.loc.expression) }
|
99
101
|
.map { |c| c.loc.line }
|
100
102
|
|
@@ -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 looks for uses of flip flop operator
|
7
8
|
class FlipFlop < Cop
|
8
|
-
MSG = 'Avoid the use of flip flop operators.'
|
9
|
+
MSG = 'Avoid the use of flip flop operators.'.freeze
|
9
10
|
|
10
11
|
def on_iflipflop(node)
|
11
12
|
add_offense(node, :expression)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -31,7 +32,7 @@ module RuboCop
|
|
31
32
|
return unless method_name == :each && args.empty?
|
32
33
|
|
33
34
|
if style == :for
|
34
|
-
end_pos = method.
|
35
|
+
end_pos = method.source_range.end_pos
|
35
36
|
range = Parser::Source::Range.new(processed_source.buffer,
|
36
37
|
end_pos - EACH_LENGTH,
|
37
38
|
end_pos)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# This cop is designed to help upgrade to Ruby 3.0. It will add the
|
8
|
+
# comment `# frozen_string_literal: true` to the top of files to
|
9
|
+
# enable frozen string literals. Frozen string literals will be default
|
10
|
+
# in Ruby 3.0. The comment will be added below a shebang and encoding
|
11
|
+
# comment. The frozen string literal comment is only valid in Ruby 2.3+.
|
12
|
+
class FrozenStringLiteralComment < Cop
|
13
|
+
include ConfigurableEnforcedStyle
|
14
|
+
|
15
|
+
MSG = 'Missing frozen string literal comment.'.freeze
|
16
|
+
FROZEN_STRING_LITERAL = '# frozen_string_literal:'.freeze
|
17
|
+
FROZEN_STRING_LITERAL_ENABLED = '# frozen_string_literal: true'.freeze
|
18
|
+
SHEBANG = '#!'.freeze
|
19
|
+
|
20
|
+
def_node_matcher :frozen_strings, '{(send {dstr str} :<< ...)
|
21
|
+
(send {dstr str} :freeze)}'
|
22
|
+
|
23
|
+
def investigate(processed_source)
|
24
|
+
return unless style == :always
|
25
|
+
return if processed_source.buffer.source.empty?
|
26
|
+
|
27
|
+
return if frozen_string_literal_comment_exists?(processed_source)
|
28
|
+
|
29
|
+
offense(processed_source)
|
30
|
+
end
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
return if target_ruby_version < 2.3 && RUBY_VERSION < '2.3.0'
|
34
|
+
return unless style == :when_needed
|
35
|
+
return if frozen_string_literal_comment_exists?(processed_source)
|
36
|
+
|
37
|
+
frozen_strings(node) { offense(processed_source) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def autocorrect(_node)
|
41
|
+
lambda do |corrector|
|
42
|
+
last_special_comment = last_special_comment(processed_source)
|
43
|
+
if last_special_comment.nil?
|
44
|
+
corrector.insert_before(processed_source.tokens[0].pos,
|
45
|
+
"#{FROZEN_STRING_LITERAL_ENABLED}\n")
|
46
|
+
else
|
47
|
+
corrector.insert_after(last_special_comment.pos,
|
48
|
+
"\n#{FROZEN_STRING_LITERAL_ENABLED}")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def frozen_string_literal_comment_exists?(processed_source)
|
56
|
+
first_three_lines =
|
57
|
+
[processed_source[0], processed_source[1], processed_source[2]]
|
58
|
+
first_three_lines.compact!
|
59
|
+
first_three_lines.any? do |line|
|
60
|
+
line.start_with?(FROZEN_STRING_LITERAL)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def last_special_comment(processed_source)
|
65
|
+
token_number = 0
|
66
|
+
if processed_source.tokens[token_number].text.start_with?(SHEBANG)
|
67
|
+
token = processed_source.tokens[token_number]
|
68
|
+
token_number += 1
|
69
|
+
end
|
70
|
+
|
71
|
+
if processed_source.tokens[token_number].text =~
|
72
|
+
Encoding::ENCODING_PATTERN
|
73
|
+
token = processed_source.tokens[token_number]
|
74
|
+
end
|
75
|
+
|
76
|
+
token
|
77
|
+
end
|
78
|
+
|
79
|
+
def offense(processed_source)
|
80
|
+
last_special_comment = last_special_comment(processed_source)
|
81
|
+
last_special_comment ||= processed_source.tokens[0]
|
82
|
+
range = source_range(processed_source.buffer, 0, 0)
|
83
|
+
|
84
|
+
add_offense(last_special_comment, range, MSG)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
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
|
@@ -10,7 +11,7 @@ module RuboCop
|
|
10
11
|
#
|
11
12
|
# Note that backreferences like $1, $2, etc are not global variables.
|
12
13
|
class GlobalVars < Cop
|
13
|
-
MSG = 'Do not introduce global variables.'
|
14
|
+
MSG = 'Do not introduce global variables.'.freeze
|
14
15
|
|
15
16
|
# predefined global variables their English aliases
|
16
17
|
# http://www.zenspider.com/Languages/Ruby/QuickRef.html
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
module RuboCop
|
4
5
|
module Cop
|
@@ -24,45 +25,96 @@ module RuboCop
|
|
24
25
|
# def test
|
25
26
|
# work if something
|
26
27
|
# end
|
28
|
+
#
|
29
|
+
# # bad
|
30
|
+
# if something
|
31
|
+
# raise 'exception'
|
32
|
+
# else
|
33
|
+
# ok
|
34
|
+
# end
|
35
|
+
#
|
36
|
+
# # good
|
37
|
+
# raise 'exception' if something
|
38
|
+
# ok
|
27
39
|
class GuardClause < Cop
|
28
40
|
include ConfigurableEnforcedStyle
|
29
41
|
include IfNode
|
30
42
|
include MinBodyLength
|
31
43
|
|
32
44
|
MSG = 'Use a guard clause instead of wrapping the code inside a ' \
|
33
|
-
'conditional expression.'
|
45
|
+
'conditional expression.'.freeze
|
46
|
+
|
47
|
+
def_node_matcher :single_line_control_flow_exit?, <<-PATTERN
|
48
|
+
[{(send nil {:raise :fail} ...) return break next} single_line?]
|
49
|
+
PATTERN
|
34
50
|
|
35
51
|
def on_def(node)
|
36
52
|
_, _, body = *node
|
37
53
|
return unless body
|
38
54
|
|
39
55
|
if if?(body)
|
40
|
-
|
41
|
-
elsif body.
|
42
|
-
|
43
|
-
last_expr
|
44
|
-
|
45
|
-
check_if_node(last_expr) if if?(last_expr)
|
56
|
+
check_trailing_if(body)
|
57
|
+
elsif body.begin_type?
|
58
|
+
last_expr = body.children.last
|
59
|
+
check_trailing_if(last_expr) if if?(last_expr)
|
46
60
|
end
|
47
61
|
end
|
48
62
|
|
63
|
+
def on_if(node)
|
64
|
+
cond, body, else_body = *node
|
65
|
+
|
66
|
+
return unless body && else_body
|
67
|
+
# discard modifier ifs and ternary_ops
|
68
|
+
return if modifier_if?(node) || ternary_op?(node) || elsif?(node)
|
69
|
+
|
70
|
+
return unless single_line_control_flow_exit?(body) ||
|
71
|
+
single_line_control_flow_exit?(else_body)
|
72
|
+
return if cond.multiline?
|
73
|
+
return if line_too_long_when_corrected?(node)
|
74
|
+
|
75
|
+
add_offense(node, :keyword, MSG)
|
76
|
+
end
|
77
|
+
|
49
78
|
private
|
50
79
|
|
51
|
-
def if?(
|
52
|
-
|
80
|
+
def if?(node)
|
81
|
+
node && node.if_type?
|
53
82
|
end
|
54
83
|
|
55
|
-
def
|
56
|
-
|
84
|
+
def elsif?(node)
|
85
|
+
node.children.last.if_type?
|
86
|
+
end
|
87
|
+
|
88
|
+
def check_trailing_if(node)
|
89
|
+
cond, body, else_body = *node
|
57
90
|
|
58
91
|
return if body && else_body
|
59
92
|
# discard modifier ifs and ternary_ops
|
60
93
|
return if modifier_if?(node) || ternary_op?(node)
|
94
|
+
return if cond.multiline?
|
61
95
|
# discard short ifs
|
62
96
|
return unless min_body_length?(node)
|
97
|
+
return if line_too_long_when_corrected?(node)
|
63
98
|
|
64
99
|
add_offense(node, :keyword, MSG)
|
65
100
|
end
|
101
|
+
|
102
|
+
def line_too_long_when_corrected?(node)
|
103
|
+
cond, body, else_body = *node
|
104
|
+
|
105
|
+
if single_line_control_flow_exit?(body) || !else_body
|
106
|
+
line_too_long?(node, body, 'if', cond)
|
107
|
+
else
|
108
|
+
line_too_long?(node, else_body, 'unless', cond)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def line_too_long?(node, body, keyword, condition)
|
113
|
+
max = config.for_cop('Metrics/LineLength')['Max'] || 80
|
114
|
+
indent = node.loc.column
|
115
|
+
# 2 is for spaces on left and right of keyword
|
116
|
+
indent + (body.source + keyword + condition.source).length + 2 > max
|
117
|
+
end
|
66
118
|
end
|
67
119
|
end
|
68
120
|
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
|
@@ -12,9 +13,9 @@ module RuboCop
|
|
12
13
|
class HashSyntax < Cop
|
13
14
|
include ConfigurableEnforcedStyle
|
14
15
|
|
15
|
-
MSG_19 = 'Use the new Ruby 1.9 hash syntax.'
|
16
|
-
MSG_RUBY19_NO_MIXED_KEYS = "Don't mix styles in the same hash."
|
17
|
-
MSG_HASH_ROCKETS = 'Use hash rockets syntax.'
|
16
|
+
MSG_19 = 'Use the new Ruby 1.9 hash syntax.'.freeze
|
17
|
+
MSG_RUBY19_NO_MIXED_KEYS = "Don't mix styles in the same hash.".freeze
|
18
|
+
MSG_HASH_ROCKETS = 'Use hash rockets syntax.'.freeze
|
18
19
|
|
19
20
|
@force_hash_rockets = false
|
20
21
|
|
@@ -95,8 +96,7 @@ module RuboCop
|
|
95
96
|
|
96
97
|
return false unless key.sym_type?
|
97
98
|
|
98
|
-
|
99
|
-
valid_19_syntax_symbol?(sym_name)
|
99
|
+
valid_19_syntax_symbol?(key.source)
|
100
100
|
end
|
101
101
|
|
102
102
|
def valid_19_syntax_symbol?(sym_name)
|
@@ -105,15 +105,15 @@ module RuboCop
|
|
105
105
|
# Most hash keys can be matched against a simple regex.
|
106
106
|
return true if sym_name =~ /\A[_a-z]\w*[?!]?\z/i
|
107
107
|
|
108
|
-
# For more complicated hash keys, let the
|
109
|
-
|
108
|
+
# For more complicated hash keys, let the parser validate the syntax.
|
109
|
+
parse("{ #{sym_name}: :foo }").valid_syntax?
|
110
110
|
end
|
111
111
|
|
112
112
|
def check(pairs, delim, msg)
|
113
113
|
pairs.each do |pair|
|
114
114
|
if pair.loc.operator && pair.loc.operator.is?(delim)
|
115
115
|
add_offense(pair,
|
116
|
-
pair.
|
116
|
+
pair.source_range.begin.join(pair.loc.operator),
|
117
117
|
msg) do
|
118
118
|
opposite_style_detected
|
119
119
|
end
|
@@ -124,7 +124,7 @@ module RuboCop
|
|
124
124
|
end
|
125
125
|
|
126
126
|
def autocorrect_ruby19(corrector, node)
|
127
|
-
key = node.children.first.
|
127
|
+
key = node.children.first.source_range
|
128
128
|
op = node.loc.operator
|
129
129
|
|
130
130
|
range = Parser::Source::Range.new(key.source_buffer,
|
@@ -135,7 +135,7 @@ module RuboCop
|
|
135
135
|
end
|
136
136
|
|
137
137
|
def autocorrect_hash_rockets(corrector, node)
|
138
|
-
key = node.children.first.
|
138
|
+
key = node.children.first.source_range
|
139
139
|
op = node.loc.operator
|
140
140
|
|
141
141
|
corrector.insert_after(key, ' => ')
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Style
|
7
|
+
# This cop checks for identical lines at the end of each branch of a
|
8
|
+
# conditional statement.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# @bad
|
12
|
+
# if condition
|
13
|
+
# do_x
|
14
|
+
# do_z
|
15
|
+
# else
|
16
|
+
# do_y
|
17
|
+
# do_z
|
18
|
+
# end
|
19
|
+
#
|
20
|
+
# @good
|
21
|
+
# if condition
|
22
|
+
# do_x
|
23
|
+
# else
|
24
|
+
# do_y
|
25
|
+
# end
|
26
|
+
# do_z
|
27
|
+
class IdenticalConditionalBranches < Cop
|
28
|
+
include IfNode
|
29
|
+
|
30
|
+
MSG = 'Move `%s` out of the conditional.'.freeze
|
31
|
+
|
32
|
+
def on_if(node)
|
33
|
+
return if elsif?(node)
|
34
|
+
_condition, if_branch, else_branch = *node
|
35
|
+
branches = expand_elses(else_branch).unshift(if_branch)
|
36
|
+
|
37
|
+
# return if any branch is empty. An empty branch can be an `if`
|
38
|
+
# without an `else`, or a branch that contains only comments.
|
39
|
+
return if branches.any?(&:nil?)
|
40
|
+
|
41
|
+
check_node(branches)
|
42
|
+
end
|
43
|
+
|
44
|
+
def on_case(node)
|
45
|
+
return unless node.loc.else
|
46
|
+
_condition, *when_branches, else_branch = *node
|
47
|
+
return unless else_branch # empty else
|
48
|
+
when_branches = expand_when_branches(when_branches)
|
49
|
+
|
50
|
+
check_node(when_branches.push(else_branch))
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def check_node(branches)
|
56
|
+
branches = branches.map { |branch| tail(branch) }
|
57
|
+
|
58
|
+
return unless branches.all? { |branch| branch == branches[0] }
|
59
|
+
branches.each do |branch|
|
60
|
+
add_offense(branch, :expression, format(MSG, branch.source))
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# `elsif` branches show up in the if node as nested `else` branches. We
|
65
|
+
# need to recursively iterate over all `else` branches.
|
66
|
+
def expand_elses(branch)
|
67
|
+
if branch.nil?
|
68
|
+
[nil]
|
69
|
+
elsif branch.if_type?
|
70
|
+
_condition, elsif_branch, else_branch = *branch
|
71
|
+
expand_elses(else_branch).unshift(elsif_branch)
|
72
|
+
else
|
73
|
+
[branch]
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# `when` nodes contain the entire branch including the condition.
|
78
|
+
# We only need the contents of the branch, not the condition.
|
79
|
+
def expand_when_branches(when_branches)
|
80
|
+
when_branches.map { |branch| branch.children[1] }
|
81
|
+
end
|
82
|
+
|
83
|
+
def tail(node)
|
84
|
+
if node && node.begin_type?
|
85
|
+
node.children.last
|
86
|
+
else
|
87
|
+
node
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|