rubocop 1.80.2 → 1.82.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 +35 -7
- data/config/obsoletion.yml +4 -0
- data/lib/rubocop/cli/command/auto_generate_config.rb +2 -2
- data/lib/rubocop/cli.rb +3 -3
- data/lib/rubocop/comment_config.rb +62 -17
- data/lib/rubocop/config_loader.rb +5 -2
- data/lib/rubocop/config_loader_resolver.rb +7 -6
- data/lib/rubocop/config_store.rb +5 -0
- data/lib/rubocop/cop/autocorrect_logic.rb +8 -4
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -2
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -4
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -2
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +10 -5
- data/lib/rubocop/cop/internal_affairs/location_exists.rb +28 -2
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups/ast_processor.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/node_pattern_groups.rb +3 -1
- data/lib/rubocop/cop/internal_affairs/on_send_without_on_csend.rb +1 -1
- data/lib/rubocop/cop/layout/class_structure.rb +1 -1
- data/lib/rubocop/cop/layout/dot_position.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_after_guard_clause.rb +3 -0
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +30 -12
- data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/hash_alignment.rb +2 -5
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +1 -4
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +12 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +17 -5
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +5 -1
- data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +6 -4
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +13 -3
- data/lib/rubocop/cop/layout/space_after_comma.rb +2 -10
- data/lib/rubocop/cop/layout/space_after_semicolon.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
- data/lib/rubocop/cop/lint/constant_overwritten_in_rescue.rb +3 -2
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +14 -8
- data/lib/rubocop/cop/lint/debugger.rb +0 -2
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +4 -1
- data/lib/rubocop/cop/lint/duplicate_match_pattern.rb +4 -4
- data/lib/rubocop/cop/lint/else_layout.rb +19 -0
- data/lib/rubocop/cop/lint/empty_interpolation.rb +11 -0
- data/lib/rubocop/cop/lint/literal_as_condition.rb +4 -0
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/missing_cop_enable_directive.rb +16 -6
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +23 -9
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +4 -2
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -1
- data/lib/rubocop/cop/lint/rescue_exception.rb +1 -4
- data/lib/rubocop/cop/lint/self_assignment.rb +10 -2
- data/lib/rubocop/cop/lint/shadowed_argument.rb +7 -7
- data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
- data/lib/rubocop/cop/lint/useless_assignment.rb +44 -16
- data/lib/rubocop/cop/lint/useless_or.rb +15 -2
- data/lib/rubocop/cop/lint/utils/nil_receiver_checker.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +7 -0
- data/lib/rubocop/cop/message_annotator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +1 -1
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +2 -4
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +1 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +21 -2
- data/lib/rubocop/cop/mixin/method_complexity.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +5 -4
- data/lib/rubocop/cop/mixin/statement_modifier.rb +0 -6
- data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -5
- data/lib/rubocop/cop/naming/method_name.rb +4 -2
- data/lib/rubocop/cop/naming/predicate_method.rb +16 -4
- data/lib/rubocop/cop/security/json_load.rb +33 -11
- data/lib/rubocop/cop/style/array_intersect.rb +2 -2
- data/lib/rubocop/cop/style/array_intersect_with_single_element.rb +47 -0
- data/lib/rubocop/cop/style/bare_percent_literals.rb +1 -2
- data/lib/rubocop/cop/style/case_equality.rb +11 -13
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -0
- data/lib/rubocop/cop/style/conditional_assignment.rb +8 -14
- data/lib/rubocop/cop/style/constant_visibility.rb +17 -12
- data/lib/rubocop/cop/style/double_negation.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +0 -6
- data/lib/rubocop/cop/style/endless_method.rb +15 -2
- data/lib/rubocop/cop/style/explicit_block_argument.rb +1 -1
- data/lib/rubocop/cop/style/float_division.rb +15 -1
- data/lib/rubocop/cop/style/guard_clause.rb +0 -11
- data/lib/rubocop/cop/style/hash_syntax.rb +1 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -3
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +12 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +17 -4
- data/lib/rubocop/cop/style/module_member_existence_check.rb +74 -0
- data/lib/rubocop/cop/style/multiline_method_signature.rb +2 -4
- data/lib/rubocop/cop/style/nil_comparison.rb +9 -7
- data/lib/rubocop/cop/style/one_line_conditional.rb +17 -9
- data/lib/rubocop/cop/style/operator_method_call.rb +11 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +2 -2
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -0
- data/lib/rubocop/cop/style/redundant_exception.rb +1 -1
- data/lib/rubocop/cop/style/redundant_format.rb +26 -5
- data/lib/rubocop/cop/style/redundant_interpolation.rb +11 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -0
- data/lib/rubocop/cop/style/redundant_percent_q.rb +1 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +9 -0
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
- data/lib/rubocop/cop/style/semicolon.rb +23 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +8 -1
- data/lib/rubocop/cop/style/super_arguments.rb +2 -2
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +45 -0
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
- data/lib/rubocop/cop/style/unless_else.rb +10 -9
- data/lib/rubocop/cop/util.rb +2 -3
- data/lib/rubocop/cop/utils/format_string.rb +10 -0
- data/lib/rubocop/cops_documentation_generator.rb +4 -4
- data/lib/rubocop/directive_comment.rb +46 -3
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -0
- data/lib/rubocop/lsp/diagnostic.rb +10 -14
- data/lib/rubocop/lsp/stdin_runner.rb +0 -16
- data/lib/rubocop/magic_comment.rb +20 -0
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +7 -8
- data/lib/rubocop/result_cache.rb +38 -27
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/rspec/support.rb +1 -1
- data/lib/rubocop/runner.rb +4 -0
- data/lib/rubocop/target_ruby.rb +11 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +2 -0
- data/lib/ruby_lsp/rubocop/addon.rb +23 -8
- data/lib/ruby_lsp/rubocop/runtime_adapter.rb +49 -15
- metadata +9 -7
|
@@ -10,6 +10,9 @@ module RuboCop
|
|
|
10
10
|
# for all parenthesized multi-line method calls with arguments.
|
|
11
11
|
# * `comma`: Requires a comma after the last argument, but only for
|
|
12
12
|
# parenthesized method calls where each argument is on its own line.
|
|
13
|
+
# * `diff_comma`: Requires a comma after the last argument, but only
|
|
14
|
+
# when that argument is followed by an immediate newline, even if
|
|
15
|
+
# there is an inline comment on the same line.
|
|
13
16
|
# * `no_comma`: Requires that there is no comma after the last
|
|
14
17
|
# argument.
|
|
15
18
|
#
|
|
@@ -75,6 +78,48 @@ module RuboCop
|
|
|
75
78
|
# 2,
|
|
76
79
|
# )
|
|
77
80
|
#
|
|
81
|
+
# @example EnforcedStyleForMultiline: diff_comma
|
|
82
|
+
# # bad
|
|
83
|
+
# method(1, 2,)
|
|
84
|
+
#
|
|
85
|
+
# # good
|
|
86
|
+
# method(1, 2)
|
|
87
|
+
#
|
|
88
|
+
# # good
|
|
89
|
+
# method(
|
|
90
|
+
# 1, 2,
|
|
91
|
+
# 3,
|
|
92
|
+
# )
|
|
93
|
+
#
|
|
94
|
+
# # good
|
|
95
|
+
# method(
|
|
96
|
+
# 1, 2, 3,
|
|
97
|
+
# )
|
|
98
|
+
#
|
|
99
|
+
# # good
|
|
100
|
+
# method(
|
|
101
|
+
# 1,
|
|
102
|
+
# 2,
|
|
103
|
+
# )
|
|
104
|
+
#
|
|
105
|
+
# # bad
|
|
106
|
+
# method(1, [
|
|
107
|
+
# 2,
|
|
108
|
+
# ],)
|
|
109
|
+
#
|
|
110
|
+
# # good
|
|
111
|
+
# method(1, [
|
|
112
|
+
# 2,
|
|
113
|
+
# ])
|
|
114
|
+
#
|
|
115
|
+
# # bad
|
|
116
|
+
# object[1, 2,
|
|
117
|
+
# 3, 4,]
|
|
118
|
+
#
|
|
119
|
+
# # good
|
|
120
|
+
# object[1, 2,
|
|
121
|
+
# 3, 4]
|
|
122
|
+
#
|
|
78
123
|
# @example EnforcedStyleForMultiline: no_comma (default)
|
|
79
124
|
# # bad
|
|
80
125
|
# method(1, 2,)
|
|
@@ -7,26 +7,26 @@ module RuboCop
|
|
|
7
7
|
#
|
|
8
8
|
# @example
|
|
9
9
|
# # bad
|
|
10
|
-
# a, b, _ = foo
|
|
11
|
-
# a, b, _, = foo
|
|
12
|
-
# a, _, _ = foo
|
|
13
|
-
# a, _, _, = foo
|
|
10
|
+
# a, b, _ = foo
|
|
11
|
+
# a, b, _, = foo
|
|
12
|
+
# a, _, _ = foo
|
|
13
|
+
# a, _, _, = foo
|
|
14
14
|
#
|
|
15
15
|
# # good
|
|
16
|
-
# a, b, = foo
|
|
17
|
-
# a, = foo
|
|
18
|
-
# *a, b, _ = foo
|
|
16
|
+
# a, b, = foo
|
|
17
|
+
# a, = foo
|
|
18
|
+
# *a, b, _ = foo
|
|
19
19
|
# # => We need to know to not include 2 variables in a
|
|
20
|
-
# a, *b, _ = foo
|
|
21
|
-
# # => The correction `a, *b, = foo
|
|
20
|
+
# a, *b, _ = foo
|
|
21
|
+
# # => The correction `a, *b, = foo` is a syntax error
|
|
22
22
|
#
|
|
23
23
|
# @example AllowNamedUnderscoreVariables: true (default)
|
|
24
24
|
# # good
|
|
25
|
-
# a, b, _something = foo
|
|
25
|
+
# a, b, _something = foo
|
|
26
26
|
#
|
|
27
27
|
# @example AllowNamedUnderscoreVariables: false
|
|
28
28
|
# # bad
|
|
29
|
-
# a, b, _something = foo
|
|
29
|
+
# a, b, _something = foo
|
|
30
30
|
#
|
|
31
31
|
class TrailingUnderscoreVariable < Base
|
|
32
32
|
include SurroundingSpace
|
|
@@ -20,7 +20,6 @@ module RuboCop
|
|
|
20
20
|
# # do a different thing...
|
|
21
21
|
# end
|
|
22
22
|
class UnlessElse < Base
|
|
23
|
-
include RangeHelp
|
|
24
23
|
extend AutoCorrector
|
|
25
24
|
|
|
26
25
|
MSG = 'Do not use `unless` with `else`. Rewrite these with the positive case first.'
|
|
@@ -29,25 +28,27 @@ module RuboCop
|
|
|
29
28
|
return unless node.unless? && node.else?
|
|
30
29
|
|
|
31
30
|
add_offense(node) do |corrector|
|
|
32
|
-
body_range = range_between_condition_and_else(node, node.condition)
|
|
33
|
-
else_range = range_between_else_and_end(node)
|
|
34
|
-
|
|
35
31
|
next if part_of_ignored_node?(node)
|
|
36
32
|
|
|
37
33
|
corrector.replace(node.loc.keyword, 'if')
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
|
|
35
|
+
body_range = range_between_condition_and_else(node)
|
|
36
|
+
else_range = range_between_else_and_end(node)
|
|
37
|
+
|
|
38
|
+
corrector.swap(body_range, else_range)
|
|
40
39
|
end
|
|
41
40
|
|
|
42
41
|
ignore_node(node)
|
|
43
42
|
end
|
|
44
43
|
|
|
45
|
-
def range_between_condition_and_else(node
|
|
46
|
-
|
|
44
|
+
def range_between_condition_and_else(node)
|
|
45
|
+
range = node.loc.begin ? node.loc.begin.end : node.condition.source_range
|
|
46
|
+
|
|
47
|
+
range.end.join(node.loc.else.begin)
|
|
47
48
|
end
|
|
48
49
|
|
|
49
50
|
def range_between_else_and_end(node)
|
|
50
|
-
|
|
51
|
+
node.loc.else.end.join(node.loc.end.begin)
|
|
51
52
|
end
|
|
52
53
|
end
|
|
53
54
|
end
|
data/lib/rubocop/cop/util.rb
CHANGED
|
@@ -117,10 +117,9 @@ module RuboCop
|
|
|
117
117
|
# with calls chained to the end of it.
|
|
118
118
|
def first_part_of_call_chain(node)
|
|
119
119
|
while node
|
|
120
|
-
|
|
121
|
-
when :send
|
|
120
|
+
if node.call_type?
|
|
122
121
|
node = node.receiver
|
|
123
|
-
|
|
122
|
+
elsif node.any_block_type?
|
|
124
123
|
node = node.send_node
|
|
125
124
|
else
|
|
126
125
|
break
|
|
@@ -71,6 +71,16 @@ module RuboCop
|
|
|
71
71
|
name && @source.include?('{')
|
|
72
72
|
end
|
|
73
73
|
|
|
74
|
+
def variable_width?
|
|
75
|
+
!!width&.start_with?('*')
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def variable_width_argument_number
|
|
79
|
+
return unless variable_width?
|
|
80
|
+
|
|
81
|
+
width == '*' ? 1 : width.match(DIGIT_DOLLAR)['arg_number'].to_i
|
|
82
|
+
end
|
|
83
|
+
|
|
74
84
|
# Number of arguments required for the format sequence
|
|
75
85
|
def arity
|
|
76
86
|
@source.scan('*').count + 1
|
|
@@ -194,10 +194,10 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
194
194
|
|
|
195
195
|
def configurations(department, cop, cop_config)
|
|
196
196
|
header = ['Name', 'Default value', 'Configurable values']
|
|
197
|
-
configs = cop_config
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
197
|
+
configs = cop_config.each_key.reject do |key|
|
|
198
|
+
key == 'AllowMultipleStyles' ||
|
|
199
|
+
(key != 'SupportedTypes' && key.start_with?('Supported'))
|
|
200
|
+
end
|
|
201
201
|
return '' if configs.empty?
|
|
202
202
|
|
|
203
203
|
content = configs.map do |name|
|
|
@@ -14,11 +14,17 @@ module RuboCop
|
|
|
14
14
|
# @api private
|
|
15
15
|
COP_NAME_PATTERN = '([A-Za-z]\w+/)*(?:[A-Za-z]\w+)'
|
|
16
16
|
# @api private
|
|
17
|
+
COP_NAME_PATTERN_NC = '(?:[A-Za-z]\w+/)*[A-Za-z]\w+'
|
|
18
|
+
# @api private
|
|
19
|
+
COP_NAMES_PATTERN_NC = "(?:#{COP_NAME_PATTERN_NC} , )*#{COP_NAME_PATTERN_NC}"
|
|
20
|
+
# @api private
|
|
17
21
|
COP_NAMES_PATTERN = "(?:#{COP_NAME_PATTERN} , )*#{COP_NAME_PATTERN}"
|
|
18
22
|
# @api private
|
|
19
23
|
COPS_PATTERN = "(all|#{COP_NAMES_PATTERN})"
|
|
20
24
|
# @api private
|
|
21
|
-
|
|
25
|
+
PUSH_POP_ARGS_PATTERN = "([+\\-]#{COP_NAME_PATTERN_NC}(?:\\s+[+\\-]#{COP_NAME_PATTERN_NC})*)"
|
|
26
|
+
# @api private
|
|
27
|
+
AVAILABLE_MODES = %w[disable enable todo push pop].freeze
|
|
22
28
|
# @api private
|
|
23
29
|
DIRECTIVE_MARKER_PATTERN = '# rubocop : '
|
|
24
30
|
# @api private
|
|
@@ -27,7 +33,7 @@ module RuboCop
|
|
|
27
33
|
DIRECTIVE_HEADER_PATTERN = "#{DIRECTIVE_MARKER_PATTERN}((?:#{AVAILABLE_MODES.join('|')}))\\b"
|
|
28
34
|
# @api private
|
|
29
35
|
DIRECTIVE_COMMENT_REGEXP = Regexp.new(
|
|
30
|
-
"#{DIRECTIVE_HEADER_PATTERN}
|
|
36
|
+
"#{DIRECTIVE_HEADER_PATTERN}(?:\\s+#{COPS_PATTERN}|\\s+#{PUSH_POP_ARGS_PATTERN})?"
|
|
31
37
|
.gsub(' ', '\s*')
|
|
32
38
|
)
|
|
33
39
|
# @api private
|
|
@@ -58,6 +64,7 @@ module RuboCop
|
|
|
58
64
|
# Checks if the comment is malformed as a `# rubocop:` directive
|
|
59
65
|
def malformed?
|
|
60
66
|
return true if !start_with_marker? || @match_data.nil?
|
|
67
|
+
return true if missing_cop_name?
|
|
61
68
|
|
|
62
69
|
tail = @match_data.post_match.lstrip
|
|
63
70
|
!(tail.empty? || tail.start_with?(TRAILING_COMMENT_MARKER))
|
|
@@ -65,6 +72,8 @@ module RuboCop
|
|
|
65
72
|
|
|
66
73
|
# Checks if the directive comment is missing a cop name
|
|
67
74
|
def missing_cop_name?
|
|
75
|
+
return false if push? || pop?
|
|
76
|
+
|
|
68
77
|
MALFORMED_DIRECTIVE_WITHOUT_COP_NAME_REGEXP.match?(comment.text)
|
|
69
78
|
end
|
|
70
79
|
|
|
@@ -88,7 +97,13 @@ module RuboCop
|
|
|
88
97
|
|
|
89
98
|
# Returns match captures to directive comment pattern
|
|
90
99
|
def match_captures
|
|
91
|
-
@match_captures ||= @match_data
|
|
100
|
+
@match_captures ||= @match_data && begin
|
|
101
|
+
captures = @match_data.captures
|
|
102
|
+
mode = captures[0]
|
|
103
|
+
# COPS_PATTERN is at captures[1], PUSH_POP_ARGS_PATTERN is at captures[4]
|
|
104
|
+
cops = captures[1] || captures[4]
|
|
105
|
+
[mode, cops]
|
|
106
|
+
end
|
|
92
107
|
end
|
|
93
108
|
|
|
94
109
|
# Checks if this directive disables cops
|
|
@@ -101,6 +116,21 @@ module RuboCop
|
|
|
101
116
|
mode == 'enable'
|
|
102
117
|
end
|
|
103
118
|
|
|
119
|
+
# Checks if this directive is a push
|
|
120
|
+
def push?
|
|
121
|
+
mode == 'push'
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
# Checks if this directive is a pop
|
|
125
|
+
def pop?
|
|
126
|
+
mode == 'pop'
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
# Returns the push arguments as a hash of cop names with their operations
|
|
130
|
+
def push_args
|
|
131
|
+
@push_args ||= parse_push_args
|
|
132
|
+
end
|
|
133
|
+
|
|
104
134
|
# Checks if this directive enables all cops
|
|
105
135
|
def enabled_all?
|
|
106
136
|
!disabled? && all_cops?
|
|
@@ -176,5 +206,18 @@ module RuboCop
|
|
|
176
206
|
def exclude_lint_department_cops(cops)
|
|
177
207
|
cops - [LINT_REDUNDANT_DIRECTIVE_COP, LINT_SYNTAX_COP]
|
|
178
208
|
end
|
|
209
|
+
|
|
210
|
+
def parse_push_args
|
|
211
|
+
return {} unless push? && cops
|
|
212
|
+
|
|
213
|
+
args = {}
|
|
214
|
+
cops.split.each do |cop_spec|
|
|
215
|
+
op = cop_spec[0]
|
|
216
|
+
cop_name = cop_spec[1..]
|
|
217
|
+
args[op] ||= []
|
|
218
|
+
args[op] << cop_name
|
|
219
|
+
end
|
|
220
|
+
args
|
|
221
|
+
end
|
|
179
222
|
end
|
|
180
223
|
end
|
|
@@ -45,11 +45,11 @@ module RuboCop
|
|
|
45
45
|
range: LanguageServer::Protocol::Interface::Range.new(
|
|
46
46
|
start: LanguageServer::Protocol::Interface::Position.new(
|
|
47
47
|
line: @offense.line - 1,
|
|
48
|
-
character: highlighted.begin_pos
|
|
48
|
+
character: to_position_character(highlighted.begin_pos)
|
|
49
49
|
),
|
|
50
50
|
end: LanguageServer::Protocol::Interface::Position.new(
|
|
51
51
|
line: @offense.line - 1,
|
|
52
|
-
character: highlighted.end_pos
|
|
52
|
+
character: to_position_character(highlighted.end_pos)
|
|
53
53
|
)
|
|
54
54
|
),
|
|
55
55
|
data: {
|
|
@@ -107,11 +107,11 @@ module RuboCop
|
|
|
107
107
|
range: LanguageServer::Protocol::Interface::Range.new(
|
|
108
108
|
start: LanguageServer::Protocol::Interface::Position.new(
|
|
109
109
|
line: range.line - 1,
|
|
110
|
-
character: range.column
|
|
110
|
+
character: to_position_character(range.column)
|
|
111
111
|
),
|
|
112
112
|
end: LanguageServer::Protocol::Interface::Position.new(
|
|
113
113
|
line: range.last_line - 1,
|
|
114
|
-
character: range.last_column
|
|
114
|
+
character: to_position_character(range.last_column)
|
|
115
115
|
)
|
|
116
116
|
),
|
|
117
117
|
new_text: replacement
|
|
@@ -149,7 +149,7 @@ module RuboCop
|
|
|
149
149
|
|
|
150
150
|
eol = LanguageServer::Protocol::Interface::Position.new(
|
|
151
151
|
line: @offense.line - 1,
|
|
152
|
-
character:
|
|
152
|
+
character: to_position_character(@offense.source_line.length)
|
|
153
153
|
)
|
|
154
154
|
|
|
155
155
|
# TODO: fails for multiline strings - may be preferable to use block
|
|
@@ -162,16 +162,12 @@ module RuboCop
|
|
|
162
162
|
[inline_comment]
|
|
163
163
|
end
|
|
164
164
|
|
|
165
|
-
def
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
line_length += 1
|
|
170
|
-
line_length += 1 if codepoint > RubyLsp::Document::Scanner::SURROGATE_PAIR_START
|
|
171
|
-
end
|
|
172
|
-
line_length
|
|
165
|
+
def to_position_character(utf8_index)
|
|
166
|
+
str = @offense.source_line[0, utf8_index]
|
|
167
|
+
if @document_encoding == Encoding::UTF_16LE || @document_encoding.nil?
|
|
168
|
+
str.length + str.b.count("\xf0-\xff".b)
|
|
173
169
|
else
|
|
174
|
-
|
|
170
|
+
str.length
|
|
175
171
|
end
|
|
176
172
|
end
|
|
177
173
|
|
|
@@ -40,7 +40,6 @@ module RuboCop
|
|
|
40
40
|
super(@options, config_store)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
# rubocop:disable Metrics/MethodLength
|
|
44
43
|
def run(path, contents, options, prism_result: nil)
|
|
45
44
|
@options = options.merge(DEFAULT_RUBOCOP_OPTIONS)
|
|
46
45
|
@options[:stdin] = contents
|
|
@@ -54,22 +53,7 @@ module RuboCop
|
|
|
54
53
|
super([path])
|
|
55
54
|
|
|
56
55
|
raise Interrupt if aborting?
|
|
57
|
-
rescue RuboCop::Runner::InfiniteCorrectionLoop => e
|
|
58
|
-
if defined?(::RubyLsp::Requests::Formatting::Error)
|
|
59
|
-
raise ::RubyLsp::Requests::Formatting::Error, e.message
|
|
60
|
-
end
|
|
61
|
-
|
|
62
|
-
raise e
|
|
63
|
-
rescue RuboCop::ValidationError => e
|
|
64
|
-
raise ConfigurationError, e.message
|
|
65
|
-
rescue StandardError => e
|
|
66
|
-
if defined?(::RubyLsp::Requests::Formatting::Error)
|
|
67
|
-
raise ::RubyLsp::Requests::Support::InternalRuboCopError, e
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
raise e
|
|
71
56
|
end
|
|
72
|
-
# rubocop:enable Metrics/MethodLength
|
|
73
57
|
|
|
74
58
|
def formatted_source
|
|
75
59
|
@options[:stdin]
|
|
@@ -11,6 +11,7 @@ module RuboCop
|
|
|
11
11
|
KEYWORDS = {
|
|
12
12
|
encoding: '(?:en)?coding',
|
|
13
13
|
frozen_string_literal: 'frozen[_-]string[_-]literal',
|
|
14
|
+
rbs_inline: 'rbs_inline',
|
|
14
15
|
shareable_constant_value: 'shareable[_-]constant[_-]value',
|
|
15
16
|
typed: 'typed'
|
|
16
17
|
}.freeze
|
|
@@ -36,6 +37,7 @@ module RuboCop
|
|
|
36
37
|
def any?
|
|
37
38
|
frozen_string_literal_specified? ||
|
|
38
39
|
encoding_specified? ||
|
|
40
|
+
rbs_inline_specified? ||
|
|
39
41
|
shareable_constant_value_specified? ||
|
|
40
42
|
typed_specified?
|
|
41
43
|
end
|
|
@@ -60,6 +62,10 @@ module RuboCop
|
|
|
60
62
|
[true, false].include?(frozen_string_literal)
|
|
61
63
|
end
|
|
62
64
|
|
|
65
|
+
def valid_rbs_inline_value?
|
|
66
|
+
%w[enabled disabled].include?(extract_rbs_inline_value)
|
|
67
|
+
end
|
|
68
|
+
|
|
63
69
|
def valid_shareable_constant_value?
|
|
64
70
|
%w[none literal experimental_everything experimental_copy].include?(shareable_constant_value)
|
|
65
71
|
end
|
|
@@ -105,6 +111,10 @@ module RuboCop
|
|
|
105
111
|
specified?(encoding)
|
|
106
112
|
end
|
|
107
113
|
|
|
114
|
+
def rbs_inline_specified?
|
|
115
|
+
valid_rbs_inline_value?
|
|
116
|
+
end
|
|
117
|
+
|
|
108
118
|
# Was the Sorbet `typed` sigil specified?
|
|
109
119
|
#
|
|
110
120
|
# @return [Boolean]
|
|
@@ -203,6 +213,9 @@ module RuboCop
|
|
|
203
213
|
match(KEYWORDS[:frozen_string_literal])
|
|
204
214
|
end
|
|
205
215
|
|
|
216
|
+
# Emacs comments cannot specify RBS::inline behavior.
|
|
217
|
+
def extract_rbs_inline_value; end
|
|
218
|
+
|
|
206
219
|
def extract_shareable_constant_value
|
|
207
220
|
match(KEYWORDS[:shareable_constant_value])
|
|
208
221
|
end
|
|
@@ -242,6 +255,9 @@ module RuboCop
|
|
|
242
255
|
# Vim comments cannot specify frozen string literal behavior.
|
|
243
256
|
def frozen_string_literal; end
|
|
244
257
|
|
|
258
|
+
# Vim comments cannot specify RBS::inline behavior.
|
|
259
|
+
def extract_rbs_inline_value; end
|
|
260
|
+
|
|
245
261
|
# Vim comments cannot specify shareable constant values behavior.
|
|
246
262
|
def shareable_constant_value; end
|
|
247
263
|
|
|
@@ -296,6 +312,10 @@ module RuboCop
|
|
|
296
312
|
extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*#{TOKEN}\s*\z/io)
|
|
297
313
|
end
|
|
298
314
|
|
|
315
|
+
def extract_rbs_inline_value
|
|
316
|
+
extract(/\A\s*#\s*#{KEYWORDS[:rbs_inline]}:\s*#{TOKEN}\s*\z/io)
|
|
317
|
+
end
|
|
318
|
+
|
|
299
319
|
def extract_shareable_constant_value
|
|
300
320
|
extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*#{TOKEN}\s*\z/io)
|
|
301
321
|
end
|
data/lib/rubocop/rake_task.rb
CHANGED
|
@@ -75,7 +75,7 @@ module RuboCop
|
|
|
75
75
|
def setup_subtasks(name, *args, &task_block) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
76
76
|
namespace(name) do
|
|
77
77
|
# rubocop:todo Naming/InclusiveLanguage
|
|
78
|
-
task(:auto_correct, *args) do
|
|
78
|
+
task(:auto_correct, *args) do |_, task_args|
|
|
79
79
|
require 'rainbow'
|
|
80
80
|
warn Rainbow(
|
|
81
81
|
'rubocop:auto_correct task is deprecated; ' \
|
|
@@ -11,13 +11,13 @@ module RuboCop
|
|
|
11
11
|
|
|
12
12
|
CACHE_LIFETIME = 24 * 60 * 60
|
|
13
13
|
|
|
14
|
-
def initialize(url,
|
|
14
|
+
def initialize(url, cache_root)
|
|
15
15
|
begin
|
|
16
16
|
@uri = URI.parse(url)
|
|
17
17
|
rescue URI::InvalidURIError
|
|
18
18
|
raise ConfigNotFoundError, "Failed to resolve configuration: '#{url}' is not a valid URI"
|
|
19
19
|
end
|
|
20
|
-
@
|
|
20
|
+
@cache_root = cache_root
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
def file
|
|
@@ -27,16 +27,17 @@ module RuboCop
|
|
|
27
27
|
next if response.is_a?(Net::HTTPNotModified)
|
|
28
28
|
next if response.is_a?(SocketError)
|
|
29
29
|
|
|
30
|
+
FileUtils.mkdir_p(File.dirname(cache_path))
|
|
30
31
|
File.write(cache_path, response.body)
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
cache_path
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
def inherit_from_remote(file
|
|
37
|
+
def inherit_from_remote(file)
|
|
37
38
|
new_uri = @uri.dup
|
|
38
39
|
new_uri.path.gsub!(%r{/[^/]*$}, "/#{file.delete_prefix('./')}")
|
|
39
|
-
RemoteConfig.new(new_uri.to_s,
|
|
40
|
+
RemoteConfig.new(new_uri.to_s, @cache_root)
|
|
40
41
|
end
|
|
41
42
|
|
|
42
43
|
private
|
|
@@ -80,7 +81,7 @@ module RuboCop
|
|
|
80
81
|
end
|
|
81
82
|
|
|
82
83
|
def cache_path
|
|
83
|
-
File.expand_path(".rubocop-#{cache_name_from_uri}", @
|
|
84
|
+
@cache_path ||= File.expand_path(".rubocop-remote-#{cache_name_from_uri}", @cache_root)
|
|
84
85
|
end
|
|
85
86
|
|
|
86
87
|
def cache_path_exists?
|
|
@@ -97,9 +98,7 @@ module RuboCop
|
|
|
97
98
|
end
|
|
98
99
|
|
|
99
100
|
def cache_name_from_uri
|
|
100
|
-
uri
|
|
101
|
-
uri.query = nil
|
|
102
|
-
uri.to_s.gsub!(/[^0-9A-Za-z]/, '-')
|
|
101
|
+
"#{Digest::MD5.hexdigest(@uri.to_s)}.yml"
|
|
103
102
|
end
|
|
104
103
|
|
|
105
104
|
def cloned_url
|
data/lib/rubocop/result_cache.rb
CHANGED
|
@@ -22,7 +22,7 @@ module RuboCop
|
|
|
22
22
|
# Remove old files so that the cache doesn't grow too big. When the
|
|
23
23
|
# threshold MaxFilesInCache has been exceeded, the oldest 50% of all the
|
|
24
24
|
# files in the cache are removed. The reason for removing so much is that
|
|
25
|
-
#
|
|
25
|
+
# removing should be done relatively seldom, since there is a slight risk
|
|
26
26
|
# that some other RuboCop process was just about to read the file, when
|
|
27
27
|
# there's parallel execution and the cache is shared.
|
|
28
28
|
def self.cleanup(config_store, verbose, cache_root_override = nil)
|
|
@@ -31,10 +31,12 @@ module RuboCop
|
|
|
31
31
|
rubocop_cache_dir = cache_root(config_store, cache_root_override)
|
|
32
32
|
return unless File.exist?(rubocop_cache_dir)
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
# We know the cache entries are 3 level deep, so globing
|
|
35
|
+
# for `*/*/*` only returns files.
|
|
36
|
+
files = Dir[File.join(rubocop_cache_dir, '*/*/*')]
|
|
35
37
|
return unless requires_file_removal?(files.length, config_store)
|
|
36
38
|
|
|
37
|
-
remove_oldest_files(files,
|
|
39
|
+
remove_oldest_files(files, rubocop_cache_dir, verbose)
|
|
38
40
|
end
|
|
39
41
|
|
|
40
42
|
class << self
|
|
@@ -49,26 +51,36 @@ module RuboCop
|
|
|
49
51
|
file_count > 1 && file_count > config_store.for_pwd.for_all_cops['MaxFilesInCache']
|
|
50
52
|
end
|
|
51
53
|
|
|
52
|
-
def remove_oldest_files(files,
|
|
54
|
+
def remove_oldest_files(files, rubocop_cache_dir, verbose)
|
|
53
55
|
# Add 1 to half the number of files, so that we remove the file if
|
|
54
56
|
# there's only 1 left.
|
|
55
57
|
remove_count = (files.length / 2) + 1
|
|
56
58
|
puts "Removing the #{remove_count} oldest files from #{rubocop_cache_dir}" if verbose
|
|
57
59
|
sorted = files.sort_by { |path| File.mtime(path) }
|
|
58
|
-
remove_files(sorted,
|
|
60
|
+
remove_files(sorted, remove_count)
|
|
59
61
|
rescue Errno::ENOENT
|
|
60
62
|
# This can happen if parallel RuboCop invocations try to remove the
|
|
61
63
|
# same files. No problem.
|
|
62
64
|
puts $ERROR_INFO if verbose
|
|
63
65
|
end
|
|
64
66
|
|
|
65
|
-
def remove_files(files,
|
|
67
|
+
def remove_files(files, remove_count)
|
|
66
68
|
# Batch file deletions, deleting over 130,000+ files will crash
|
|
67
69
|
# File.delete.
|
|
68
70
|
files[0, remove_count].each_slice(10_000).each do |files_slice|
|
|
69
71
|
File.delete(*files_slice)
|
|
70
72
|
end
|
|
71
|
-
|
|
73
|
+
|
|
74
|
+
dirs = files.map { |f| File.dirname(f) }.uniq
|
|
75
|
+
until dirs.empty?
|
|
76
|
+
dirs.select! do |dir|
|
|
77
|
+
Dir.rmdir(dir)
|
|
78
|
+
true
|
|
79
|
+
rescue SystemCallError # ENOTEMPTY etc
|
|
80
|
+
false
|
|
81
|
+
end
|
|
82
|
+
dirs = dirs.map { |f| File.dirname(f) }.uniq
|
|
83
|
+
end
|
|
72
84
|
end
|
|
73
85
|
end
|
|
74
86
|
|
|
@@ -90,7 +102,7 @@ module RuboCop
|
|
|
90
102
|
@allow_symlinks_in_cache_location =
|
|
91
103
|
ResultCache.allow_symlinks_in_cache_location?(config_store)
|
|
92
104
|
@path = File.join(rubocop_cache_dir,
|
|
93
|
-
|
|
105
|
+
self.class.source_checksum,
|
|
94
106
|
context_checksum(team, options),
|
|
95
107
|
file_checksum(file, config_store))
|
|
96
108
|
@cached_data = CachedData.new(file)
|
|
@@ -167,13 +179,11 @@ module RuboCop
|
|
|
167
179
|
end
|
|
168
180
|
|
|
169
181
|
class << self
|
|
170
|
-
attr_accessor :
|
|
171
|
-
end
|
|
182
|
+
attr_accessor :inhibit_cleanup
|
|
172
183
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
begin
|
|
184
|
+
# The checksum of the RuboCop program running the inspection.
|
|
185
|
+
def source_checksum
|
|
186
|
+
@source_checksum ||= begin
|
|
177
187
|
digest = Digest::SHA1.new
|
|
178
188
|
rubocop_extra_features
|
|
179
189
|
.select { |path| File.file?(path) }
|
|
@@ -184,21 +194,22 @@ module RuboCop
|
|
|
184
194
|
digest << RuboCop::Version::STRING << RuboCop::AST::Version::STRING
|
|
185
195
|
digest.hexdigest
|
|
186
196
|
end
|
|
187
|
-
|
|
197
|
+
end
|
|
188
198
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
+
private
|
|
200
|
+
|
|
201
|
+
def digest(path)
|
|
202
|
+
content = if path.end_with?(*DL_EXTENSIONS)
|
|
203
|
+
# Shared libraries often contain timestamps of when
|
|
204
|
+
# they were compiled and other non-stable data.
|
|
205
|
+
File.basename(path)
|
|
206
|
+
else
|
|
207
|
+
File.binread(path) # mtime not reliable
|
|
208
|
+
end
|
|
209
|
+
Zlib.crc32(content).to_s
|
|
210
|
+
end
|
|
199
211
|
|
|
200
|
-
|
|
201
|
-
@rubocop_extra_features ||= begin
|
|
212
|
+
def rubocop_extra_features
|
|
202
213
|
lib_root = File.join(File.dirname(__FILE__), '..')
|
|
203
214
|
exe_root = File.join(lib_root, '..', 'exe')
|
|
204
215
|
|
data/lib/rubocop/runner.rb
CHANGED
|
@@ -65,6 +65,10 @@ module RuboCop
|
|
|
65
65
|
end
|
|
66
66
|
|
|
67
67
|
def run(paths)
|
|
68
|
+
# Compute the cache source checksum once to avoid potential
|
|
69
|
+
# inconsistencies between workers.
|
|
70
|
+
ResultCache.source_checksum
|
|
71
|
+
|
|
68
72
|
target_files = find_target_files(paths)
|
|
69
73
|
if @options[:list_target_files]
|
|
70
74
|
list_files(target_files)
|