rubocop 1.42.0 → 1.45.1
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/README.md +1 -1
- data/config/default.yml +73 -31
- data/lib/rubocop/cli.rb +54 -8
- data/lib/rubocop/config_loader.rb +12 -15
- data/lib/rubocop/config_loader_resolver.rb +3 -4
- data/lib/rubocop/cop/base.rb +27 -9
- data/lib/rubocop/cop/commissioner.rb +8 -2
- data/lib/rubocop/cop/cop.rb +23 -3
- data/lib/rubocop/cop/corrector.rb +10 -2
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +1 -6
- data/lib/rubocop/cop/gemspec/development_dependencies.rb +107 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +11 -3
- data/lib/rubocop/cop/layout/array_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/block_end_newline.rb +7 -1
- data/lib/rubocop/cop/layout/class_structure.rb +2 -16
- data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +2 -6
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +6 -9
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +1 -1
- data/lib/rubocop/cop/layout/space_inside_array_literal_brackets.rb +11 -13
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +4 -4
- data/lib/rubocop/cop/layout/space_inside_string_interpolation.rb +5 -4
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +4 -0
- data/lib/rubocop/cop/lint/debugger.rb +8 -27
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +62 -112
- data/lib/rubocop/cop/lint/else_layout.rb +2 -6
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +14 -7
- data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +15 -17
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +1 -1
- data/lib/rubocop/cop/lint/mixed_regexp_capture_types.rb +1 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +8 -5
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +11 -1
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +7 -4
- data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -3
- data/lib/rubocop/cop/lint/useless_rescue.rb +85 -0
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +9 -1
- data/lib/rubocop/cop/lint/void.rb +19 -10
- data/lib/rubocop/cop/metrics/block_length.rb +1 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +1 -1
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/parameter_lists.rb +27 -0
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +2 -5
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_methods.rb +3 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +5 -3
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +57 -23
- data/lib/rubocop/cop/mixin/line_length_help.rb +3 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -0
- data/lib/rubocop/cop/mixin/surrounding_space.rb +3 -3
- data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +4 -0
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +1 -1
- data/lib/rubocop/cop/registry.rb +12 -7
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +26 -11
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -0
- data/lib/rubocop/cop/style/block_delimiters.rb +8 -2
- data/lib/rubocop/cop/style/class_and_module_children.rb +3 -10
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/comparable_clamp.rb +125 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +0 -6
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/documentation_method.rb +6 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +13 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -0
- data/lib/rubocop/cop/style/infinite_loop.rb +2 -5
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +114 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +23 -14
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/min_max_comparison.rb +11 -1
- data/lib/rubocop/cop/style/missing_else.rb +13 -1
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +0 -4
- data/lib/rubocop/cop/style/multiline_memoization.rb +2 -2
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +18 -3
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -5
- data/lib/rubocop/cop/style/numbered_parameters_limit.rb +11 -3
- data/lib/rubocop/cop/style/one_line_conditional.rb +3 -6
- data/lib/rubocop/cop/style/operator_method_call.rb +16 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +3 -1
- data/lib/rubocop/cop/style/redundant_condition.rb +16 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +0 -4
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +16 -10
- data/lib/rubocop/cop/style/redundant_heredoc_delimiter_quotes.rb +58 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
- data/lib/rubocop/cop/style/require_order.rb +2 -9
- data/lib/rubocop/cop/style/self_assignment.rb +2 -2
- data/lib/rubocop/cop/style/semicolon.rb +24 -2
- data/lib/rubocop/cop/style/string_hash_keys.rb +4 -1
- data/lib/rubocop/cop/style/symbol_array.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +1 -1
- data/lib/rubocop/cop/style/yoda_condition.rb +12 -5
- data/lib/rubocop/cop/style/yoda_expression.rb +18 -2
- data/lib/rubocop/cop/team.rb +19 -14
- data/lib/rubocop/cop/variable_force/scope.rb +3 -3
- data/lib/rubocop/cop/variable_force/variable_table.rb +3 -1
- data/lib/rubocop/cop/variable_force.rb +1 -1
- data/lib/rubocop/formatter.rb +0 -1
- data/lib/rubocop/options.rb +22 -1
- data/lib/rubocop/path_util.rb +11 -6
- data/lib/rubocop/rspec/expect_offense.rb +6 -4
- data/lib/rubocop/runner.rb +40 -4
- data/lib/rubocop/server/cache.rb +10 -3
- data/lib/rubocop/server/cli.rb +37 -18
- data/lib/rubocop/server/client_command/exec.rb +1 -1
- data/lib/rubocop/server/client_command/start.rb +6 -1
- data/lib/rubocop/server/core.rb +23 -8
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +5 -0
- metadata +12 -27
@@ -18,21 +18,27 @@ module RuboCop
|
|
18
18
|
|
19
19
|
MSG = 'Remove the redundant double splat and braces, use keyword arguments directly.'
|
20
20
|
|
21
|
-
# @!method double_splat_hash_braces?(node)
|
22
|
-
def_node_matcher :double_splat_hash_braces?, <<~PATTERN
|
23
|
-
(hash (kwsplat (hash ...)))
|
24
|
-
PATTERN
|
25
|
-
|
26
21
|
def on_hash(node)
|
27
22
|
return if node.pairs.empty? || node.pairs.any?(&:hash_rocket?)
|
23
|
+
return unless (parent = node.parent)
|
24
|
+
return unless parent.kwsplat_type?
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
corrector.replace(grandparent, node.pairs.map(&:source).join(', '))
|
26
|
+
add_offense(parent) do |corrector|
|
27
|
+
corrector.remove(parent.loc.operator)
|
28
|
+
corrector.remove(opening_brace(node))
|
29
|
+
corrector.remove(closing_brace(node))
|
34
30
|
end
|
35
31
|
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def opening_brace(node)
|
36
|
+
node.loc.begin.join(node.children.first.loc.expression.begin)
|
37
|
+
end
|
38
|
+
|
39
|
+
def closing_brace(node)
|
40
|
+
node.children.last.loc.expression.end.join(node.loc.end)
|
41
|
+
end
|
36
42
|
end
|
37
43
|
end
|
38
44
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks for redundant heredoc delimiter quotes.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# do_something(<<~'EOS')
|
12
|
+
# no string interpolation style text
|
13
|
+
# EOS
|
14
|
+
#
|
15
|
+
# # good
|
16
|
+
# do_something(<<~EOS)
|
17
|
+
# no string interpolation style text
|
18
|
+
# EOS
|
19
|
+
#
|
20
|
+
# do_something(<<~'EOS')
|
21
|
+
# #{string_interpolation_style_text_not_evaluated}
|
22
|
+
# EOS
|
23
|
+
#
|
24
|
+
# do_something(<<~'EOS')
|
25
|
+
# Preserve \
|
26
|
+
# newlines
|
27
|
+
# EOS
|
28
|
+
#
|
29
|
+
class RedundantHeredocDelimiterQuotes < Base
|
30
|
+
include Heredoc
|
31
|
+
extend AutoCorrector
|
32
|
+
|
33
|
+
MSG = 'Remove the redundant heredoc delimiter quotes, use `%<replacement>s` instead.'
|
34
|
+
STRING_INTERPOLATION_OR_ESCAPED_CHARACTER_PATTERN = /#(\{|@|\$)|\\/.freeze
|
35
|
+
|
36
|
+
def on_heredoc(node)
|
37
|
+
return if need_heredoc_delimiter_quotes?(node)
|
38
|
+
|
39
|
+
replacement = "#{heredoc_type(node)}#{delimiter_string(node)}"
|
40
|
+
|
41
|
+
add_offense(node, message: format(MSG, replacement: replacement)) do |corrector|
|
42
|
+
corrector.replace(node, replacement)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def need_heredoc_delimiter_quotes?(node)
|
49
|
+
heredoc_delimiter = node.source.delete(heredoc_type(node))
|
50
|
+
return true unless heredoc_delimiter.start_with?("'", '"')
|
51
|
+
|
52
|
+
node.loc.heredoc_end.source.strip.match?(/\W/) ||
|
53
|
+
node.loc.heredoc_body.source.match?(STRING_INTERPOLATION_OR_ESCAPED_CHARACTER_PATTERN)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -77,7 +77,8 @@ module RuboCop
|
|
77
77
|
# but it's not necessry to escape hyphen if it's the first or last character
|
78
78
|
# within the character class. This method checks if that's the case.
|
79
79
|
# e.g. "[0-9\\-]" or "[\\-0-9]" would return true
|
80
|
-
node.source[index] == '[' ||
|
80
|
+
contents_range(node).source[index - 1] == '[' ||
|
81
|
+
contents_range(node).source[index + 2] == ']'
|
81
82
|
end
|
82
83
|
|
83
84
|
def delimiter?(node, char)
|
@@ -88,10 +88,9 @@ module RuboCop
|
|
88
88
|
return unless previous_older_sibling
|
89
89
|
|
90
90
|
add_offense(node, message: format(MSG, name: node.method_name)) do |corrector|
|
91
|
-
swap(
|
91
|
+
corrector.swap(
|
92
92
|
range_with_comments_and_lines(previous_older_sibling),
|
93
|
-
range_with_comments_and_lines(node.parent.if_type? ? node.parent : node)
|
94
|
-
corrector: corrector
|
93
|
+
range_with_comments_and_lines(node.parent.if_type? ? node.parent : node)
|
95
94
|
)
|
96
95
|
end
|
97
96
|
end
|
@@ -130,12 +129,6 @@ module RuboCop
|
|
130
129
|
end_pos: node2.location.expression.end_pos
|
131
130
|
).source.include?("\n\n")
|
132
131
|
end
|
133
|
-
|
134
|
-
def swap(range1, range2, corrector:)
|
135
|
-
inserted = range2.source
|
136
|
-
corrector.insert_before(range1, inserted)
|
137
|
-
corrector.remove(range2)
|
138
|
-
end
|
139
132
|
end
|
140
133
|
end
|
141
134
|
end
|
@@ -42,7 +42,7 @@ module RuboCop
|
|
42
42
|
|
43
43
|
if rhs.send_type?
|
44
44
|
check_send_node(node, rhs, var_name, var_type)
|
45
|
-
elsif
|
45
|
+
elsif rhs.operator_keyword?
|
46
46
|
check_boolean_node(node, rhs, var_name, var_type)
|
47
47
|
end
|
48
48
|
end
|
@@ -76,7 +76,7 @@ module RuboCop
|
|
76
76
|
|
77
77
|
if rhs.send_type?
|
78
78
|
autocorrect_send_node(corrector, node, rhs)
|
79
|
-
elsif
|
79
|
+
elsif rhs.operator_keyword?
|
80
80
|
autocorrect_boolean_node(corrector, node, rhs)
|
81
81
|
end
|
82
82
|
end
|
@@ -72,8 +72,10 @@ module RuboCop
|
|
72
72
|
|
73
73
|
def each_semicolon
|
74
74
|
tokens_for_lines.each do |line, tokens|
|
75
|
-
|
76
|
-
|
75
|
+
semicolon_pos = semicolon_position(tokens)
|
76
|
+
after_expr_pos = semicolon_pos == -1 ? -2 : semicolon_pos
|
77
|
+
|
78
|
+
yield line, tokens[semicolon_pos].column, tokens[after_expr_pos] if semicolon_pos
|
77
79
|
end
|
78
80
|
end
|
79
81
|
|
@@ -81,6 +83,26 @@ module RuboCop
|
|
81
83
|
processed_source.tokens.group_by(&:line)
|
82
84
|
end
|
83
85
|
|
86
|
+
def semicolon_position(tokens)
|
87
|
+
if tokens.last.semicolon?
|
88
|
+
-1
|
89
|
+
elsif tokens.first.semicolon?
|
90
|
+
0
|
91
|
+
elsif exist_semicolon_before_right_curly_brace?(tokens)
|
92
|
+
-3
|
93
|
+
elsif exist_semicolon_after_left_curly_brace?(tokens)
|
94
|
+
2
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def exist_semicolon_before_right_curly_brace?(tokens)
|
99
|
+
tokens[-2]&.right_curly_brace? && tokens[-3]&.semicolon?
|
100
|
+
end
|
101
|
+
|
102
|
+
def exist_semicolon_after_left_curly_brace?(tokens)
|
103
|
+
tokens[1]&.left_curly_brace? && tokens[2]&.semicolon?
|
104
|
+
end
|
105
|
+
|
84
106
|
def register_semicolon(line, column, after_expression, token_before_semicolon = nil)
|
85
107
|
range = source_range(processed_source.buffer, line, column)
|
86
108
|
|
@@ -41,10 +41,13 @@ module RuboCop
|
|
41
41
|
|
42
42
|
def on_pair(node)
|
43
43
|
return unless string_hash_key?(node)
|
44
|
+
|
45
|
+
key_content = node.key.str_content
|
46
|
+
return unless key_content.valid_encoding?
|
44
47
|
return if receive_environments_method?(node)
|
45
48
|
|
46
49
|
add_offense(node.key) do |corrector|
|
47
|
-
symbol_content =
|
50
|
+
symbol_content = key_content.to_sym.inspect
|
48
51
|
|
49
52
|
corrector.replace(node.key, symbol_content)
|
50
53
|
end
|
@@ -33,12 +33,14 @@ module RuboCop
|
|
33
33
|
# "bar" != foo
|
34
34
|
# 42 >= foo
|
35
35
|
# 10 < bar
|
36
|
+
# 99 == CONST
|
36
37
|
#
|
37
38
|
# # good
|
38
39
|
# foo == 99
|
39
40
|
# foo == "bar"
|
40
41
|
# foo <= 42
|
41
42
|
# bar > 10
|
43
|
+
# CONST == 99
|
42
44
|
# "#{interpolation}" == foo
|
43
45
|
# /#{interpolation}/ == foo
|
44
46
|
#
|
@@ -92,9 +94,10 @@ module RuboCop
|
|
92
94
|
def on_send(node)
|
93
95
|
return unless yoda_compatible_condition?(node)
|
94
96
|
return if (equality_only? && non_equality_operator?(node)) ||
|
95
|
-
file_constant_equal_program_name?(node)
|
97
|
+
file_constant_equal_program_name?(node) ||
|
98
|
+
valid_yoda?(node)
|
96
99
|
|
97
|
-
|
100
|
+
add_offense(node) do |corrector|
|
98
101
|
corrector.replace(actual_code_range(node), corrected_code(node))
|
99
102
|
end
|
100
103
|
end
|
@@ -119,11 +122,11 @@ module RuboCop
|
|
119
122
|
lhs = node.receiver
|
120
123
|
rhs = node.first_argument
|
121
124
|
|
122
|
-
return true if (lhs
|
123
|
-
(!lhs
|
125
|
+
return true if (constant_portion?(lhs) && constant_portion?(rhs)) ||
|
126
|
+
(!constant_portion?(lhs) && !constant_portion?(rhs)) ||
|
124
127
|
interpolation?(lhs)
|
125
128
|
|
126
|
-
enforce_yoda? ? lhs
|
129
|
+
enforce_yoda? ? constant_portion?(lhs) : constant_portion?(rhs)
|
127
130
|
end
|
128
131
|
|
129
132
|
def message(node)
|
@@ -137,6 +140,10 @@ module RuboCop
|
|
137
140
|
"#{rhs.source} #{reverse_comparison(node.method_name)} #{lhs.source}"
|
138
141
|
end
|
139
142
|
|
143
|
+
def constant_portion?(node)
|
144
|
+
node.literal? || node.const_type?
|
145
|
+
end
|
146
|
+
|
140
147
|
def actual_code_range(node)
|
141
148
|
range_between(node.loc.expression.begin_pos, node.loc.expression.end_pos)
|
142
149
|
end
|
@@ -7,6 +7,13 @@ module RuboCop
|
|
7
7
|
# and `^` operators) where the order of expression is reversed, eg. `1 + x`.
|
8
8
|
# This cop complements `Style/YodaCondition` cop, which has a similar purpose.
|
9
9
|
#
|
10
|
+
# This cop is disabled by default to respect user intentions such as:
|
11
|
+
#
|
12
|
+
# [source,ruby]
|
13
|
+
# ----
|
14
|
+
# config.server_port = 9000 + ENV["TEST_ENV_NUMBER"].to_i
|
15
|
+
# ----
|
16
|
+
#
|
10
17
|
# @safety
|
11
18
|
# This cop is unsafe because binary operators can be defined
|
12
19
|
# differently on different classes, and are not guaranteed to
|
@@ -17,12 +24,14 @@ module RuboCop
|
|
17
24
|
# 1 + x
|
18
25
|
# 10 * y
|
19
26
|
# 1 & z
|
27
|
+
# 1 + CONST
|
20
28
|
#
|
21
29
|
# # good
|
22
30
|
# 60 * 24
|
23
31
|
# x + 1
|
24
32
|
# y * 10
|
25
33
|
# z & 1
|
34
|
+
# CONST + 1
|
26
35
|
#
|
27
36
|
# # good
|
28
37
|
# 1 | x
|
@@ -43,8 +52,7 @@ module RuboCop
|
|
43
52
|
|
44
53
|
lhs = node.receiver
|
45
54
|
rhs = node.first_argument
|
46
|
-
return
|
47
|
-
|
55
|
+
return unless yoda_expression_constant?(lhs, rhs)
|
48
56
|
return if offended_ancestor?(node)
|
49
57
|
|
50
58
|
message = format(MSG, source: rhs.source)
|
@@ -57,6 +65,14 @@ module RuboCop
|
|
57
65
|
|
58
66
|
private
|
59
67
|
|
68
|
+
def yoda_expression_constant?(lhs, rhs)
|
69
|
+
constant_portion?(lhs) && !constant_portion?(rhs)
|
70
|
+
end
|
71
|
+
|
72
|
+
def constant_portion?(node)
|
73
|
+
node.numeric_type? || node.const_type?
|
74
|
+
end
|
75
|
+
|
60
76
|
def supported_operators
|
61
77
|
Array(cop_config['SupportedOperators'])
|
62
78
|
end
|
data/lib/rubocop/cop/team.rb
CHANGED
@@ -77,7 +77,7 @@ module RuboCop
|
|
77
77
|
end
|
78
78
|
|
79
79
|
# @return [Commissioner::InvestigationReport]
|
80
|
-
def investigate(processed_source)
|
80
|
+
def investigate(processed_source, offset: 0, original: processed_source)
|
81
81
|
be_ready
|
82
82
|
|
83
83
|
# The autocorrection process may have to be repeated multiple times
|
@@ -87,14 +87,15 @@ module RuboCop
|
|
87
87
|
on_duty = roundup_relevant_cops(processed_source.file_path)
|
88
88
|
|
89
89
|
autocorrect_cops, other_cops = on_duty.partition(&:autocorrect?)
|
90
|
+
report = investigate_partial(autocorrect_cops, processed_source,
|
91
|
+
offset: offset, original: original)
|
90
92
|
|
91
|
-
report
|
92
|
-
|
93
|
-
unless autocorrect(processed_source, report)
|
93
|
+
unless autocorrect(processed_source, report, offset: offset, original: original)
|
94
94
|
# If we corrected some errors, another round of inspection will be
|
95
95
|
# done, and any other offenses will be caught then, so only need
|
96
96
|
# to check other_cops if no correction was done
|
97
|
-
report = report.merge(investigate_partial(other_cops, processed_source
|
97
|
+
report = report.merge(investigate_partial(other_cops, processed_source,
|
98
|
+
offset: offset, original: original))
|
98
99
|
end
|
99
100
|
|
100
101
|
process_errors(processed_source.path, report.errors)
|
@@ -116,12 +117,12 @@ module RuboCop
|
|
116
117
|
|
117
118
|
private
|
118
119
|
|
119
|
-
def autocorrect(processed_source, report)
|
120
|
+
def autocorrect(processed_source, report, original:, offset:)
|
120
121
|
@updated_source_file = false
|
121
122
|
return unless autocorrect?
|
122
123
|
return if report.processed_source.parser_error
|
123
124
|
|
124
|
-
new_source = autocorrect_report(report)
|
125
|
+
new_source = autocorrect_report(report, original: original, offset: offset)
|
125
126
|
|
126
127
|
return unless new_source
|
127
128
|
|
@@ -149,9 +150,9 @@ module RuboCop
|
|
149
150
|
end
|
150
151
|
|
151
152
|
# @return [Commissioner::InvestigationReport]
|
152
|
-
def investigate_partial(cops, processed_source)
|
153
|
+
def investigate_partial(cops, processed_source, offset:, original:)
|
153
154
|
commissioner = Commissioner.new(cops, self.class.forces_for(cops), @options)
|
154
|
-
commissioner.investigate(processed_source)
|
155
|
+
commissioner.investigate(processed_source, offset: offset, original: original)
|
155
156
|
end
|
156
157
|
|
157
158
|
# @return [Array<cop>]
|
@@ -175,18 +176,22 @@ module RuboCop
|
|
175
176
|
cop.class.support_target_rails_version?(cop.target_rails_version)
|
176
177
|
end
|
177
178
|
|
178
|
-
def autocorrect_report(report)
|
179
|
-
corrector = collate_corrections(report)
|
179
|
+
def autocorrect_report(report, offset:, original:)
|
180
|
+
corrector = collate_corrections(report, offset: offset, original: original)
|
180
181
|
|
181
182
|
corrector.rewrite unless corrector.empty?
|
182
183
|
end
|
183
184
|
|
184
|
-
def collate_corrections(report)
|
185
|
-
corrector = Corrector.new(
|
185
|
+
def collate_corrections(report, offset:, original:)
|
186
|
+
corrector = Corrector.new(original)
|
186
187
|
|
187
188
|
each_corrector(report) do |to_merge|
|
188
189
|
suppress_clobbering do
|
189
|
-
|
190
|
+
if offset.positive?
|
191
|
+
corrector.import!(to_merge, offset: offset)
|
192
|
+
else
|
193
|
+
corrector.merge!(to_merge)
|
194
|
+
end
|
190
195
|
end
|
191
196
|
end
|
192
197
|
|
@@ -45,9 +45,9 @@ module RuboCop
|
|
45
45
|
node
|
46
46
|
else
|
47
47
|
child_index = case node.type
|
48
|
-
when :module, :sclass
|
49
|
-
when :def, :class, :block then 2
|
50
|
-
when :defs
|
48
|
+
when :module, :sclass then 1
|
49
|
+
when :def, :class, :block, :numblock then 2
|
50
|
+
when :defs then 3
|
51
51
|
end
|
52
52
|
|
53
53
|
node.children[child_index]
|
@@ -97,8 +97,10 @@ module RuboCop
|
|
97
97
|
scope_stack.reverse_each do |scope|
|
98
98
|
variable = scope.variables[name]
|
99
99
|
return variable if variable
|
100
|
+
|
100
101
|
# Only block scope allows referencing outer scope variables.
|
101
|
-
|
102
|
+
node = scope.node
|
103
|
+
return nil unless node.block_type? || node.numblock_type?
|
102
104
|
end
|
103
105
|
|
104
106
|
nil
|
@@ -50,7 +50,7 @@ module RuboCop
|
|
50
50
|
|
51
51
|
ZERO_ARITY_SUPER_TYPE = :zsuper
|
52
52
|
|
53
|
-
TWISTED_SCOPE_TYPES = %i[block class sclass defs module].freeze
|
53
|
+
TWISTED_SCOPE_TYPES = %i[block numblock class sclass defs module].freeze
|
54
54
|
SCOPE_TYPES = (TWISTED_SCOPE_TYPES + [:def]).freeze
|
55
55
|
|
56
56
|
SEND_TYPE = :send
|
data/lib/rubocop/formatter.rb
CHANGED
data/lib/rubocop/options.rb
CHANGED
@@ -61,6 +61,9 @@ module RuboCop
|
|
61
61
|
add_config_generation_options(opts)
|
62
62
|
add_additional_modes(opts)
|
63
63
|
add_general_options(opts)
|
64
|
+
|
65
|
+
# `stackprof` is not supported on JRuby and Windows.
|
66
|
+
add_profile_options(opts) if RUBY_ENGINE == 'ruby' && !Platform.windows?
|
64
67
|
end
|
65
68
|
end
|
66
69
|
|
@@ -206,6 +209,7 @@ module RuboCop
|
|
206
209
|
option(opts, '--start-server')
|
207
210
|
option(opts, '--stop-server')
|
208
211
|
option(opts, '--server-status')
|
212
|
+
option(opts, '--no-detach')
|
209
213
|
end
|
210
214
|
end
|
211
215
|
|
@@ -233,6 +237,16 @@ module RuboCop
|
|
233
237
|
end
|
234
238
|
end
|
235
239
|
|
240
|
+
def add_profile_options(opts)
|
241
|
+
section(opts, 'Profiling Options') do
|
242
|
+
option(opts, '--profile') do
|
243
|
+
@options[:profile] = true
|
244
|
+
@options[:cache] = 'false' unless @options.key?(:cache)
|
245
|
+
end
|
246
|
+
option(opts, '--memory')
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
236
250
|
def handle_deprecated_option(old_option, new_option)
|
237
251
|
warn rainbow.wrap("#{old_option} is deprecated; use #{new_option} instead.").yellow
|
238
252
|
@options[long_opt_symbol([new_option])] = @options.delete(long_opt_symbol([old_option]))
|
@@ -424,6 +438,8 @@ module RuboCop
|
|
424
438
|
def invalid_arguments_for_parallel
|
425
439
|
[('--auto-gen-config' if @options.key?(:auto_gen_config)),
|
426
440
|
('-F/--fail-fast' if @options.key?(:fail_fast)),
|
441
|
+
('--profile' if @options[:profile]),
|
442
|
+
('--memory' if @options[:memory]),
|
427
443
|
('--cache false' if @options > { cache: 'false' })].compact
|
428
444
|
end
|
429
445
|
|
@@ -465,6 +481,7 @@ module RuboCop
|
|
465
481
|
|
466
482
|
# This module contains help texts for command line options.
|
467
483
|
# @api private
|
484
|
+
# rubocop:disable Metrics/ModuleLength
|
468
485
|
module OptionsHelp
|
469
486
|
MAX_EXCL = RuboCop::Options::DEFAULT_MAXIMUM_EXCLUSION_ITEMS.to_s
|
470
487
|
FORMATTER_OPTION_LIST = RuboCop::Formatter::FormatterSet::BUILTIN_FORMATTERS_FOR_KEYS.keys
|
@@ -599,9 +616,13 @@ module RuboCop
|
|
599
616
|
start_server: 'Start server process.',
|
600
617
|
stop_server: 'Stop server process.',
|
601
618
|
server_status: 'Show server status.',
|
619
|
+
no_detach: 'Run the server process in the foreground.',
|
602
620
|
raise_cop_error: ['Raise cop-related errors with cause and location.',
|
603
621
|
'This is used to prevent cops from failing silently.',
|
604
|
-
'Default is false.']
|
622
|
+
'Default is false.'],
|
623
|
+
profile: 'Profile rubocop',
|
624
|
+
memory: 'Profile rubocop memory usage'
|
605
625
|
}.freeze
|
606
626
|
end
|
627
|
+
# rubocop:enable Metrics/ModuleLength
|
607
628
|
end
|
data/lib/rubocop/path_util.rb
CHANGED
@@ -28,14 +28,19 @@ module RuboCop
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
+
SMART_PATH_CACHE = {} # rubocop:disable Style/MutableConstant
|
32
|
+
private_constant :SMART_PATH_CACHE
|
33
|
+
|
31
34
|
def smart_path(path)
|
32
|
-
|
33
|
-
|
35
|
+
SMART_PATH_CACHE[path] ||= begin
|
36
|
+
# Ideally, we calculate this relative to the project root.
|
37
|
+
base_dir = Dir.pwd
|
34
38
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
+
if path.start_with? base_dir
|
40
|
+
relative_path(path, base_dir)
|
41
|
+
else
|
42
|
+
path
|
43
|
+
end
|
39
44
|
end
|
40
45
|
end
|
41
46
|
|
@@ -6,7 +6,7 @@ module RuboCop
|
|
6
6
|
#
|
7
7
|
# This mixin makes it easier to specify strict offense expectations
|
8
8
|
# in a declarative and visual fashion. Just type out the code that
|
9
|
-
# should generate
|
9
|
+
# should generate an offense, annotate code by writing '^'s
|
10
10
|
# underneath each character that should be highlighted, and follow
|
11
11
|
# the carets with a string (separated by a space) that is the
|
12
12
|
# message of the offense. You can include multiple offenses in
|
@@ -126,7 +126,7 @@ module RuboCop
|
|
126
126
|
@offenses
|
127
127
|
end
|
128
128
|
|
129
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
129
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
130
130
|
def expect_correction(correction, loop: true, source: nil)
|
131
131
|
if source
|
132
132
|
expected_annotations = parse_annotations(source, raise_error: false)
|
@@ -138,6 +138,8 @@ module RuboCop
|
|
138
138
|
|
139
139
|
source = @processed_source.raw_source
|
140
140
|
|
141
|
+
raise 'Use `expect_no_corrections` if the code will not change' if correction == source
|
142
|
+
|
141
143
|
iteration = 0
|
142
144
|
new_source = loop do
|
143
145
|
iteration += 1
|
@@ -157,11 +159,11 @@ module RuboCop
|
|
157
159
|
_investigate(cop, @processed_source)
|
158
160
|
end
|
159
161
|
|
160
|
-
raise '
|
162
|
+
raise 'Expected correction but no corrections were made' if new_source == source
|
161
163
|
|
162
164
|
expect(new_source).to eq(correction)
|
163
165
|
end
|
164
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
166
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
165
167
|
|
166
168
|
def expect_no_corrections
|
167
169
|
raise '`expect_no_corrections` must follow `expect_offense`' unless @processed_source
|
data/lib/rubocop/runner.rb
CHANGED
@@ -24,6 +24,27 @@ module RuboCop
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
+
class << self
|
28
|
+
# @return [Array<#call>]
|
29
|
+
def ruby_extractors
|
30
|
+
@ruby_extractors ||= [default_ruby_extractor]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# @return [#call]
|
36
|
+
def default_ruby_extractor
|
37
|
+
lambda do |processed_source|
|
38
|
+
[
|
39
|
+
{
|
40
|
+
offset: 0,
|
41
|
+
processed_source: processed_source
|
42
|
+
}
|
43
|
+
]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
27
48
|
# @api private
|
28
49
|
MAX_ITERATIONS = 200
|
29
50
|
|
@@ -319,10 +340,25 @@ module RuboCop
|
|
319
340
|
end
|
320
341
|
|
321
342
|
def inspect_file(processed_source, team = mobilize_team(processed_source))
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
343
|
+
extracted_ruby_sources = extract_ruby_sources(processed_source)
|
344
|
+
offenses = extracted_ruby_sources.flat_map do |extracted_ruby_source|
|
345
|
+
report = team.investigate(
|
346
|
+
extracted_ruby_source[:processed_source],
|
347
|
+
offset: extracted_ruby_source[:offset],
|
348
|
+
original: processed_source
|
349
|
+
)
|
350
|
+
@errors.concat(team.errors)
|
351
|
+
@warnings.concat(team.warnings)
|
352
|
+
report.offenses
|
353
|
+
end
|
354
|
+
[offenses, team.updated_source_file?]
|
355
|
+
end
|
356
|
+
|
357
|
+
def extract_ruby_sources(processed_source)
|
358
|
+
self.class.ruby_extractors.find do |ruby_extractor|
|
359
|
+
result = ruby_extractor.call(processed_source)
|
360
|
+
break result if result
|
361
|
+
end
|
326
362
|
end
|
327
363
|
|
328
364
|
def mobilize_team(processed_source)
|