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}"
|