rubocop 0.52.1 → 0.53.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +118 -46
- data/config/disabled.yml +8 -8
- data/config/enabled.yml +84 -28
- data/lib/rubocop.rb +28 -8
- data/lib/rubocop/ast/builder.rb +35 -37
- data/lib/rubocop/ast/node.rb +16 -1
- data/lib/rubocop/ast/node/and_node.rb +0 -8
- data/lib/rubocop/ast/node/block_node.rb +1 -9
- data/lib/rubocop/ast/node/case_node.rb +0 -8
- data/lib/rubocop/ast/node/ensure_node.rb +0 -8
- data/lib/rubocop/ast/node/for_node.rb +0 -8
- data/lib/rubocop/ast/node/or_node.rb +0 -8
- data/lib/rubocop/ast/node/pair_node.rb +0 -8
- data/lib/rubocop/ast/node/resbody_node.rb +0 -8
- data/lib/rubocop/ast/node/send_node.rb +0 -8
- data/lib/rubocop/ast/node/symbol_node.rb +0 -8
- data/lib/rubocop/ast/node/until_node.rb +0 -8
- data/lib/rubocop/ast/node/when_node.rb +0 -8
- data/lib/rubocop/ast/node/while_node.rb +0 -8
- data/lib/rubocop/cli.rb +17 -7
- data/lib/rubocop/comment_config.rb +24 -3
- data/lib/rubocop/config.rb +75 -6
- data/lib/rubocop/config_loader.rb +18 -28
- data/lib/rubocop/config_loader_resolver.rb +61 -9
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +3 -1
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +4 -2
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -1
- data/lib/rubocop/cop/commissioner.rb +2 -2
- data/lib/rubocop/cop/cop.rb +4 -0
- data/lib/rubocop/cop/corrector.rb +11 -1
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +3 -6
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +59 -0
- data/lib/rubocop/cop/correctors/multiline_literal_brace_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/space_corrector.rb +13 -0
- data/lib/rubocop/cop/correctors/unused_arg_corrector.rb +1 -1
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +3 -1
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +3 -5
- data/lib/rubocop/cop/generator.rb +29 -8
- data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +2 -0
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +2 -0
- data/lib/rubocop/cop/layout/align_hash.rb +106 -37
- data/lib/rubocop/cop/{lint → layout}/block_alignment.rb +8 -5
- data/lib/rubocop/cop/layout/block_end_newline.rb +7 -17
- data/lib/rubocop/cop/layout/case_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +6 -7
- data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
- data/lib/rubocop/cop/{lint → layout}/condition_position.rb +3 -3
- data/lib/rubocop/cop/{lint → layout}/def_end_alignment.rb +2 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_comment.rb +140 -0
- data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +2 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -0
- data/lib/rubocop/cop/layout/empty_lines.rb +3 -1
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +7 -5
- data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +20 -10
- data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +20 -0
- data/lib/rubocop/cop/{lint → layout}/end_alignment.rb +37 -6
- data/lib/rubocop/cop/layout/end_of_line.rb +1 -0
- data/lib/rubocop/cop/layout/extra_spacing.rb +30 -37
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -0
- data/lib/rubocop/cop/layout/indent_heredoc.rb +38 -2
- data/lib/rubocop/cop/layout/indentation_consistency.rb +105 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +4 -3
- data/lib/rubocop/cop/layout/initial_indentation.rb +15 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +4 -2
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_method_call_brace_layout.rb +62 -29
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_method_definition_brace_layout.rb +74 -33
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +16 -2
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +3 -1
- data/lib/rubocop/cop/layout/space_after_method_name.rb +2 -0
- data/lib/rubocop/cop/layout/space_after_not.rb +2 -0
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +1 -0
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +15 -2
- data/lib/rubocop/cop/layout/space_around_operators.rb +15 -13
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +13 -1
- data/lib/rubocop/cop/layout/space_before_comment.rb +6 -4
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +1 -0
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -0
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +30 -45
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +3 -2
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +48 -18
- data/lib/rubocop/cop/layout/space_inside_parens.rb +8 -7
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +57 -11
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +1 -0
- data/lib/rubocop/cop/layout/tab.rb +42 -16
- data/lib/rubocop/cop/layout/trailing_blank_lines.rb +46 -13
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +12 -0
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +5 -3
- data/lib/rubocop/cop/lint/big_decimal_new.rb +44 -0
- data/lib/rubocop/cop/lint/boolean_symbol.rb +2 -2
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +2 -2
- data/lib/rubocop/cop/lint/debugger.rb +2 -2
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +5 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +20 -9
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +4 -3
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +16 -10
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +5 -4
- data/lib/rubocop/cop/lint/inherit_exception.rb +2 -2
- data/lib/rubocop/cop/lint/interpolation_check.rb +4 -3
- data/lib/rubocop/cop/lint/literal_as_condition.rb +2 -2
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +2 -0
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +7 -5
- data/lib/rubocop/cop/lint/nested_percent_literal.rb +1 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +59 -0
- data/lib/rubocop/cop/lint/ordered_magic_comments.rb +86 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +2 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +0 -2
- data/lib/rubocop/cop/lint/rand_one.rb +2 -2
- data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -0
- data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -0
- data/lib/rubocop/cop/lint/require_parentheses.rb +2 -0
- data/lib/rubocop/cop/lint/rescue_type.rb +6 -3
- data/lib/rubocop/cop/lint/return_in_void_context.rb +2 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +17 -21
- data/lib/rubocop/cop/lint/script_permission.rb +30 -10
- data/lib/rubocop/cop/lint/shadowed_argument.rb +3 -3
- data/lib/rubocop/cop/lint/shadowed_exception.rb +1 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +2 -2
- data/lib/rubocop/cop/lint/unified_integer.rb +2 -2
- data/lib/rubocop/cop/lint/{unneeded_disable.rb → unneeded_cop_disable_directive.rb} +13 -7
- data/lib/rubocop/cop/lint/unneeded_cop_enable_directive.rb +97 -0
- data/lib/rubocop/cop/lint/unneeded_require_statement.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +3 -3
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +11 -10
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +7 -5
- data/lib/rubocop/cop/lint/useless_assignment.rb +2 -2
- data/lib/rubocop/cop/lint/useless_setter_call.rb +2 -2
- data/lib/rubocop/cop/lint/void.rb +49 -10
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/line_length.rb +5 -2
- data/lib/rubocop/cop/mixin/alignment.rb +4 -0
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -1
- data/lib/rubocop/cop/mixin/def_node.rb +4 -0
- data/lib/rubocop/cop/mixin/documentation_comment.rb +11 -3
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +12 -2
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +20 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +4 -0
- data/lib/rubocop/cop/mixin/hash_alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/match_range.rb +2 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +6 -0
- data/lib/rubocop/cop/mixin/nil_methods.rb +19 -0
- data/lib/rubocop/cop/mixin/percent_literal.rb +57 -9
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +6 -5
- data/lib/rubocop/cop/mixin/range_help.rb +102 -0
- data/lib/rubocop/cop/mixin/rescue_node.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +8 -7
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +11 -9
- data/lib/rubocop/cop/mixin/statement_modifier.rb +3 -10
- data/lib/rubocop/cop/mixin/surrounding_space.rb +38 -8
- data/lib/rubocop/cop/mixin/trailing_body.rb +26 -0
- data/lib/rubocop/cop/mixin/trailing_comma.rb +15 -3
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +104 -0
- data/lib/rubocop/cop/naming/ascii_identifiers.rb +3 -1
- data/lib/rubocop/cop/naming/file_name.rb +5 -10
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +76 -0
- data/lib/rubocop/cop/naming/uncommunicative_block_param_name.rb +48 -0
- data/lib/rubocop/cop/naming/uncommunicative_method_param_name.rb +57 -0
- data/lib/rubocop/cop/offense.rb +3 -2
- data/lib/rubocop/cop/performance/case_when_splat.rb +1 -0
- data/lib/rubocop/cop/performance/casecmp.rb +17 -8
- data/lib/rubocop/cop/performance/compare_with_block.rb +2 -0
- data/lib/rubocop/cop/performance/count.rb +1 -0
- data/lib/rubocop/cop/performance/fixed_size.rb +41 -0
- data/lib/rubocop/cop/performance/flat_map.rb +2 -0
- data/lib/rubocop/cop/performance/lstrip_rstrip.rb +2 -0
- data/lib/rubocop/cop/performance/redundant_merge.rb +1 -1
- data/lib/rubocop/cop/performance/redundant_sort_by.rb +2 -0
- data/lib/rubocop/cop/performance/regexp_match.rb +4 -0
- data/lib/rubocop/cop/performance/reverse_each.rb +2 -0
- data/lib/rubocop/cop/performance/string_replacement.rb +2 -0
- data/lib/rubocop/cop/rails/active_record_aliases.rb +46 -0
- data/lib/rubocop/cop/rails/blank.rb +3 -3
- data/lib/rubocop/cop/rails/create_table_with_timestamps.rb +6 -0
- data/lib/rubocop/cop/rails/delegate.rb +6 -6
- data/lib/rubocop/cop/rails/file_path.rb +7 -1
- data/lib/rubocop/cop/rails/find_by.rb +2 -0
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +17 -5
- data/lib/rubocop/cop/rails/inverse_of.rb +21 -2
- data/lib/rubocop/cop/rails/lexically_scoped_action_filter.rb +45 -9
- data/lib/rubocop/cop/rails/presence.rb +8 -2
- data/lib/rubocop/cop/rails/present.rb +5 -5
- data/lib/rubocop/cop/rails/read_write_attribute.rb +4 -3
- data/lib/rubocop/cop/rails/redundant_receiver_in_with_options.rb +1 -0
- data/lib/rubocop/cop/rails/relative_date_constant.rb +4 -3
- data/lib/rubocop/cop/rails/request_referer.rb +3 -2
- data/lib/rubocop/cop/rails/reversible_migration.rb +9 -8
- data/lib/rubocop/cop/rails/safe_navigation.rb +3 -2
- data/lib/rubocop/cop/rails/save_bang.rb +11 -12
- data/lib/rubocop/cop/rails/skips_model_validations.rb +2 -2
- data/lib/rubocop/cop/rails/time_zone.rb +38 -16
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +26 -16
- data/lib/rubocop/cop/rails/validation.rb +30 -2
- data/lib/rubocop/cop/security/open.rb +48 -0
- data/lib/rubocop/cop/style/and_or.rb +1 -0
- data/lib/rubocop/cop/style/ascii_comments.rb +3 -1
- data/lib/rubocop/cop/style/attr.rb +2 -0
- data/lib/rubocop/cop/style/block_comments.rb +3 -1
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +2 -5
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
- data/lib/rubocop/cop/style/class_vars.rb +23 -0
- data/lib/rubocop/cop/style/colon_method_call.rb +1 -2
- data/lib/rubocop/cop/style/comment_annotation.rb +6 -4
- data/lib/rubocop/cop/style/commented_keyword.rb +3 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +1 -1
- data/lib/rubocop/cop/style/copyright.rb +3 -1
- data/lib/rubocop/cop/style/each_with_object.rb +15 -1
- data/lib/rubocop/cop/style/empty_block_parameter.rb +1 -0
- data/lib/rubocop/cop/style/empty_case_condition.rb +2 -0
- data/lib/rubocop/cop/style/empty_else.rb +9 -5
- data/lib/rubocop/cop/style/empty_lambda_parameter.rb +1 -0
- data/lib/rubocop/cop/style/empty_line_after_guard_clause.rb +80 -0
- data/lib/rubocop/cop/style/empty_literal.rb +1 -0
- data/lib/rubocop/cop/style/encoding.rb +2 -0
- data/lib/rubocop/cop/style/expand_path_arguments.rb +194 -0
- data/lib/rubocop/cop/style/for.rb +33 -0
- data/lib/rubocop/cop/style/format_string.rb +1 -1
- data/lib/rubocop/cop/style/format_string_token.rb +4 -5
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +2 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -1
- data/lib/rubocop/cop/style/inline_comment.rb +1 -1
- data/lib/rubocop/cop/style/lambda.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +2 -0
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +2 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -0
- data/lib/rubocop/cop/style/missing_else.rb +72 -7
- data/lib/rubocop/cop/style/mixin_usage.rb +3 -5
- data/lib/rubocop/cop/style/module_function.rb +10 -0
- data/lib/rubocop/cop/style/multiline_block_chain.rb +2 -0
- data/lib/rubocop/cop/style/multiline_if_then.rb +1 -0
- data/lib/rubocop/cop/style/nested_modifier.rb +2 -0
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +2 -0
- data/lib/rubocop/cop/style/next.rb +1 -0
- data/lib/rubocop/cop/style/not.rb +2 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +2 -2
- data/lib/rubocop/cop/style/redundant_exception.rb +8 -3
- data/lib/rubocop/cop/style/redundant_return.rb +37 -3
- data/lib/rubocop/cop/style/redundant_self.rb +1 -1
- data/lib/rubocop/cop/style/rescue_standard_error.rb +1 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +74 -32
- data/lib/rubocop/cop/style/semicolon.rb +3 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +14 -23
- data/lib/rubocop/cop/style/stderr_puts.rb +2 -0
- data/lib/rubocop/cop/style/string_hash_keys.rb +12 -0
- data/lib/rubocop/cop/style/string_literals.rb +1 -1
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/symbol_array.rb +29 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +2 -0
- data/lib/rubocop/cop/style/trailing_body_on_class.rb +43 -0
- data/lib/rubocop/cop/style/trailing_body_on_method_definition.rb +7 -54
- data/lib/rubocop/cop/style/trailing_body_on_module.rb +43 -0
- data/lib/rubocop/cop/style/{trailing_comma_in_literal.rb → trailing_comma_in_array_literal.rb} +2 -20
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +56 -0
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +17 -20
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +1 -0
- data/lib/rubocop/cop/style/unless_else.rb +2 -0
- data/lib/rubocop/cop/style/word_array.rb +0 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -0
- data/lib/rubocop/cop/team.rb +5 -5
- data/lib/rubocop/cop/util.rb +23 -188
- data/lib/rubocop/cop/variable_force.rb +1 -1
- data/lib/rubocop/file_finder.rb +45 -0
- data/lib/rubocop/formatter/disabled_config_formatter.rb +23 -14
- data/lib/rubocop/formatter/fuubar_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +12 -5
- data/lib/rubocop/formatter/json_formatter.rb +1 -1
- data/lib/rubocop/node_pattern.rb +8 -5
- data/lib/rubocop/options.rb +40 -33
- data/lib/rubocop/path_util.rb +5 -8
- data/lib/rubocop/processed_source.rb +53 -0
- data/lib/rubocop/remote_config.rb +1 -1
- data/lib/rubocop/result_cache.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +0 -4
- data/lib/rubocop/rspec/host_environment_simulation_helper.rb +0 -4
- data/lib/rubocop/rspec/shared_contexts.rb +3 -1
- data/lib/rubocop/rspec/shared_examples.rb +23 -25
- data/lib/rubocop/rspec/support.rb +5 -0
- data/lib/rubocop/runner.rb +3 -2
- data/lib/rubocop/string_util.rb +10 -9
- data/lib/rubocop/target_finder.rb +4 -1
- data/lib/rubocop/token.rb +26 -16
- data/lib/rubocop/version.rb +6 -4
- metadata +31 -17
- data/lib/rubocop/cop/performance/hash_each_methods.rb +0 -129
| @@ -7,14 +7,6 @@ module RuboCop | |
| 7 7 | 
             
                # available to all `sym` nodes within RuboCop.
         | 
