rubocop 0.78.0 → 0.82.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 +4 -4
- data/config/default.yml +158 -48
- data/lib/rubocop.rb +19 -4
- data/lib/rubocop/ast/builder.rb +45 -42
- data/lib/rubocop/ast/node.rb +12 -19
- data/lib/rubocop/ast/node/array_node.rb +13 -0
- data/lib/rubocop/ast/node/block_node.rb +5 -1
- data/lib/rubocop/ast/node/case_match_node.rb +56 -0
- data/lib/rubocop/ast/node/def_node.rb +11 -0
- data/lib/rubocop/ast/node/forward_args_node.rb +18 -0
- data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +8 -0
- data/lib/rubocop/ast/node/regexp_node.rb +2 -4
- data/lib/rubocop/ast/traversal.rb +29 -10
- data/lib/rubocop/cli.rb +10 -4
- data/lib/rubocop/cli/command/show_cops.rb +11 -4
- data/lib/rubocop/comment_config.rb +6 -1
- data/lib/rubocop/config.rb +36 -10
- data/lib/rubocop/config_loader.rb +42 -33
- data/lib/rubocop/config_loader_resolver.rb +1 -1
- data/lib/rubocop/config_obsoletion.rb +4 -1
- data/lib/rubocop/config_validator.rb +66 -92
- data/lib/rubocop/cop/autocorrect_logic.rb +6 -3
- data/lib/rubocop/cop/badge.rb +5 -5
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -1
- data/lib/rubocop/cop/corrector.rb +48 -24
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/condition_corrector.rb +1 -2
- data/lib/rubocop/cop/correctors/empty_line_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +3 -3
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/percent_literal_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/string_literal_corrector.rb +2 -2
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
- data/lib/rubocop/cop/generator.rb +3 -4
- data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/array_alignment.rb +53 -10
- data/lib/rubocop/cop/layout/block_end_newline.rb +5 -3
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/else_alignment.rb +8 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
- data/lib/rubocop/cop/layout/end_of_line.rb +2 -2
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +16 -10
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +8 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +2 -2
- data/lib/rubocop/cop/layout/{tab.rb → indentation_style.rb} +48 -6
- data/lib/rubocop/cop/layout/leading_comment_space.rb +34 -3
- data/lib/rubocop/cop/layout/line_length.rb +32 -3
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +15 -6
- data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +0 -4
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_block_parameters.rb +3 -3
- data/lib/rubocop/cop/layout/space_around_method_call_operator.rb +133 -0
- data/lib/rubocop/cop/layout/space_around_operators.rb +19 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +2 -2
- data/lib/rubocop/cop/layout/space_before_first_arg.rb +8 -0
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -2
- data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -9
- data/lib/rubocop/cop/layout/space_inside_range_literal.rb +2 -2
- data/lib/rubocop/cop/lint/boolean_symbol.rb +12 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -2
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
- data/lib/rubocop/cop/lint/inherit_exception.rb +1 -1
- data/lib/rubocop/cop/lint/interpolation_check.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/loop.rb +6 -4
- data/lib/rubocop/cop/lint/multiple_comparison.rb +1 -1
- data/lib/rubocop/cop/lint/nested_method_definition.rb +2 -2
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +2 -2
- data/lib/rubocop/cop/lint/number_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/percent_string_array.rb +2 -2
- data/lib/rubocop/cop/lint/raise_exception.rb +75 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +12 -7
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -1
- data/lib/rubocop/cop/lint/struct_new_override.rb +58 -0
- data/lib/rubocop/cop/lint/suppressed_exception.rb +12 -22
- data/lib/rubocop/cop/lint/unified_integer.rb +0 -2
- data/lib/rubocop/cop/lint/unused_method_argument.rb +32 -6
- data/lib/rubocop/cop/lint/uri_regexp.rb +4 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -0
- data/lib/rubocop/cop/migration/department_name.rb +47 -6
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +4 -0
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +6 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +7 -7
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +171 -0
- data/lib/rubocop/cop/mixin/line_length_help.rb +1 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +5 -0
- data/lib/rubocop/cop/mixin/statement_modifier.rb +4 -3
- data/lib/rubocop/cop/mixin/trailing_comma.rb +3 -10
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +2 -1
- data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +1 -1
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
- data/lib/rubocop/cop/naming/method_name.rb +30 -0
- data/lib/rubocop/cop/naming/method_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +1 -1
- data/lib/rubocop/cop/registry.rb +15 -3
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -6
- data/lib/rubocop/cop/style/alias.rb +4 -4
- data/lib/rubocop/cop/style/and_or.rb +5 -6
- data/lib/rubocop/cop/style/array_join.rb +1 -1
- data/lib/rubocop/cop/style/block_delimiters.rb +60 -1
- data/lib/rubocop/cop/style/case_equality.rb +24 -1
- data/lib/rubocop/cop/style/character_literal.rb +2 -2
- data/lib/rubocop/cop/style/collection_methods.rb +2 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +8 -8
- data/lib/rubocop/cop/style/copyright.rb +1 -1
- data/lib/rubocop/cop/style/dir.rb +1 -1
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -0
- data/lib/rubocop/cop/style/documentation.rb +43 -5
- data/lib/rubocop/cop/style/double_cop_disable_directive.rb +1 -1
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -1
- data/lib/rubocop/cop/style/each_with_object.rb +3 -3
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/end_block.rb +6 -0
- data/lib/rubocop/cop/style/even_odd.rb +1 -1
- data/lib/rubocop/cop/style/expand_path_arguments.rb +3 -3
- data/lib/rubocop/cop/style/exponential_notation.rb +119 -0
- data/lib/rubocop/cop/style/format_string.rb +2 -2
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +89 -11
- data/lib/rubocop/cop/style/hash_each_methods.rb +89 -0
- data/lib/rubocop/cop/style/hash_syntax.rb +3 -5
- data/lib/rubocop/cop/style/hash_transform_keys.rb +83 -0
- data/lib/rubocop/cop/style/hash_transform_values.rb +80 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +23 -3
- data/lib/rubocop/cop/style/inverse_methods.rb +9 -5
- data/lib/rubocop/cop/style/lambda.rb +3 -2
- data/lib/rubocop/cop/style/lambda_call.rb +2 -2
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -205
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +169 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +54 -0
- data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
- data/lib/rubocop/cop/style/module_function.rb +58 -12
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +1 -1
- data/lib/rubocop/cop/style/multiline_memoization.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +5 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +2 -4
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +4 -4
- data/lib/rubocop/cop/style/next.rb +2 -2
- data/lib/rubocop/cop/style/nil_comparison.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +4 -4
- data/lib/rubocop/cop/style/not.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +1 -1
- data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
- data/lib/rubocop/cop/style/numeric_predicate.rb +5 -4
- data/lib/rubocop/cop/style/one_line_conditional.rb +4 -3
- data/lib/rubocop/cop/style/or_assignment.rb +4 -3
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +7 -7
- data/lib/rubocop/cop/style/percent_q_literals.rb +1 -1
- data/lib/rubocop/cop/style/perl_backrefs.rb +2 -2
- data/lib/rubocop/cop/style/proc.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_condition.rb +18 -6
- data/lib/rubocop/cop/style/redundant_conditional.rb +1 -1
- data/lib/rubocop/cop/style/redundant_exception.rb +3 -3
- data/lib/rubocop/cop/style/redundant_interpolation.rb +2 -2
- data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -2
- data/lib/rubocop/cop/style/redundant_return.rb +5 -7
- data/lib/rubocop/cop/style/redundant_self.rb +1 -1
- data/lib/rubocop/cop/style/redundant_sort.rb +2 -2
- data/lib/rubocop/cop/style/rescue_modifier.rb +1 -1
- data/lib/rubocop/cop/style/return_nil.rb +1 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
- data/lib/rubocop/cop/style/self_assignment.rb +1 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +1 -4
- data/lib/rubocop/cop/style/string_hash_keys.rb +1 -1
- data/lib/rubocop/cop/style/symbol_array.rb +3 -3
- data/lib/rubocop/cop/style/symbol_literal.rb +2 -2
- data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -3
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +35 -22
- data/lib/rubocop/cop/style/trailing_comma_in_array_literal.rb +41 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +88 -0
- data/lib/rubocop/cop/style/trailing_comma_in_hash_literal.rb +44 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/unpack_first.rb +0 -4
- data/lib/rubocop/cop/style/variable_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +16 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +1 -1
- data/lib/rubocop/cop/variable_force.rb +4 -1
- data/lib/rubocop/formatter/clang_style_formatter.rb +1 -1
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/junit_formatter.rb +74 -0
- data/lib/rubocop/formatter/pacman_formatter.rb +1 -1
- data/lib/rubocop/formatter/tap_formatter.rb +1 -1
- data/lib/rubocop/node_pattern.rb +96 -10
- data/lib/rubocop/options.rb +7 -1
- data/lib/rubocop/processed_source.rb +1 -4
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +1 -1
- data/lib/rubocop/rspec/shared_contexts.rb +5 -4
- data/lib/rubocop/runner.rb +1 -1
- data/lib/rubocop/target_ruby.rb +151 -0
- data/lib/rubocop/version.rb +1 -1
- metadata +39 -12
- data/lib/rubocop/cop/lint/end_in_method.rb +0 -40
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +0 -209
- data/lib/rubocop/formatter/disabled_lines_formatter.rb +0 -57
@@ -121,6 +121,14 @@ module RuboCop
|
|
121
121
|
loc.respond_to?(:dot) && loc.dot && loc.dot.is?('::')
|
122
122
|
end
|
123
123
|
|
124
|
+
# Checks whether the dispatched method uses a safe navigation operator to
|
125
|
+
# connect the receiver and the method name.
|
126
|
+
#
|
127
|
+
# @return [Boolean] whether the method was called with a connecting dot
|
128
|
+
def safe_navigation?
|
129
|
+
loc.respond_to?(:dot) && loc.dot && loc.dot.is?('&.')
|
130
|
+
end
|
131
|
+
|
124
132
|
# Checks whether the *explicit* receiver of this method dispatch is
|
125
133
|
# `self`.
|
126
134
|
#
|
@@ -21,14 +21,12 @@ module RuboCop
|
|
21
21
|
|
22
22
|
# @return [RuboCop::AST::Node] a regopt node
|
23
23
|
def regopt
|
24
|
-
|
25
|
-
first.regopt_type? ? first : second
|
24
|
+
children.last
|
26
25
|
end
|
27
26
|
|
28
27
|
# @return [String] a string of regexp content
|
29
28
|
def content
|
30
|
-
|
31
|
-
str.str_content || ''
|
29
|
+
children.select(&:str_type?).map(&:str_content).join
|
32
30
|
end
|
33
31
|
end
|
34
32
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable Metrics/ModuleLength
|
3
4
|
module RuboCop
|
4
5
|
module AST
|
5
6
|
# Provides methods for traversing an AST.
|
@@ -18,15 +19,21 @@ module RuboCop
|
|
18
19
|
rational str sym regopt self lvar
|
19
20
|
ivar cvar gvar nth_ref back_ref cbase
|
20
21
|
arg restarg blockarg shadowarg
|
21
|
-
kwrestarg zsuper lambda redo retry
|
22
|
+
kwrestarg zsuper lambda redo retry
|
23
|
+
forward_args forwarded_args
|
24
|
+
match_var match_nil_pattern empty_else].freeze
|
22
25
|
ONE_CHILD_NODE = %i[splat kwsplat block_pass not break next
|
23
26
|
preexe postexe match_current_line defined?
|
24
|
-
arg_expr
|
27
|
+
arg_expr pin match_rest if_guard unless_guard
|
28
|
+
match_with_trailing_comma].freeze
|
25
29
|
MANY_CHILD_NODES = %i[dstr dsym xstr regexp array hash pair
|
26
30
|
mlhs masgn or_asgn and_asgn
|
27
31
|
undef alias args super yield or and
|
28
32
|
while_post until_post iflipflop eflipflop
|
29
|
-
match_with_lvasgn begin kwbegin return
|
33
|
+
match_with_lvasgn begin kwbegin return
|
34
|
+
in_match match_alt
|
35
|
+
match_as array_pattern array_pattern_with_tail
|
36
|
+
hash_pattern const_pattern].freeze
|
30
37
|
SECOND_CHILD_ONLY = %i[lvasgn ivasgn cvasgn gvasgn optarg kwarg
|
31
38
|
kwoptarg].freeze
|
32
39
|
|
@@ -171,13 +178,25 @@ module RuboCop
|
|
171
178
|
nil
|
172
179
|
end
|
173
180
|
|
174
|
-
alias on_rescue
|
175
|
-
alias on_resbody
|
176
|
-
alias on_ensure
|
177
|
-
alias on_for
|
178
|
-
alias on_when
|
179
|
-
alias
|
180
|
-
alias
|
181
|
+
alias on_rescue on_case
|
182
|
+
alias on_resbody on_case
|
183
|
+
alias on_ensure on_case
|
184
|
+
alias on_for on_case
|
185
|
+
alias on_when on_case
|
186
|
+
alias on_case_match on_case
|
187
|
+
alias on_in_pattern on_case
|
188
|
+
alias on_irange on_case
|
189
|
+
alias on_erange on_case
|
190
|
+
|
191
|
+
def on_numblock(node)
|
192
|
+
children = node.children
|
193
|
+
child = children[0]
|
194
|
+
send(:"on_#{child.type}", child)
|
195
|
+
return unless (child = children[2])
|
196
|
+
|
197
|
+
send(:"on_#{child.type}", child)
|
198
|
+
end
|
181
199
|
end
|
182
200
|
end
|
183
201
|
end
|
202
|
+
# rubocop:enable Metrics/ModuleLength
|
data/lib/rubocop/cli.rb
CHANGED
@@ -83,10 +83,7 @@ module RuboCop
|
|
83
83
|
end
|
84
84
|
|
85
85
|
def act_on_options
|
86
|
-
|
87
|
-
ConfigLoader.auto_gen_config = @options[:auto_gen_config]
|
88
|
-
ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion]
|
89
|
-
ConfigLoader.options_config = @options[:config]
|
86
|
+
set_options_to_config_loader
|
90
87
|
|
91
88
|
@config_store.options_config = @options[:config] if @options[:config]
|
92
89
|
@config_store.force_default_config! if @options[:force_default_config]
|
@@ -102,6 +99,15 @@ module RuboCop
|
|
102
99
|
end
|
103
100
|
end
|
104
101
|
|
102
|
+
def set_options_to_config_loader
|
103
|
+
ConfigLoader.debug = @options[:debug]
|
104
|
+
ConfigLoader.auto_gen_config = @options[:auto_gen_config]
|
105
|
+
ConfigLoader.disable_pending_cops = @options[:disable_pending_cops]
|
106
|
+
ConfigLoader.enable_pending_cops = @options[:enable_pending_cops]
|
107
|
+
ConfigLoader.ignore_parent_exclusion = @options[:ignore_parent_exclusion]
|
108
|
+
ConfigLoader.options_config = @options[:config]
|
109
|
+
end
|
110
|
+
|
105
111
|
def handle_exiting_options
|
106
112
|
return unless Options::EXITING_OPTIONS.any? { |o| @options.key? o }
|
107
113
|
|
@@ -8,6 +8,13 @@ module RuboCop
|
|
8
8
|
class ShowCops < Base
|
9
9
|
self.command_name = :show_cops
|
10
10
|
|
11
|
+
def initialize(env)
|
12
|
+
super
|
13
|
+
|
14
|
+
# Load the configs so the require()s are done for custom cops
|
15
|
+
@config = @config_store.for(Dir.pwd)
|
16
|
+
end
|
17
|
+
|
11
18
|
def run
|
12
19
|
print_available_cops
|
13
20
|
end
|
@@ -15,8 +22,6 @@ module RuboCop
|
|
15
22
|
private
|
16
23
|
|
17
24
|
def print_available_cops
|
18
|
-
# Load the configs so the require()s are done for custom cops
|
19
|
-
@config_store.for(Dir.pwd)
|
20
25
|
registry = Cop::Cop.registry
|
21
26
|
show_all = @options[:show_cops].empty?
|
22
27
|
|
@@ -46,7 +51,9 @@ module RuboCop
|
|
46
51
|
|
47
52
|
def print_cop_details(cops)
|
48
53
|
cops.each do |cop|
|
49
|
-
|
54
|
+
if cop.new(@config).support_autocorrect?
|
55
|
+
puts '# Supports --auto-correct'
|
56
|
+
end
|
50
57
|
puts "#{cop.cop_name}:"
|
51
58
|
puts config_lines(cop)
|
52
59
|
puts
|
@@ -64,7 +71,7 @@ module RuboCop
|
|
64
71
|
end
|
65
72
|
|
66
73
|
def config_lines(cop)
|
67
|
-
cnf = @
|
74
|
+
cnf = @config.for_cop(cop)
|
68
75
|
cnf.to_yaml.lines.to_a.drop(1).map { |line| ' ' + line }
|
69
76
|
end
|
70
77
|
end
|
@@ -113,7 +113,8 @@ module RuboCop
|
|
113
113
|
def each_mentioned_cop
|
114
114
|
each_directive do |comment, cop_names, disabled|
|
115
115
|
comment_line_number = comment.loc.expression.line
|
116
|
-
single_line = !comment_only_line?(comment_line_number)
|
116
|
+
single_line = !comment_only_line?(comment_line_number) ||
|
117
|
+
directive_on_comment_line?(comment)
|
117
118
|
|
118
119
|
cop_names.each do |cop_name|
|
119
120
|
yield qualified_cop_name(cop_name), disabled, comment_line_number,
|
@@ -122,6 +123,10 @@ module RuboCop
|
|
122
123
|
end
|
123
124
|
end
|
124
125
|
|
126
|
+
def directive_on_comment_line?(comment)
|
127
|
+
comment.text[1..-1].match(COMMENT_DIRECTIVE_REGEXP)
|
128
|
+
end
|
129
|
+
|
125
130
|
def each_directive
|
126
131
|
return if processed_source.comments.nil?
|
127
132
|
|
data/lib/rubocop/config.rb
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'pathname'
|
4
4
|
|
5
|
+
# FIXME: Moving Rails department code to RuboCop Rails will remove
|
6
|
+
# the following rubocop:disable comment.
|
7
|
+
# rubocop:disable Metrics/ClassLength
|
5
8
|
module RuboCop
|
6
9
|
# This class represents the configuration of the RuboCop application
|
7
10
|
# and all its cops. A Config is associated with a YAML configuration
|
@@ -13,6 +16,8 @@ module RuboCop
|
|
13
16
|
include FileFinder
|
14
17
|
extend Forwardable
|
15
18
|
|
19
|
+
CopConfig = Struct.new(:name, :metadata)
|
20
|
+
|
16
21
|
DEFAULT_RAILS_VERSION = 5.0
|
17
22
|
attr_reader :loaded_path
|
18
23
|
|
@@ -42,7 +47,7 @@ module RuboCop
|
|
42
47
|
end
|
43
48
|
|
44
49
|
def_delegators :@hash, :[], :[]=, :delete, :each, :key?, :keys, :each_key,
|
45
|
-
:map, :merge, :to_h, :to_hash
|
50
|
+
:map, :merge, :to_h, :to_hash, :transform_values
|
46
51
|
def_delegators :@validator, :validate, :target_ruby_version
|
47
52
|
|
48
53
|
def to_s
|
@@ -111,6 +116,14 @@ module RuboCop
|
|
111
116
|
@for_all_cops ||= self['AllCops'] || {}
|
112
117
|
end
|
113
118
|
|
119
|
+
def disabled_new_cops?
|
120
|
+
for_all_cops['NewCops'] == 'disable'
|
121
|
+
end
|
122
|
+
|
123
|
+
def enabled_new_cops?
|
124
|
+
for_all_cops['NewCops'] == 'enable'
|
125
|
+
end
|
126
|
+
|
114
127
|
def file_to_include?(file)
|
115
128
|
relative_file_path = path_relative_to_config(file)
|
116
129
|
|
@@ -215,6 +228,18 @@ module RuboCop
|
|
215
228
|
nil
|
216
229
|
end
|
217
230
|
|
231
|
+
def pending_cops
|
232
|
+
keys.each_with_object([]) do |qualified_cop_name, pending_cops|
|
233
|
+
department = department_of(qualified_cop_name)
|
234
|
+
next if department && department['Enabled'] == false
|
235
|
+
|
236
|
+
cop_metadata = self[qualified_cop_name]
|
237
|
+
next unless cop_metadata['Enabled'] == 'pending'
|
238
|
+
|
239
|
+
pending_cops << CopConfig.new(qualified_cop_name, cop_metadata)
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
218
243
|
private
|
219
244
|
|
220
245
|
def target_rails_version_from_bundler_lock_file
|
@@ -235,17 +260,18 @@ module RuboCop
|
|
235
260
|
end
|
236
261
|
|
237
262
|
def enable_cop?(qualified_cop_name, cop_options)
|
238
|
-
|
239
|
-
department
|
240
|
-
|
241
|
-
unless department
|
242
|
-
department_options = self[cop_department]
|
243
|
-
if department_options && department_options['Enabled'] == false
|
244
|
-
return false
|
245
|
-
end
|
246
|
-
end
|
263
|
+
department = department_of(qualified_cop_name)
|
264
|
+
return false if department && department['Enabled'] == false
|
247
265
|
|
248
266
|
cop_options.fetch('Enabled') { !for_all_cops['DisabledByDefault'] }
|
249
267
|
end
|
268
|
+
|
269
|
+
def department_of(qualified_cop_name)
|
270
|
+
cop_department, cop_name = qualified_cop_name.split('/')
|
271
|
+
return nil if cop_name.nil?
|
272
|
+
|
273
|
+
self[cop_department]
|
274
|
+
end
|
250
275
|
end
|
251
276
|
end
|
277
|
+
# rubocop:enable Metrics/ClassLength
|
@@ -24,7 +24,7 @@ module RuboCop
|
|
24
24
|
include FileFinder
|
25
25
|
|
26
26
|
attr_accessor :debug, :auto_gen_config, :ignore_parent_exclusion,
|
27
|
-
:options_config
|
27
|
+
:options_config, :disable_pending_cops, :enable_pending_cops
|
28
28
|
attr_writer :default_configuration
|
29
29
|
|
30
30
|
alias debug? debug
|
@@ -55,7 +55,10 @@ module RuboCop
|
|
55
55
|
end
|
56
56
|
|
57
57
|
def add_missing_namespaces(path, hash)
|
58
|
-
hash.
|
58
|
+
# Using `hash.each_key` will cause the
|
59
|
+
# `can't add a new key into hash during iteration` error
|
60
|
+
hash_keys = hash.keys
|
61
|
+
hash_keys.each do |key|
|
59
62
|
q = Cop::Cop.qualified_cop_name(key, path)
|
60
63
|
next if q == key
|
61
64
|
|
@@ -76,28 +79,35 @@ module RuboCop
|
|
76
79
|
# user's home directory is checked. If there's no .rubocop.yml
|
77
80
|
# there either, the path to the default file is returned.
|
78
81
|
def configuration_file_for(target_dir)
|
79
|
-
find_project_dotfile(target_dir) ||
|
80
|
-
|
81
|
-
find_user_xdg_config ||
|
82
|
-
DEFAULT_FILE
|
82
|
+
find_project_dotfile(target_dir) || find_user_dotfile ||
|
83
|
+
find_user_xdg_config || DEFAULT_FILE
|
83
84
|
end
|
84
85
|
|
85
86
|
def configuration_from_file(config_file)
|
86
|
-
|
87
|
-
return config if config_file == DEFAULT_FILE
|
87
|
+
return ConfigLoader.default_configuration if config_file == DEFAULT_FILE
|
88
88
|
|
89
|
+
config = load_file(config_file)
|
89
90
|
if ignore_parent_exclusion?
|
90
91
|
print 'Ignoring AllCops/Exclude from parent folders' if debug?
|
91
92
|
else
|
92
93
|
add_excludes_from_files(config, config_file)
|
93
94
|
end
|
94
|
-
|
95
|
+
|
96
|
+
merge_with_default(config, config_file).tap do |merged_config|
|
97
|
+
unless possible_new_cops?(config)
|
98
|
+
warn_on_pending_cops(merged_config.pending_cops)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def possible_new_cops?(config)
|
104
|
+
disable_pending_cops || enable_pending_cops ||
|
105
|
+
config.disabled_new_cops? || config.enabled_new_cops?
|
95
106
|
end
|
96
107
|
|
97
108
|
def add_excludes_from_files(config, config_file)
|
98
|
-
found_files =
|
99
|
-
|
100
|
-
[find_user_dotfile, find_user_xdg_config].compact
|
109
|
+
found_files = find_files_upwards(DOTFILE, config_file) +
|
110
|
+
[find_user_dotfile, find_user_xdg_config].compact
|
101
111
|
|
102
112
|
return if found_files.empty?
|
103
113
|
return if PathUtil.relative_path(found_files.last) ==
|
@@ -114,6 +124,22 @@ module RuboCop
|
|
114
124
|
end
|
115
125
|
end
|
116
126
|
|
127
|
+
def warn_on_pending_cops(pending_cops)
|
128
|
+
return if pending_cops.empty?
|
129
|
+
|
130
|
+
warn Rainbow('The following cops were added to RuboCop, but are not ' \
|
131
|
+
'configured. Please set Enabled to either `true` or ' \
|
132
|
+
'`false` in your `.rubocop.yml` file:').yellow
|
133
|
+
|
134
|
+
pending_cops.each do |cop|
|
135
|
+
warn Rainbow(
|
136
|
+
" - #{cop.name} (#{cop.metadata['VersionAdded']})"
|
137
|
+
).yellow
|
138
|
+
end
|
139
|
+
|
140
|
+
warn Rainbow('For more information: https://docs.rubocop.org/en/latest/versioning/').yellow
|
141
|
+
end
|
142
|
+
|
117
143
|
# Merges the given configuration with the default one. If
|
118
144
|
# AllCops:DisabledByDefault is true, it changes the Enabled params so
|
119
145
|
# that only cops from user configuration are enabled.
|
@@ -180,7 +206,9 @@ module RuboCop
|
|
180
206
|
def write_config_file(file_name, file_string, rubocop_yml_contents)
|
181
207
|
File.open(file_name, 'w') do |f|
|
182
208
|
f.write "inherit_from:#{file_string}\n"
|
183
|
-
|
209
|
+
if /\S/.match?(rubocop_yml_contents)
|
210
|
+
f.write "\n#{rubocop_yml_contents}"
|
211
|
+
end
|
184
212
|
end
|
185
213
|
end
|
186
214
|
|
@@ -199,8 +227,6 @@ module RuboCop
|
|
199
227
|
raise(TypeError, "Malformed configuration in #{absolute_path}")
|
200
228
|
end
|
201
229
|
|
202
|
-
check_cop_config_value(hash)
|
203
|
-
|
204
230
|
hash
|
205
231
|
end
|
206
232
|
|
@@ -222,22 +248,6 @@ module RuboCop
|
|
222
248
|
end
|
223
249
|
end
|
224
250
|
|
225
|
-
def check_cop_config_value(hash, parent = nil)
|
226
|
-
hash.each do |key, value|
|
227
|
-
check_cop_config_value(value, key) if value.is_a?(Hash)
|
228
|
-
|
229
|
-
next unless %w[Enabled
|
230
|
-
Safe
|
231
|
-
SafeAutoCorrect
|
232
|
-
AutoCorrect].include?(key) && value.is_a?(String)
|
233
|
-
|
234
|
-
abort(
|
235
|
-
"Property #{Rainbow(key).yellow} of cop #{Rainbow(parent).yellow}" \
|
236
|
-
" is supposed to be a boolean and #{Rainbow(value).yellow} is not."
|
237
|
-
)
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
251
|
# Read the specified file, or exit with a friendly, concise message on
|
242
252
|
# stderr. Care is taken to use the standard OS exit code for a "file not
|
243
253
|
# found" error.
|
@@ -250,8 +260,7 @@ module RuboCop
|
|
250
260
|
|
251
261
|
def yaml_safe_load(yaml_code, filename)
|
252
262
|
if defined?(SafeYAML) && SafeYAML.respond_to?(:load)
|
253
|
-
SafeYAML.load(yaml_code, filename,
|
254
|
-
whitelisted_tags: %w[!ruby/regexp])
|
263
|
+
SafeYAML.load(yaml_code, filename, whitelisted_tags: %w[!ruby/regexp])
|
255
264
|
# Ruby 2.6+
|
256
265
|
elsif Gem::Version.new(Psych::VERSION) >= Gem::Version.new('3.1.0')
|
257
266
|
YAML.safe_load(
|
@@ -17,8 +17,10 @@ module RuboCop
|
|
17
17
|
'Layout/IndentHash' => 'Layout/FirstHashElementIndentation',
|
18
18
|
'Layout/IndentHeredoc' => 'Layout/HeredocIndentation',
|
19
19
|
'Layout/LeadingBlankLines' => 'Layout/LeadingEmptyLines',
|
20
|
+
'Layout/Tab' => 'Layout/IndentationStyle',
|
20
21
|
'Layout/TrailingBlankLines' => 'Layout/TrailingEmptyLines',
|
21
22
|
'Lint/DuplicatedKey' => 'Lint/DuplicateHashKey',
|
23
|
+
'Lint/EndInMethod' => 'Style/EndBlock',
|
22
24
|
'Lint/HandleExceptions' => 'Lint/SuppressedException',
|
23
25
|
'Lint/MultipleCompare' => 'Lint/MultipleComparison',
|
24
26
|
'Lint/StringConversionInInterpolation' => 'Lint/RedundantStringCoercion',
|
@@ -69,7 +71,8 @@ module RuboCop
|
|
69
71
|
'Style/TrailingCommaInHashLiteral',
|
70
72
|
'Style/TrailingCommaInLiteral' => 'Style/TrailingCommaInArrayLiteral ' \
|
71
73
|
'and/or ' \
|
72
|
-
'Style/TrailingCommaInHashLiteral'
|
74
|
+
'Style/TrailingCommaInHashLiteral',
|
75
|
+
'Style/BracesAroundHashParameters' => nil
|
73
76
|
}.map do |old_name, other_cops|
|
74
77
|
if other_cops
|
75
78
|
more = ". Please use #{other_cops} instead".gsub(%r{[A-Z]\w+/\w+},
|
@@ -13,26 +13,22 @@ module RuboCop
|
|
13
13
|
INTERNAL_PARAMS = %w[Description StyleGuide
|
14
14
|
VersionAdded VersionChanged VersionRemoved
|
15
15
|
Reference Safe SafeAutoCorrect].freeze
|
16
|
+
NEW_COPS_VALUES = %w[pending disable enable].freeze
|
16
17
|
|
17
|
-
|
18
|
-
DEFAULT_RUBY_VERSION = 2.3
|
19
|
-
KNOWN_RUBIES = [2.3, 2.4, 2.5, 2.6, 2.7].freeze
|
20
|
-
OBSOLETE_RUBIES = {
|
21
|
-
1.9 => '0.50', 2.0 => '0.50', 2.1 => '0.58', 2.2 => '0.69'
|
22
|
-
}.freeze
|
23
|
-
RUBY_VERSION_FILENAME = '.ruby-version'
|
24
|
-
|
25
|
-
def_delegators :@config,
|
26
|
-
:smart_loaded_path, :for_all_cops, :find_file_upwards,
|
27
|
-
:base_dir_for_path_parameters, :bundler_lock_file_path
|
18
|
+
def_delegators :@config, :smart_loaded_path, :for_all_cops
|
28
19
|
|
29
20
|
def initialize(config)
|
30
21
|
@config = config
|
31
22
|
@config_obsoletion = ConfigObsoletion.new(config)
|
23
|
+
@target_ruby = TargetRuby.new(config)
|
32
24
|
end
|
33
25
|
|
26
|
+
# rubocop:disable Metrics/AbcSize
|
34
27
|
def validate
|
35
|
-
|
28
|
+
check_cop_config_value(@config)
|
29
|
+
reject_conflicting_safe_settings
|
30
|
+
|
31
|
+
# Don't validate RuboCop's own files further. Avoids infinite recursion.
|
36
32
|
return if @config.internal?
|
37
33
|
|
38
34
|
valid_cop_names, invalid_cop_names = @config.keys.partition do |key|
|
@@ -43,30 +39,16 @@ module RuboCop
|
|
43
39
|
|
44
40
|
alert_about_unrecognized_cops(invalid_cop_names)
|
45
41
|
check_target_ruby
|
42
|
+
validate_new_cops_parameter
|
46
43
|
validate_parameter_names(valid_cop_names)
|
47
44
|
validate_enforced_styles(valid_cop_names)
|
48
45
|
validate_syntax_cop
|
49
46
|
reject_mutually_exclusive_defaults
|
50
47
|
end
|
48
|
+
# rubocop:enable Metrics/AbcSize
|
51
49
|
|
52
50
|
def target_ruby_version
|
53
|
-
|
54
|
-
if for_all_cops['TargetRubyVersion']
|
55
|
-
@target_ruby_version_source = :rubocop_yml
|
56
|
-
|
57
|
-
for_all_cops['TargetRubyVersion'].to_f
|
58
|
-
elsif target_ruby_version_from_version_file
|
59
|
-
@target_ruby_version_source = :ruby_version_file
|
60
|
-
|
61
|
-
target_ruby_version_from_version_file
|
62
|
-
elsif target_ruby_version_from_bundler_lock_file
|
63
|
-
@target_ruby_version_source = :bundler_lock_file
|
64
|
-
|
65
|
-
target_ruby_version_from_bundler_lock_file
|
66
|
-
else
|
67
|
-
DEFAULT_RUBY_VERSION
|
68
|
-
end
|
69
|
-
end
|
51
|
+
target_ruby.version
|
70
52
|
end
|
71
53
|
|
72
54
|
def validate_section_presence(name)
|
@@ -78,20 +60,24 @@ module RuboCop
|
|
78
60
|
|
79
61
|
private
|
80
62
|
|
63
|
+
attr_reader :target_ruby
|
64
|
+
|
81
65
|
def check_target_ruby
|
82
|
-
return if
|
66
|
+
return if target_ruby.supported?
|
67
|
+
|
68
|
+
source = target_ruby.source
|
69
|
+
last_version = target_ruby.rubocop_version_with_support
|
83
70
|
|
84
|
-
msg = if
|
71
|
+
msg = if last_version
|
85
72
|
"RuboCop found unsupported Ruby version #{target_ruby_version} " \
|
86
|
-
"in #{
|
87
|
-
|
88
|
-
"#{OBSOLETE_RUBIES[target_ruby_version]}."
|
73
|
+
"in #{source}. #{target_ruby_version}-compatible " \
|
74
|
+
"analysis was dropped after version #{last_version}."
|
89
75
|
else
|
90
76
|
'RuboCop found unknown Ruby version ' \
|
91
|
-
"#{target_ruby_version.inspect} in #{
|
77
|
+
"#{target_ruby_version.inspect} in #{source}."
|
92
78
|
end
|
93
79
|
|
94
|
-
msg += "\nSupported versions: #{
|
80
|
+
msg += "\nSupported versions: #{TargetRuby.supported_versions.join(', ')}"
|
95
81
|
|
96
82
|
raise ValidationError, msg
|
97
83
|
end
|
@@ -125,6 +111,18 @@ module RuboCop
|
|
125
111
|
'It\'s not possible to disable this cop.'
|
126
112
|
end
|
127
113
|
|
114
|
+
def validate_new_cops_parameter
|
115
|
+
new_cop_parameter = @config.for_all_cops['NewCops']
|
116
|
+
return if new_cop_parameter.nil? ||
|
117
|
+
NEW_COPS_VALUES.include?(new_cop_parameter)
|
118
|
+
|
119
|
+
message = "invalid #{new_cop_parameter} for `NewCops` found in" \
|
120
|
+
"#{smart_loaded_path}\n" \
|
121
|
+
"Valid choices are: #{NEW_COPS_VALUES.join(', ')}"
|
122
|
+
|
123
|
+
raise ValidationError, message
|
124
|
+
end
|
125
|
+
|
128
126
|
def validate_parameter_names(valid_cop_names)
|
129
127
|
valid_cop_names.each do |name|
|
130
128
|
validate_section_presence(name)
|
@@ -178,71 +176,47 @@ module RuboCop
|
|
178
176
|
formats.all? { |format| valid.include?(format) }
|
179
177
|
end
|
180
178
|
|
181
|
-
def
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
when :bundler_lock_file
|
186
|
-
"`#{bundler_lock_file_path}`"
|
187
|
-
when :rubocop_yml
|
188
|
-
"`TargetRubyVersion` parameter (in #{smart_loaded_path})"
|
189
|
-
end
|
190
|
-
end
|
179
|
+
def reject_mutually_exclusive_defaults
|
180
|
+
disabled_by_default = for_all_cops['DisabledByDefault']
|
181
|
+
enabled_by_default = for_all_cops['EnabledByDefault']
|
182
|
+
return unless disabled_by_default && enabled_by_default
|
191
183
|
|
192
|
-
|
193
|
-
|
194
|
-
find_file_upwards(RUBY_VERSION_FILENAME, base_dir_for_path_parameters)
|
184
|
+
msg = 'Cops cannot be both enabled by default and disabled by default'
|
185
|
+
raise ValidationError, msg
|
195
186
|
end
|
196
187
|
|
197
|
-
def
|
198
|
-
|
199
|
-
|
188
|
+
def reject_conflicting_safe_settings
|
189
|
+
@config.each do |name, cop_config|
|
190
|
+
next unless cop_config.is_a?(Hash)
|
191
|
+
next unless cop_config['Safe'] == false &&
|
192
|
+
cop_config['SafeAutoCorrect'] == true
|
200
193
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
194
|
+
msg = 'Unsafe cops cannot have a safe auto-correction ' \
|
195
|
+
"(section #{name} in #{smart_loaded_path})"
|
196
|
+
raise ValidationError, msg
|
197
|
+
end
|
205
198
|
end
|
206
199
|
|
207
|
-
def
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
# towards the bottom of the file that look like:
|
220
|
-
# RUBY VERSION
|
221
|
-
# ruby W.X.YpZ
|
222
|
-
# We ultimately want to match the "ruby W.X.Y.pZ" line, but there's
|
223
|
-
# extra logic to make sure we only start looking once we've seen the
|
224
|
-
# "RUBY VERSION" line.
|
225
|
-
in_ruby_section ||= line.match(/^\s*RUBY\s*VERSION\s*$/)
|
226
|
-
next unless in_ruby_section
|
227
|
-
|
228
|
-
# We currently only allow this feature to work with MRI ruby. If jruby
|
229
|
-
# (or something else) is used by the project, it's lock file will have a
|
230
|
-
# line that looks like:
|
231
|
-
# RUBY VERSION
|
232
|
-
# ruby W.X.YpZ (jruby x.x.x.x)
|
233
|
-
# The regex won't match in this situation.
|
234
|
-
result = line.match(/^\s*ruby\s+(\d+\.\d+)[p.\d]*\s*$/)
|
235
|
-
return result.captures.first.to_f if result
|
200
|
+
def check_cop_config_value(hash, parent = nil)
|
201
|
+
hash.each do |key, value|
|
202
|
+
check_cop_config_value(value, key) if value.is_a?(Hash)
|
203
|
+
|
204
|
+
next unless %w[Enabled
|
205
|
+
Safe
|
206
|
+
SafeAutoCorrect
|
207
|
+
AutoCorrect].include?(key) && value.is_a?(String)
|
208
|
+
|
209
|
+
next if key == 'Enabled' && value == 'pending'
|
210
|
+
|
211
|
+
raise ValidationError, msg_not_boolean(parent, key, value)
|
236
212
|
end
|
237
213
|
end
|
238
214
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
msg = 'Cops cannot be both enabled by default and disabled by default'
|
245
|
-
raise ValidationError, msg
|
215
|
+
# FIXME: Handling colors in exception messages like this is ugly.
|
216
|
+
def msg_not_boolean(parent, key, value)
|
217
|
+
"#{Rainbow('').reset}" \
|
218
|
+
"Property #{Rainbow(key).yellow} of cop #{Rainbow(parent).yellow}" \
|
219
|
+
" is supposed to be a boolean and #{Rainbow(value).yellow} is not."
|
246
220
|
end
|
247
221
|
end
|
248
222
|
end
|