| 8 8 | 
             
                class SymbolNode < Node
         | 
| 9 9 | 
             
                  include BasicLiteralNode
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                  # Custom destructuring method. This can be used to normalize
         | 
| 12 | 
            -
                  # destructuring for different variations of the node.
         | 
| 13 | 
            -
                  #
         | 
| 14 | 
            -
                  # @return [Array] the different parts of the `sym` node
         | 
| 15 | 
            -
                  def node_parts
         | 
| 16 | 
            -
                    to_a
         | 
| 17 | 
            -
                  end
         | 
| 18 10 | 
             
                end
         | 
| 19 11 | 
             
              end
         | 
| 20 12 | 
             
            end
         | 
| @@ -30,14 +30,6 @@ module RuboCop | |
| 30 30 | 
             
                  def do?
         | 
| 31 31 | 
             
                    loc.begin && loc.begin.is?('do')
         | 
| 32 32 | 
             
                  end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                  # Custom destructuring method. This can be used to normalize
         | 
| 35 | 
            -
                  # destructuring for different variations of the node.
         | 
| 36 | 
            -
                  #
         | 
| 37 | 
            -
                  # @return [Array<Node>] the different parts of the `until` statement
         | 
| 38 | 
            -
                  def node_parts
         | 
| 39 | 
            -
                    to_a
         | 
| 40 | 
            -
                  end
         | 
| 41 33 | 
             
                end
         | 
| 42 34 | 
             
              end
         | 
| 43 35 | 
             
            end
         | 
| @@ -48,14 +48,6 @@ module RuboCop | |
| 48 48 | 
             
                  def body
         | 
| 49 49 | 
             
                    node_parts[-1]
         | 
| 50 50 | 
             
                  end
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                  # Custom destructuring method. This can be used to normalize
         | 
| 53 | 
            -
                  # destructuring for different variations of the node.
         | 
| 54 | 
            -
                  #
         | 
| 55 | 
            -
                  # @return [Array<Node>] the different parts of the `until` statement
         | 
| 56 | 
            -
                  def node_parts
         | 
| 57 | 
            -
                    to_a
         | 
| 58 | 
            -
                  end
         | 
| 59 51 | 
             
                end
         | 
| 60 52 | 
             
              end
         | 
| 61 53 | 
             
            end
         | 
| @@ -30,14 +30,6 @@ module RuboCop | |
| 30 30 | 
             
                  def do?
         | 
| 31 31 | 
             
                    loc.begin && loc.begin.is?('do')
         | 
| 32 32 | 
             
                  end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                  # Custom destructuring method. This can be used to normalize
         | 
| 35 | 
            -
                  # destructuring for different variations of the node.
         | 
| 36 | 
            -
                  #
         | 
| 37 | 
            -
                  # @return [Array<Node>] the different parts of the `while` statement
         | 
| 38 | 
            -
                  def node_parts
         | 
| 39 | 
            -
                    to_a
         | 
| 40 | 
            -
                  end
         | 
| 41 33 | 
             
                end
         | 
| 42 34 | 
             
              end
         | 
| 43 35 | 
             
            end
         | 
    
        data/lib/rubocop/cli.rb
    CHANGED
    
    | @@ -10,6 +10,9 @@ module RuboCop | |
| 10 10 | 
             
                SKIPPED_PHASE_1 = 'Phase 1 of 2: run Metrics/LineLength cop (skipped ' \
         | 
| 11 11 | 
             
                                  'because the default Metrics/LineLength:Max is ' \
         | 
| 12 12 | 
             
                                  'overridden)'.freeze
         | 
| 13 | 
            +
                STATUS_SUCCESS  = 0
         | 
| 14 | 
            +
                STATUS_OFFENSES = 1
         | 
| 15 | 
            +
                STATUS_ERROR    = 2
         | 
| 13 16 |  | 
| 14 17 | 
             
                class Finished < RuntimeError; end
         | 
| 15 18 |  | 
| @@ -29,27 +32,30 @@ module RuboCop | |
| 29 32 | 
             
                # @param args [Array<String>] command line arguments
         | 
| 30 33 | 
             
                # @return [Integer] UNIX exit code
         | 
| 31 34 | 
             
                #
         | 
| 32 | 
            -
                # rubocop:disable Metrics/MethodLength
         | 
| 35 | 
            +
                # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
         | 
| 33 36 | 
             
                def run(args = ARGV)
         | 
| 34 37 | 
             
                  @options, paths = Options.new.parse(args)
         | 
| 35 38 | 
             
                  validate_options_vs_config
         | 
| 36 39 | 
             
                  act_on_options
         | 
| 37 40 | 
             
                  apply_default_formatter
         | 
| 38 41 | 
             
                  execute_runners(paths)
         | 
| 42 | 
            +
                rescue RuboCop::ConfigNotFoundError => e
         | 
| 43 | 
            +
                  warn e.message
         | 
| 44 | 
            +
                  e.status
         | 
| 39 45 | 
             
                rescue RuboCop::Error => e
         | 
| 40 46 | 
             
                  warn Rainbow("Error: #{e.message}").red
         | 
| 41 | 
            -
                   | 
| 47 | 
            +
                  STATUS_ERROR
         | 
| 42 48 | 
             
                rescue Finished
         | 
| 43 | 
            -
                   | 
| 49 | 
            +
                  STATUS_SUCCESS
         | 
| 44 50 | 
             
                rescue IncorrectCopNameError => e
         | 
| 45 51 | 
             
                  warn e.message
         | 
| 46 | 
            -
                   | 
| 52 | 
            +
                  STATUS_ERROR
         | 
| 47 53 | 
             
                rescue StandardError, SyntaxError, LoadError => e
         | 
| 48 54 | 
             
                  warn e.message
         | 
| 49 55 | 
             
                  warn e.backtrace
         | 
| 50 | 
            -
                   | 
| 56 | 
            +
                  STATUS_ERROR
         | 
| 51 57 | 
             
                end
         | 
| 52 | 
            -
                # rubocop:enable Metrics/MethodLength
         | 
| 58 | 
            +
                # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
         | 
| 53 59 |  | 
| 54 60 | 
             
                def trap_interrupt(runner)
         | 
| 55 61 | 
             
                  Signal.trap('INT') do
         | 
| @@ -152,7 +158,11 @@ module RuboCop | |
| 152 158 | 
             
                  display_error_summary(runner.errors)
         | 
| 153 159 | 
             
                  maybe_print_corrected_source
         | 
| 154 160 |  | 
| 155 | 
            -
                  all_passed && !runner.aborting? && runner.errors.empty? | 
| 161 | 
            +
                  if all_passed && !runner.aborting? && runner.errors.empty?
         | 
| 162 | 
            +
                    STATUS_SUCCESS
         | 
| 163 | 
            +
                  else
         | 
| 164 | 
            +
                    STATUS_OFFENSES
         | 
| 165 | 
            +
                  end
         | 
| 156 166 | 
             
                end
         | 
| 157 167 |  | 
| 158 168 | 
             
                def handle_exiting_options
         | 
| @@ -4,7 +4,7 @@ module RuboCop | |
| 4 4 | 
             
              # This class parses the special `rubocop:disable` comments in a source
         | 
| 5 5 | 
             
              # and provides a way to check if each cop is enabled at arbitrary line.
         | 
| 6 6 | 
             
              class CommentConfig
         | 
| 7 | 
            -
                UNNEEDED_DISABLE = 'Lint/ | 
| 7 | 
            +
                UNNEEDED_DISABLE = 'Lint/UnneededCopDisableDirective'.freeze
         | 
| 8 8 |  | 
| 9 9 | 
             
                COP_NAME_PATTERN = '([A-Z]\w+/)?(?:[A-Z]\w+)'.freeze
         | 
| 10 10 | 
             
                COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}".freeze
         | 
| @@ -34,8 +34,29 @@ module RuboCop | |
| 34 34 | 
             
                  @cop_disabled_line_ranges ||= analyze
         | 
| 35 35 | 
             
                end
         | 
| 36 36 |  | 
| 37 | 
            +
                def extra_enabled_comments
         | 
| 38 | 
            +
                  extra_enabled_comments_with_names([], {})
         | 
| 39 | 
            +
                end
         | 
| 40 | 
            +
             | 
| 37 41 | 
             
                private
         | 
| 38 42 |  | 
| 43 | 
            +
                def extra_enabled_comments_with_names(extras, names)
         | 
| 44 | 
            +
                  each_directive do |comment, cop_names, disabled|
         | 
| 45 | 
            +
                    next unless comment_only_line?(comment.loc.expression.line)
         | 
| 46 | 
            +
                    cop_names.each do |name|
         | 
| 47 | 
            +
                      names[name] ||= 0
         | 
| 48 | 
            +
                      if disabled
         | 
| 49 | 
            +
                        names[name] += 1
         | 
| 50 | 
            +
                      elsif names[name] > 0
         | 
| 51 | 
            +
                        names[name] -= 1
         | 
| 52 | 
            +
                      else
         | 
| 53 | 
            +
                        extras << [comment, name]
         | 
| 54 | 
            +
                      end
         | 
| 55 | 
            +
                    end
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                  extras
         | 
| 58 | 
            +
                end
         | 
| 59 | 
            +
             | 
| 39 60 | 
             
                def analyze
         | 
| 40 61 | 
             
                  analyses = Hash.new { |hash, key| hash[key] = CopAnalysis.new([], nil) }
         | 
| 41 62 |  | 
| @@ -106,7 +127,7 @@ module RuboCop | |
| 106 127 | 
             
                def each_directive
         | 
| 107 128 | 
             
                  return if processed_source.comments.nil?
         | 
| 108 129 |  | 
| 109 | 
            -
                  processed_source. | 
| 130 | 
            +
                  processed_source.each_comment do |comment|
         | 
| 110 131 | 
             
                    directive = directive_parts(comment)
         | 
| 111 132 | 
             
                    next unless directive
         | 
| 112 133 |  | 
| @@ -129,7 +150,7 @@ module RuboCop | |
| 129 150 | 
             
                end
         | 
| 130 151 |  | 
| 131 152 | 
             
                def qualified_cop_name(cop_name)
         | 
| 132 | 
            -
                  Cop::Cop.qualified_cop_name(cop_name.strip, processed_source. | 
| 153 | 
            +
                  Cop::Cop.qualified_cop_name(cop_name.strip, processed_source.file_path)
         | 
| 133 154 | 
             
                end
         | 
| 134 155 |  | 
| 135 156 | 
             
                def all_cop_names
         | 
    
        data/lib/rubocop/config.rb
    CHANGED
    
    | @@ -12,6 +12,7 @@ module RuboCop | |
| 12 12 | 
             
              # rubocop:disable Metrics/ClassLength
         | 
| 13 13 | 
             
              class Config
         | 
| 14 14 | 
             
                include PathUtil
         | 
| 15 | 
            +
                include FileFinder
         | 
| 15 16 |  | 
| 16 17 | 
             
                COMMON_PARAMS = %w[Exclude Include Severity
         | 
| 17 18 | 
             
                                   AutoCorrect StyleGuide Details].freeze
         | 
| @@ -24,8 +25,13 @@ module RuboCop | |
| 24 25 | 
             
                OBSOLETE_COPS = {
         | 
| 25 26 | 
             
                  'Style/TrailingComma' =>
         | 
| 26 27 | 
             
                    'The `Style/TrailingComma` cop no longer exists. Please use ' \
         | 
| 27 | 
            -
                    '`Style/ | 
| 28 | 
            -
                    '`Style/ | 
| 28 | 
            +
                    '`Style/TrailingCommaInArguments`, ' \
         | 
| 29 | 
            +
                    '`Style/TrailingCommaInArrayLiteral`, and/or ' \
         | 
| 30 | 
            +
                    '`Style/TrailingCommaInHashLiteral` instead.',
         | 
| 31 | 
            +
                  'Style/TrailingCommaInLiteral' =>
         | 
| 32 | 
            +
                    'The `Style/TrailingCommaInLiteral` cop no longer exists. Please use ' \
         | 
| 33 | 
            +
                    '`Style/TrailingCommaInArrayLiteral` and/or ' \
         | 
| 34 | 
            +
                    '`Style/TrailingCommaInHashLiteral` instead.',
         | 
| 29 35 | 
             
                  'Rails/DefaultScope' =>
         | 
| 30 36 | 
             
                    'The `Rails/DefaultScope` cop no longer exists.',
         | 
| 31 37 | 
             
                  'Lint/InvalidCharacterLiteral' =>
         | 
| @@ -89,7 +95,20 @@ module RuboCop | |
| 89 95 | 
             
                      '`Naming/VariableName`.',
         | 
| 90 96 | 
             
                  'Style/VariableNumber' =>
         | 
| 91 97 | 
             
                    'The `Style/VariableNumber` cop has been renamed to ' \
         | 
| 92 | 
            -
                      '`Naming/VariableNumber`.'
         | 
| 98 | 
            +
                      '`Naming/VariableNumber`.',
         | 
| 99 | 
            +
                  'Lint/BlockAlignment' =>
         | 
| 100 | 
            +
                    'The `Lint/BlockAlignment` cop has been renamed to ' \
         | 
| 101 | 
            +
                      '`Layout/BlockAlignment`.',
         | 
| 102 | 
            +
                  'Lint/EndAlignment' =>
         | 
| 103 | 
            +
                    'The `Lint/EndAlignment` cop has been renamed to ' \
         | 
| 104 | 
            +
                      '`Layout/EndAlignment`.',
         | 
| 105 | 
            +
                  'Lint/DefEndAlignment' =>
         | 
| 106 | 
            +
                    'The `Lint/DefEndAlignment` cop has been renamed to ' \
         | 
| 107 | 
            +
                      '`Layout/DefEndAlignment`.',
         | 
| 108 | 
            +
                  'Performance/HashEachMethods' =>
         | 
| 109 | 
            +
                    'The `Performance/HashEachMethods` cop has been removed ' \
         | 
| 110 | 
            +
                      'since it no longer provides performance benefits in ' \
         | 
| 111 | 
            +
                      'modern rubies.'
         | 
| 93 112 | 
             
                }.freeze
         | 
| 94 113 |  | 
| 95 114 | 
             
                OBSOLETE_PARAMETERS = [
         | 
| @@ -157,18 +176,36 @@ module RuboCop | |
| 157 176 | 
             
                    alternative: '`AlignWith` has been renamed to ' \
         | 
| 158 177 | 
             
                                 '`EnforcedStyleAlignWith`'
         | 
| 159 178 | 
             
                  },
         | 
| 179 | 
            +
                  {
         | 
| 180 | 
            +
                    cop: 'Layout/BlockAlignment',
         | 
| 181 | 
            +
                    parameter: 'AlignWith',
         | 
| 182 | 
            +
                    alternative: '`AlignWith` has been renamed to ' \
         | 
| 183 | 
            +
                                 '`EnforcedStyleAlignWith`'
         | 
| 184 | 
            +
                  },
         | 
| 160 185 | 
             
                  {
         | 
| 161 186 | 
             
                    cop: 'Lint/EndAlignment',
         | 
| 162 187 | 
             
                    parameter: 'AlignWith',
         | 
| 163 188 | 
             
                    alternative: '`AlignWith` has been renamed to ' \
         | 
| 164 189 | 
             
                                 '`EnforcedStyleAlignWith`'
         | 
| 165 190 | 
             
                  },
         | 
| 191 | 
            +
                  {
         | 
| 192 | 
            +
                    cop: 'Layout/EndAlignment',
         | 
| 193 | 
            +
                    parameter: 'AlignWith',
         | 
| 194 | 
            +
                    alternative: '`AlignWith` has been renamed to ' \
         | 
| 195 | 
            +
                                 '`EnforcedStyleAlignWith`'
         | 
| 196 | 
            +
                  },
         | 
| 166 197 | 
             
                  {
         | 
| 167 198 | 
             
                    cop: 'Lint/DefEndAlignment',
         | 
| 168 199 | 
             
                    parameter: 'AlignWith',
         | 
| 169 200 | 
             
                    alternative: '`AlignWith` has been renamed to ' \
         | 
| 170 201 | 
             
                                 '`EnforcedStyleAlignWith`'
         | 
| 171 202 | 
             
                  },
         | 
| 203 | 
            +
                  {
         | 
| 204 | 
            +
                    cop: 'Layout/DefEndAlignment',
         | 
| 205 | 
            +
                    parameter: 'AlignWith',
         | 
| 206 | 
            +
                    alternative: '`AlignWith` has been renamed to ' \
         | 
| 207 | 
            +
                                 '`EnforcedStyleAlignWith`'
         | 
| 208 | 
            +
                  },
         | 
| 172 209 | 
             
                  {
         | 
| 173 210 | 
             
                    cop: 'Rails/UniqBeforePluck',
         | 
| 174 211 | 
             
                    parameter: 'EnforcedMode',
         | 
| @@ -395,7 +432,13 @@ module RuboCop | |
| 395 432 |  | 
| 396 433 | 
             
                def target_rails_version
         | 
| 397 434 | 
             
                  @target_rails_version ||=
         | 
| 398 | 
            -
                    for_all_cops | 
| 435 | 
            +
                    if for_all_cops['TargetRailsVersion']
         | 
| 436 | 
            +
                      for_all_cops['TargetRailsVersion'].to_f
         | 
| 437 | 
            +
                    elsif target_rails_version_from_bundler_lock_file
         | 
| 438 | 
            +
                      target_rails_version_from_bundler_lock_file
         | 
| 439 | 
            +
                    else
         | 
| 440 | 
            +
                      DEFAULT_RAILS_VERSION
         | 
| 441 | 
            +
                    end
         | 
| 399 442 | 
             
                end
         | 
| 400 443 |  | 
| 401 444 | 
             
                private
         | 
| @@ -521,8 +564,7 @@ module RuboCop | |
| 521 564 |  | 
| 522 565 | 
             
                def ruby_version_file
         | 
| 523 566 | 
             
                  @ruby_version_file ||=
         | 
| 524 | 
            -
                     | 
| 525 | 
            -
                                               base_dir_for_path_parameters)
         | 
| 567 | 
            +
                    find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters)
         | 
| 526 568 | 
             
                end
         | 
| 527 569 |  | 
| 528 570 | 
             
                def target_ruby_version_from_version_file
         | 
| @@ -535,6 +577,33 @@ module RuboCop | |
| 535 577 | 
             
                    end
         | 
| 536 578 | 
             
                end
         | 
| 537 579 |  | 
| 580 | 
            +
                def target_rails_version_from_bundler_lock_file
         | 
| 581 | 
            +
                  @target_rails_version_from_bundler_lock_file ||=
         | 
| 582 | 
            +
                    read_rails_version_from_bundler_lock_file
         | 
| 583 | 
            +
                end
         | 
| 584 | 
            +
             | 
| 585 | 
            +
                def read_rails_version_from_bundler_lock_file
         | 
| 586 | 
            +
                  lock_file_path = bundler_lock_file_path
         | 
| 587 | 
            +
                  return nil unless lock_file_path
         | 
| 588 | 
            +
             | 
| 589 | 
            +
                  File.foreach(lock_file_path) do |line|
         | 
| 590 | 
            +
                    # If rails is in the Gemfile, the lock file should have a line like:
         | 
| 591 | 
            +
                    #         rails (X.X.X)
         | 
| 592 | 
            +
                    result = line.match(/^\s+rails\s+\((\d\.\d\.\d)/)
         | 
| 593 | 
            +
                    return result.captures.first.to_f if result
         | 
| 594 | 
            +
                  end
         | 
| 595 | 
            +
                end
         | 
| 596 | 
            +
             | 
| 597 | 
            +
                def bundler_lock_file_path
         | 
| 598 | 
            +
                  return nil unless loaded_path
         | 
| 599 | 
            +
                  base_path = base_dir_for_path_parameters
         | 
| 600 | 
            +
                  ['gems.locked', 'Gemfile.lock'].each do |file_name|
         | 
| 601 | 
            +
                    path = File.join(base_path, file_name)
         | 
| 602 | 
            +
                    return path if File.file?(path)
         | 
| 603 | 
            +
                  end
         | 
| 604 | 
            +
                  nil
         | 
| 605 | 
            +
                end
         | 
| 606 | 
            +
             | 
| 538 607 | 
             
                def reject_mutually_exclusive_defaults
         | 
| 539 608 | 
             
                  disabled_by_default = for_all_cops['DisabledByDefault']
         | 
| 540 609 | 
             
                  enabled_by_default = for_all_cops['EnabledByDefault']
         | 
| @@ -4,6 +4,10 @@ require 'yaml' | |
| 4 4 | 
             
            require 'pathname'
         | 
| 5 5 |  | 
| 6 6 | 
             
            module RuboCop
         | 
| 7 | 
            +
              # Raised when a RuboCop configuration file is not found.
         | 
| 8 | 
            +
              class ConfigNotFoundError < Error
         | 
| 9 | 
            +
              end
         | 
| 10 | 
            +
             | 
| 7 11 | 
             
              # This class represents the configuration of the RuboCop application
         | 
| 8 12 | 
             
              # and all its cops. A Config is associated with a YAML configuration
         | 
| 9 13 | 
             
              # file from which it was read. Several different Configs can be used
         | 
| @@ -16,8 +20,9 @@ module RuboCop | |
| 16 20 | 
             
                AUTO_GENERATED_FILE = '.rubocop_todo.yml'.freeze
         | 
| 17 21 |  | 
| 18 22 | 
             
                class << self
         | 
| 23 | 
            +
                  include FileFinder
         | 
| 24 | 
            +
             | 
| 19 25 | 
             
                  attr_accessor :debug, :auto_gen_config, :ignore_parent_exclusion
         | 
| 20 | 
            -
                  attr_writer :root_level # The upwards search is stopped at this level.
         | 
| 21 26 | 
             
                  attr_writer :default_configuration
         | 
| 22 27 |  | 
| 23 28 | 
             
                  alias debug? debug
         | 
| @@ -25,7 +30,8 @@ module RuboCop | |
| 25 30 | 
             
                  alias ignore_parent_exclusion? ignore_parent_exclusion
         | 
| 26 31 |  | 
| 27 32 | 
             
                  def clear_options
         | 
| 28 | 
            -
                    @debug = @auto_gen_config =  | 
| 33 | 
            +
                    @debug = @auto_gen_config = nil
         | 
| 34 | 
            +
                    FileFinder.root_level = nil
         | 
| 29 35 | 
             
                  end
         | 
| 30 36 |  | 
| 31 37 | 
             
                  def load_file(file)
         | 
| @@ -44,11 +50,11 @@ module RuboCop | |
| 44 50 | 
             
                    resolver.resolve_inheritance(path, hash, file)
         | 
| 45 51 |  | 
| 46 52 | 
             
                    hash.delete('inherit_from')
         | 
| 53 | 
            +
                    hash.delete('inherit_mode')
         | 
| 47 54 |  | 
| 48 55 | 
             
                    Config.create(hash, path)
         | 
| 49 56 | 
             
                  end
         | 
| 50 57 |  | 
| 51 | 
            -
                  # rubocop:disable Performance/HashEachMethods
         | 
| 52 58 | 
             
                  def add_missing_namespaces(path, hash)
         | 
| 53 59 | 
             
                    hash.keys.each do |key|
         | 
| 54 60 | 
             
                      q = Cop::Cop.qualified_cop_name(key, path)
         | 
| @@ -57,7 +63,6 @@ module RuboCop | |
| 57 63 | 
             
                      hash[q] = hash.delete(key)
         | 
| 58 64 | 
             
                    end
         | 
| 59 65 | 
             
                  end
         | 
| 60 | 
            -
                  # rubocop:enable Performance/HashEachMethods
         | 
| 61 66 |  | 
| 62 67 | 
             
                  # Return a recursive merge of two hashes. That is, a normal hash merge,
         | 
| 63 68 | 
             
                  # with the addition that any value that is a hash, and occurs in both
         | 
| @@ -72,7 +77,7 @@ module RuboCop | |
| 72 77 | 
             
                  # user's home directory is checked. If there's no .rubocop.yml
         | 
| 73 78 | 
             
                  # there either, the path to the default file is returned.
         | 
| 74 79 | 
             
                  def configuration_file_for(target_dir)
         | 
| 75 | 
            -
                     | 
| 80 | 
            +
                    find_file_upwards(DOTFILE, target_dir, use_home: true) || DEFAULT_FILE
         | 
| 76 81 | 
             
                  end
         | 
| 77 82 |  | 
| 78 83 | 
             
                  def configuration_from_file(config_file)
         | 
| @@ -88,8 +93,10 @@ module RuboCop | |
| 88 93 | 
             
                  end
         | 
| 89 94 |  | 
| 90 95 | 
             
                  def add_excludes_from_files(config, config_file)
         | 
| 91 | 
            -
                    found_files =  | 
| 92 | 
            -
                    return  | 
| 96 | 
            +
                    found_files = find_files_upwards(DOTFILE, config_file, use_home: true)
         | 
| 97 | 
            +
                    return if found_files.empty?
         | 
| 98 | 
            +
                    return if PathUtil.relative_path(found_files.last) ==
         | 
| 99 | 
            +
                              PathUtil.relative_path(config_file)
         | 
| 93 100 | 
             
                    print 'AllCops/Exclude ' if debug?
         | 
| 94 101 | 
             
                    config.add_excludes_from_higher_level(load_file(found_files.last))
         | 
| 95 102 | 
             
                  end
         | 
| @@ -138,8 +145,8 @@ module RuboCop | |
| 138 145 |  | 
| 139 146 | 
             
                  def write_dotfile(file_string, rubocop_yml_contents)
         | 
| 140 147 | 
             
                    File.open(DOTFILE, 'w') do |f|
         | 
| 141 | 
            -
                      f.write "inherit_from:#{file_string}\n | 
| 142 | 
            -
                      f.write rubocop_yml_contents if rubocop_yml_contents
         | 
| 148 | 
            +
                      f.write "inherit_from:#{file_string}\n"
         | 
| 149 | 
            +
                      f.write "\n#{rubocop_yml_contents}" if rubocop_yml_contents
         | 
| 143 150 | 
             
                    end
         | 
| 144 151 | 
             
                  end
         | 
| 145 152 |  | 
| @@ -166,8 +173,8 @@ module RuboCop | |
| 166 173 | 
             
                  def read_file(absolute_path)
         | 
| 167 174 | 
             
                    IO.read(absolute_path, encoding: Encoding::UTF_8)
         | 
| 168 175 | 
             
                  rescue Errno::ENOENT
         | 
| 169 | 
            -
                     | 
| 170 | 
            -
             | 
| 176 | 
            +
                    raise ConfigNotFoundError,
         | 
| 177 | 
            +
                          "Configuration file not found: #{absolute_path}"
         | 
| 171 178 | 
             
                  end
         | 
| 172 179 |  | 
| 173 180 | 
             
                  def yaml_safe_load(yaml_code, filename)
         | 
| @@ -182,23 +189,6 @@ module RuboCop | |
| 182 189 | 
             
                      YAML.load(yaml_code, filename) # rubocop:disable Security/YAMLLoad
         | 
| 183 190 | 
             
                    end
         | 
| 184 191 | 
             
                  end
         | 
| 185 | 
            -
             | 
| 186 | 
            -
                  def config_files_in_path(target)
         | 
| 187 | 
            -
                    possible_config_files = dirs_to_search(target).map do |dir|
         | 
| 188 | 
            -
                      File.join(dir, DOTFILE)
         | 
| 189 | 
            -
                    end
         | 
| 190 | 
            -
                    possible_config_files.select { |config_file| File.exist?(config_file) }
         | 
| 191 | 
            -
                  end
         | 
| 192 | 
            -
             | 
| 193 | 
            -
                  def dirs_to_search(target_dir)
         | 
| 194 | 
            -
                    dirs_to_search = []
         | 
| 195 | 
            -
                    Pathname.new(File.expand_path(target_dir)).ascend do |dir_pathname|
         | 
| 196 | 
            -
                      break if dir_pathname.to_s == @root_level
         | 
| 197 | 
            -
                      dirs_to_search << dir_pathname.to_s
         | 
| 198 | 
            -
                    end
         | 
| 199 | 
            -
                    dirs_to_search << Dir.home if ENV.key? 'HOME'
         | 
| 200 | 
            -
                    dirs_to_search
         | 
| 201 | 
            -
                  end
         | 
| 202 192 | 
             
                end
         | 
| 203 193 |  | 
| 204 194 | 
             
                # Initializing class ivars
         | 
| @@ -18,10 +18,18 @@ module RuboCop | |
| 18 18 | 
             
                end
         | 
| 19 19 |  | 
| 20 20 | 
             
                def resolve_inheritance(path, hash, file)
         | 
| 21 | 
            -
                   | 
| 22 | 
            -
             | 
| 21 | 
            +
                  inherited_files = Array(hash['inherit_from'])
         | 
| 22 | 
            +
                  base_configs(path, inherited_files, file)
         | 
| 23 | 
            +
                    .reverse.each_with_index do |base_config, index|
         | 
| 23 24 | 
             
                    base_config.each do |k, v|
         | 
| 24 | 
            -
                       | 
| 25 | 
            +
                      next unless v.is_a?(Hash)
         | 
| 26 | 
            +
                      if hash.key?(k)
         | 
| 27 | 
            +
                        v = merge(v, hash[k],
         | 
| 28 | 
            +
                                  cop_name: k, file: file,
         | 
| 29 | 
            +
                                  inherited_file: inherited_files[index],
         | 
| 30 | 
            +
                                  inherit_mode: determine_inherit_mode(hash, k))
         | 
| 31 | 
            +
                      end
         | 
| 32 | 
            +
                      hash[k] = v
         | 
| 25 33 | 
             
                    end
         | 
| 26 34 | 
             
                  end
         | 
| 27 35 | 
             
                end
         | 
| @@ -70,18 +78,58 @@ module RuboCop | |
| 70 78 | 
             
                # Return a recursive merge of two hashes. That is, a normal hash merge,
         | 
| 71 79 | 
             
                # with the addition that any value that is a hash, and occurs in both
         | 
| 72 80 | 
             
                # arguments, will also be merged. And so on.
         | 
| 73 | 
            -
                def merge(base_hash, derived_hash)
         | 
| 81 | 
            +
                def merge(base_hash, derived_hash, **opts)
         | 
| 74 82 | 
             
                  result = base_hash.merge(derived_hash)
         | 
| 75 83 | 
             
                  keys_appearing_in_both = base_hash.keys & derived_hash.keys
         | 
| 76 84 | 
             
                  keys_appearing_in_both.each do |key|
         | 
| 77 | 
            -
                     | 
| 78 | 
            -
             | 
| 85 | 
            +
                    if base_hash[key].is_a?(Hash)
         | 
| 86 | 
            +
                      result[key] = merge(base_hash[key], derived_hash[key])
         | 
| 87 | 
            +
                    elsif should_union?(base_hash, key, opts[:inherit_mode])
         | 
| 88 | 
            +
                      result[key] = base_hash[key] | derived_hash[key]
         | 
| 89 | 
            +
                    else
         | 
| 90 | 
            +
                      warn_on_duplicate_setting(base_hash, derived_hash, key, opts)
         | 
| 91 | 
            +
                    end
         | 
| 79 92 | 
             
                  end
         | 
| 80 93 | 
             
                  result
         | 
| 81 94 | 
             
                end
         | 
| 82 95 |  | 
| 83 96 | 
             
                private
         | 
| 84 97 |  | 
| 98 | 
            +
                def duplicate_setting?(base_hash, derived_hash, key, inherited_file)
         | 
| 99 | 
            +
                  return false if inherited_file.nil? # Not inheritance resolving merge
         | 
| 100 | 
            +
                  return false if inherited_file.start_with?('..') # Legitimate override
         | 
| 101 | 
            +
                  return false if base_hash[key] == derived_hash[key] # Same value
         | 
| 102 | 
            +
                  return false if remote_file?(inherited_file) # Can't change
         | 
| 103 | 
            +
                  Gem.path.none? { |dir| inherited_file.start_with?(dir) } # Can change?
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                def warn_on_duplicate_setting(base_hash, derived_hash, key, **opts)
         | 
| 107 | 
            +
                  return unless duplicate_setting?(base_hash, derived_hash,
         | 
| 108 | 
            +
                                                   key, opts[:inherited_file])
         | 
| 109 | 
            +
             | 
| 110 | 
            +
                  inherit_mode = opts[:inherit_mode]['merge'] ||
         | 
| 111 | 
            +
                                 opts[:inherit_mode]['override']
         | 
| 112 | 
            +
                  return if base_hash[key].is_a?(Array) &&
         | 
| 113 | 
            +
                            inherit_mode && inherit_mode.include?(key)
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                  warn("#{PathUtil.smart_path(opts[:file])}: " \
         | 
| 116 | 
            +
                       "#{opts[:cop_name]}:#{key} overrides " \
         | 
| 117 | 
            +
                       "the same parameter in #{opts[:inherited_file]}")
         | 
| 118 | 
            +
                end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                def determine_inherit_mode(hash, key)
         | 
| 121 | 
            +
                  cop_cfg = hash[key]
         | 
| 122 | 
            +
                  local_inherit = cop_cfg.delete('inherit_mode') if cop_cfg.is_a?(Hash)
         | 
| 123 | 
            +
                  local_inherit || hash['inherit_mode'] || {}
         | 
| 124 | 
            +
                end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                def should_union?(base_hash, key, inherit_mode)
         | 
| 127 | 
            +
                  base_hash[key].is_a?(Array) &&
         | 
| 128 | 
            +
                    inherit_mode &&
         | 
| 129 | 
            +
                    inherit_mode['merge'] &&
         | 
| 130 | 
            +
                    inherit_mode['merge'].include?(key)
         | 
| 131 | 
            +
                end
         | 
| 132 | 
            +
             | 
| 85 133 | 
             
                def base_configs(path, inherit_from, file)
         | 
| 86 134 | 
             
                  configs = Array(inherit_from).compact.map do |f|
         | 
| 87 135 | 
             
                    ConfigLoader.load_file(inherited_file(path, f, file))
         | 
| @@ -91,8 +139,7 @@ module RuboCop | |
| 91 139 | 
             
                end
         | 
| 92 140 |  | 
| 93 141 | 
             
                def inherited_file(path, inherit_from, file)
         | 
| 94 | 
            -
                   | 
| 95 | 
            -
                  if inherit_from =~ /\A#{regex}\z/
         | 
| 142 | 
            +
                  if remote_file?(inherit_from)
         | 
| 96 143 | 
             
                    RemoteConfig.new(inherit_from, File.dirname(path))
         | 
| 97 144 | 
             
                  elsif file.is_a?(RemoteConfig)
         | 
| 98 145 | 
             
                    file.inherit_from_remote(inherit_from, path)
         | 
| @@ -102,6 +149,11 @@ module RuboCop | |
| 102 149 | 
             
                  end
         | 
| 103 150 | 
             
                end
         | 
| 104 151 |  | 
| 152 | 
            +
                def remote_file?(uri)
         | 
| 153 | 
            +
                  regex = URI::DEFAULT_PARSER.make_regexp(%w[http https])
         | 
| 154 | 
            +
                  uri =~ /\A#{regex}\z/
         | 
| 155 | 
            +
                end
         | 
| 156 | 
            +
             | 
| 105 157 | 
             
                def handle_disabled_by_default(config, new_default_configuration)
         | 
| 106 158 | 
             
                  department_config = config.to_hash.reject { |cop| cop.include?('/') }
         | 
| 107 159 | 
             
                  department_config.each do |dept, dept_params|
         | 
| @@ -132,7 +184,7 @@ module RuboCop | |
| 132 184 |  | 
| 133 185 | 
             
                def gem_config_path(gem_name, relative_config_path)
         | 
| 134 186 | 
             
                  spec = Gem::Specification.find_by_name(gem_name)
         | 
| 135 | 
            -
                   | 
| 187 | 
            +
                  File.join(spec.gem_dir, relative_config_path)
         | 
| 136 188 | 
             
                rescue Gem::LoadError => e
         | 
| 137 189 | 
             
                  raise Gem::LoadError,
         | 
| 138 190 | 
             
                        "Unable to find gem #{gem_name}; is the gem installed? #{e}"
         |