rubocop 1.81.7 → 1.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/README.md +1 -1
- data/config/default.yml +21 -5
- data/config/obsoletion.yml +4 -0
- data/lib/rubocop/cli.rb +2 -1
- data/lib/rubocop/comment_config.rb +62 -17
- data/lib/rubocop/config_loader.rb +2 -1
- data/lib/rubocop/config_loader_resolver.rb +2 -2
- data/lib/rubocop/cop/autocorrect_logic.rb +2 -0
- data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -3
- 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/layout/empty_line_after_guard_clause.rb +3 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +4 -0
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
- data/lib/rubocop/cop/layout/heredoc_indentation.rb +0 -4
- data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +7 -4
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +5 -3
- data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +47 -3
- data/lib/rubocop/cop/lint/cop_directive_syntax.rb +1 -1
- data/lib/rubocop/cop/lint/else_layout.rb +19 -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/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/self_assignment.rb +9 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +5 -3
- 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/metrics/utils/abc_size_calculator.rb +4 -3
- data/lib/rubocop/cop/mixin/check_single_line_suitability.rb +0 -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/statement_modifier.rb +0 -6
- data/lib/rubocop/cop/mixin/trailing_comma.rb +4 -5
- data/lib/rubocop/cop/naming/method_name.rb +1 -1
- 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 +1 -11
- data/lib/rubocop/cop/style/constant_visibility.rb +3 -3
- data/lib/rubocop/cop/style/empty_method.rb +0 -6
- data/lib/rubocop/cop/style/endless_method.rb +2 -2
- data/lib/rubocop/cop/style/guard_clause.rb +0 -11
- 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 +0 -4
- 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_percent_q.rb +1 -2
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +5 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +7 -7
- data/lib/rubocop/cop/style/super_arguments.rb +2 -2
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +11 -11
- data/lib/rubocop/cop/util.rb +2 -3
- data/lib/rubocop/directive_comment.rb +46 -3
- data/lib/rubocop/formatter/disabled_config_formatter.rb +1 -0
- data/lib/rubocop/lsp/diagnostic.rb +12 -17
- data/lib/rubocop/lsp/routes.rb +9 -36
- data/lib/rubocop/lsp/runtime.rb +2 -2
- data/lib/rubocop/lsp/server.rb +2 -2
- 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/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/rspec/support.rb +1 -1
- data/lib/rubocop/target_ruby.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +1 -0
- metadata +7 -6
|
@@ -9,17 +9,20 @@ module RuboCop
|
|
|
9
9
|
# In the default style (require_parentheses), macro methods are allowed.
|
|
10
10
|
# Additional methods can be added to the `AllowedMethods` or
|
|
11
11
|
# `AllowedPatterns` list. These options are valid only in the default
|
|
12
|
-
# style. Macros can be included by either setting `IgnoreMacros` to false
|
|
13
|
-
#
|
|
12
|
+
# style. Macros can be included by either setting `IgnoreMacros` to false,
|
|
13
|
+
# adding specific macros to the `IncludedMacros` list, or using
|
|
14
|
+
# `IncludedMacroPatterns` for pattern-based matching.
|
|
14
15
|
#
|
|
15
16
|
# Precedence of options is as follows:
|
|
16
17
|
#
|
|
17
18
|
# 1. `AllowedMethods`
|
|
18
19
|
# 2. `AllowedPatterns`
|
|
19
20
|
# 3. `IncludedMacros`
|
|
21
|
+
# 4. `IncludedMacroPatterns`
|
|
20
22
|
#
|
|
21
|
-
# If a method is listed in both `IncludedMacros`
|
|
22
|
-
# then the latter takes precedence (that is, the
|
|
23
|
+
# If a method is listed in both `IncludedMacros`/`IncludedMacroPatterns`
|
|
24
|
+
# and `AllowedMethods`, then the latter takes precedence (that is, the
|
|
25
|
+
# method is allowed).
|
|
23
26
|
#
|
|
24
27
|
# In the alternative style (omit_parentheses), there are three additional
|
|
25
28
|
# options.
|
|
@@ -148,6 +151,16 @@ module RuboCop
|
|
|
148
151
|
# # still enforces parentheses on other methods
|
|
149
152
|
# array.delete(e)
|
|
150
153
|
#
|
|
154
|
+
# @example IncludedMacroPatterns: ["^assert", "^refute"]
|
|
155
|
+
#
|
|
156
|
+
# # bad
|
|
157
|
+
# assert_equal 'test', x
|
|
158
|
+
# refute_nil value
|
|
159
|
+
#
|
|
160
|
+
# # good
|
|
161
|
+
# assert_equal('test', x)
|
|
162
|
+
# refute_nil(value)
|
|
163
|
+
#
|
|
151
164
|
# @example AllowParenthesesInMultilineCall: false (default)
|
|
152
165
|
#
|
|
153
166
|
# # bad
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module Cop
|
|
5
|
+
module Style
|
|
6
|
+
# Checks for usage of `Module` methods returning arrays that can be replaced
|
|
7
|
+
# with equivalent predicates.
|
|
8
|
+
#
|
|
9
|
+
# Calling a method returning an array then checking if an element is inside
|
|
10
|
+
# it is much slower than using an equivalent predicate method. For example,
|
|
11
|
+
# `instance_methods.include?` will return an array of all public and protected
|
|
12
|
+
# instance methods in the module, then check if a given method is inside that
|
|
13
|
+
# array, while `method_defined?` will do direct method lookup, which is much
|
|
14
|
+
# faster and consumes less memory.
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
# # bad
|
|
18
|
+
# Array.instance_methods.include?(:size)
|
|
19
|
+
# Array.instance_methods.member?(:size)
|
|
20
|
+
# Array.instance_methods(true).include?(:size)
|
|
21
|
+
#
|
|
22
|
+
# Array.instance_methods(false).include?(:find)
|
|
23
|
+
#
|
|
24
|
+
# # good
|
|
25
|
+
# Array.method_defined?(:size)
|
|
26
|
+
#
|
|
27
|
+
# Array.method_defined?(:find, false)
|
|
28
|
+
#
|
|
29
|
+
class ModuleMemberExistenceCheck < Base
|
|
30
|
+
extend AutoCorrector
|
|
31
|
+
|
|
32
|
+
MSG = 'Use `%<replacement>s` instead.'
|
|
33
|
+
|
|
34
|
+
RESTRICT_ON_SEND = %i[instance_methods].freeze
|
|
35
|
+
|
|
36
|
+
# @!method instance_methods_inclusion?(node)
|
|
37
|
+
def_node_matcher :instance_methods_inclusion?, <<~PATTERN
|
|
38
|
+
(call
|
|
39
|
+
(call _ :instance_methods _?)
|
|
40
|
+
{:include? :member?}
|
|
41
|
+
_)
|
|
42
|
+
PATTERN
|
|
43
|
+
|
|
44
|
+
def on_send(node) # rubocop:disable Metrics/AbcSize
|
|
45
|
+
return unless (parent = node.parent)
|
|
46
|
+
return unless instance_methods_inclusion?(parent)
|
|
47
|
+
return unless simple_method_argument?(node) && simple_method_argument?(parent)
|
|
48
|
+
|
|
49
|
+
offense_range = node.location.selector.join(parent.source_range.end)
|
|
50
|
+
replacement =
|
|
51
|
+
if node.first_argument.nil? || node.first_argument.true_type?
|
|
52
|
+
"method_defined?(#{parent.first_argument.source})"
|
|
53
|
+
else
|
|
54
|
+
"method_defined?(#{parent.first_argument.source}, #{node.first_argument.source})"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
add_offense(offense_range, message: format(MSG, replacement: replacement)) do |corrector|
|
|
58
|
+
corrector.replace(offense_range, replacement)
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
alias on_csend on_send
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def simple_method_argument?(node)
|
|
66
|
+
return false if node.splat_argument? || node.block_argument?
|
|
67
|
+
return false if node.first_argument&.hash_type?
|
|
68
|
+
|
|
69
|
+
true
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -14,7 +14,7 @@ module RuboCop
|
|
|
14
14
|
#
|
|
15
15
|
# # good
|
|
16
16
|
# one, two = *foo
|
|
17
|
-
# a, b = foo
|
|
17
|
+
# a, b = foo
|
|
18
18
|
# a, b = b, a
|
|
19
19
|
#
|
|
20
20
|
# a = 1
|
|
@@ -223,7 +223,7 @@ module RuboCop
|
|
|
223
223
|
# __FILE__ is treated as a StrNode but has no begin
|
|
224
224
|
if node.str_type? && loc.respond_to?(:begin) && loc.begin.nil?
|
|
225
225
|
"'#{node.source}'"
|
|
226
|
-
elsif node.sym_type? && loc
|
|
226
|
+
elsif node.sym_type? && !node.loc?(:begin)
|
|
227
227
|
":#{node.source}"
|
|
228
228
|
else
|
|
229
229
|
node.source
|
|
@@ -37,6 +37,7 @@ module RuboCop
|
|
|
37
37
|
# array.sum(0)
|
|
38
38
|
# exit(true)
|
|
39
39
|
# exit!(false)
|
|
40
|
+
# string.to_i(10)
|
|
40
41
|
# string.split(" ")
|
|
41
42
|
# "first\nsecond".split(" ")
|
|
42
43
|
# string.chomp("\n")
|
|
@@ -49,6 +50,7 @@ module RuboCop
|
|
|
49
50
|
# array.sum
|
|
50
51
|
# exit
|
|
51
52
|
# exit!
|
|
53
|
+
# string.to_i
|
|
52
54
|
# string.split
|
|
53
55
|
# "first second".split
|
|
54
56
|
# string.chomp
|
|
@@ -75,6 +75,11 @@ module RuboCop
|
|
|
75
75
|
new_argument.gsub!('\"', '"')
|
|
76
76
|
quote = "'"
|
|
77
77
|
elsif new_argument.include?("\\'")
|
|
78
|
+
# Add a backslash before single quotes preceded by an even number of backslashes.
|
|
79
|
+
# An even number (including zero) of backslashes before a quote means the quote itself
|
|
80
|
+
# is not escaped.
|
|
81
|
+
# Otherwise an odd number means the quote is already escaped so this doesn't touch it.
|
|
82
|
+
new_argument.gsub!(/(?<!\\)((?:\\\\)*)'/) { "#{::Regexp.last_match(1)}\\'" }
|
|
78
83
|
quote = "'"
|
|
79
84
|
elsif new_argument.include?('\'')
|
|
80
85
|
new_argument.gsub!("'", "\\\\'")
|
|
@@ -26,17 +26,17 @@ module RuboCop
|
|
|
26
26
|
#
|
|
27
27
|
# [source,ruby]
|
|
28
28
|
# ----
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
#
|
|
32
|
-
#
|
|
29
|
+
# class MyString < String; end
|
|
30
|
+
# strings = [MyString.new('test'), 'test']
|
|
31
|
+
# strings.sort.last.class #=> String
|
|
32
|
+
# strings.max.class #=> MyString
|
|
33
33
|
# ----
|
|
34
34
|
#
|
|
35
35
|
# [source,ruby]
|
|
36
36
|
# ----
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
37
|
+
# words = %w(dog horse mouse)
|
|
38
|
+
# words.sort_by { |word| word.length }.last #=> 'mouse'
|
|
39
|
+
# words.max_by { |word| word.length } #=> 'horse'
|
|
40
40
|
# ----
|
|
41
41
|
#
|
|
42
42
|
# @example
|
|
@@ -109,7 +109,7 @@ module RuboCop
|
|
|
109
109
|
|
|
110
110
|
def_args.zip(super_args).each do |def_arg, super_arg|
|
|
111
111
|
next if positional_arg_same?(def_arg, super_arg)
|
|
112
|
-
next if positional_rest_arg_same(def_arg, super_arg)
|
|
112
|
+
next if positional_rest_arg_same?(def_arg, super_arg)
|
|
113
113
|
next if keyword_arg_same?(def_arg, super_arg)
|
|
114
114
|
next if keyword_rest_arg_same?(def_arg, super_arg)
|
|
115
115
|
next if block_arg_same?(def_node, super_node, def_arg, super_arg)
|
|
@@ -147,7 +147,7 @@ module RuboCop
|
|
|
147
147
|
def_arg.name == super_arg.children.first
|
|
148
148
|
end
|
|
149
149
|
|
|
150
|
-
def positional_rest_arg_same(def_arg, super_arg)
|
|
150
|
+
def positional_rest_arg_same?(def_arg, super_arg)
|
|
151
151
|
return false unless def_arg.restarg_type?
|
|
152
152
|
# anonymous forwarding
|
|
153
153
|
return true if def_arg.name.nil? && super_arg.forwarded_restarg_type?
|
|
@@ -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
|
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
|
|
@@ -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
|
|
@@ -16,8 +16,8 @@ module RuboCop
|
|
|
16
16
|
# Diagnostic for Language Server Protocol of RuboCop.
|
|
17
17
|
# @api private
|
|
18
18
|
class Diagnostic
|
|
19
|
-
def initialize(
|
|
20
|
-
@
|
|
19
|
+
def initialize(document_encoding, offense, uri, cop_class)
|
|
20
|
+
@document_encoding = document_encoding
|
|
21
21
|
@offense = offense
|
|
22
22
|
@uri = uri
|
|
23
23
|
@cop_class = cop_class
|
|
@@ -149,7 +149,7 @@ module RuboCop
|
|
|
149
149
|
|
|
150
150
|
eol = LanguageServer::Protocol::Interface::Position.new(
|
|
151
151
|
line: @offense.line - 1,
|
|
152
|
-
character: to_position_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,6 +162,15 @@ module RuboCop
|
|
|
162
162
|
[inline_comment]
|
|
163
163
|
end
|
|
164
164
|
|
|
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)
|
|
169
|
+
else
|
|
170
|
+
str.length
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
165
174
|
def correctable?
|
|
166
175
|
!@offense.corrector.nil?
|
|
167
176
|
end
|
|
@@ -171,20 +180,6 @@ module RuboCop
|
|
|
171
180
|
uri.scheme = 'file' if uri.scheme.nil?
|
|
172
181
|
uri
|
|
173
182
|
end
|
|
174
|
-
|
|
175
|
-
def to_position_character(utf8_index = nil)
|
|
176
|
-
str = utf8_index ? @offense.source_line[0, utf8_index] : @offense.source_line
|
|
177
|
-
case @position_encoding
|
|
178
|
-
when 'utf-8', Encoding::UTF_8
|
|
179
|
-
str.bytesize
|
|
180
|
-
when 'utf-32', Encoding::UTF_32
|
|
181
|
-
str.size
|
|
182
|
-
else # 'utf-16'
|
|
183
|
-
# utf-16 is default position encoding on LSP
|
|
184
|
-
# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
|
|
185
|
-
str.size + str.count("\u{10000}-\u{10FFFF}")
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
183
|
end
|
|
189
184
|
end
|
|
190
185
|
end
|
data/lib/rubocop/lsp/routes.rb
CHANGED
|
@@ -15,7 +15,7 @@ module RuboCop
|
|
|
15
15
|
module LSP
|
|
16
16
|
# Routes for Language Server Protocol of RuboCop.
|
|
17
17
|
# @api private
|
|
18
|
-
class Routes
|
|
18
|
+
class Routes
|
|
19
19
|
CONFIGURATION_FILE_PATTERNS = [
|
|
20
20
|
RuboCop::ConfigFinder::DOTFILE,
|
|
21
21
|
RuboCop::CLI::Command::AutoGenerateConfig::AUTO_GENERATED_FILE
|
|
@@ -42,7 +42,6 @@ module RuboCop
|
|
|
42
42
|
|
|
43
43
|
handle 'initialize' do |request|
|
|
44
44
|
initialization_options = extract_initialization_options_from(request)
|
|
45
|
-
@position_encoding = initialization_options[:position_encoding]
|
|
46
45
|
|
|
47
46
|
@server.configure(initialization_options)
|
|
48
47
|
|
|
@@ -54,8 +53,7 @@ module RuboCop
|
|
|
54
53
|
text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
|
|
55
54
|
change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::INCREMENTAL,
|
|
56
55
|
open_close: true
|
|
57
|
-
)
|
|
58
|
-
position_encoding: @position_encoding
|
|
56
|
+
)
|
|
59
57
|
)
|
|
60
58
|
)
|
|
61
59
|
)
|
|
@@ -186,26 +184,14 @@ module RuboCop
|
|
|
186
184
|
|
|
187
185
|
def extract_initialization_options_from(request)
|
|
188
186
|
safe_autocorrect = request.dig(:params, :initializationOptions, :safeAutocorrect)
|
|
189
|
-
position_encodings = request.dig(:params, :capabilities, :general, :positionEncodings)
|
|
190
187
|
|
|
191
188
|
{
|
|
192
189
|
safe_autocorrect: safe_autocorrect.nil? || safe_autocorrect == true,
|
|
193
190
|
lint_mode: request.dig(:params, :initializationOptions, :lintMode) == true,
|
|
194
|
-
layout_mode: request.dig(:params, :initializationOptions, :layoutMode) == true
|
|
195
|
-
position_encoding: position_encoding(position_encodings)
|
|
191
|
+
layout_mode: request.dig(:params, :initializationOptions, :layoutMode) == true
|
|
196
192
|
}
|
|
197
193
|
end
|
|
198
194
|
|
|
199
|
-
def position_encoding(position_encodings)
|
|
200
|
-
if position_encodings&.include?('utf-8')
|
|
201
|
-
'utf-8'
|
|
202
|
-
elsif position_encodings&.include?('utf-32')
|
|
203
|
-
'utf-32'
|
|
204
|
-
else
|
|
205
|
-
'utf-16'
|
|
206
|
-
end
|
|
207
|
-
end
|
|
208
|
-
|
|
209
195
|
def format_file(file_uri, command: nil)
|
|
210
196
|
unless (text = @text_cache[file_uri])
|
|
211
197
|
Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
|
|
@@ -233,8 +219,7 @@ module RuboCop
|
|
|
233
219
|
method: 'textDocument/publishDiagnostics',
|
|
234
220
|
params: {
|
|
235
221
|
uri: file_uri,
|
|
236
|
-
diagnostics: @server.offenses(convert_file_uri_to_path(file_uri),
|
|
237
|
-
text, @position_encoding)
|
|
222
|
+
diagnostics: @server.offenses(convert_file_uri_to_path(file_uri), text)
|
|
238
223
|
}
|
|
239
224
|
}
|
|
240
225
|
end
|
|
@@ -244,8 +229,9 @@ module RuboCop
|
|
|
244
229
|
|
|
245
230
|
start_pos = text_pos(orig_text, range[:start])
|
|
246
231
|
end_pos = text_pos(orig_text, range[:end])
|
|
247
|
-
|
|
248
|
-
|
|
232
|
+
text_bin = orig_text.b
|
|
233
|
+
text_bin[start_pos...end_pos] = text.b
|
|
234
|
+
text_bin.force_encoding(orig_text.encoding)
|
|
249
235
|
end
|
|
250
236
|
|
|
251
237
|
def text_pos(text, range)
|
|
@@ -254,27 +240,14 @@ module RuboCop
|
|
|
254
240
|
pos = 0
|
|
255
241
|
text.each_line.with_index do |l, i|
|
|
256
242
|
if i == line
|
|
257
|
-
pos +=
|
|
243
|
+
pos += l.encode('utf-16be').b[0, char * 2].encode('utf-8', 'utf-16be').bytesize
|
|
258
244
|
return pos
|
|
259
245
|
end
|
|
260
|
-
pos += l.
|
|
246
|
+
pos += l.bytesize
|
|
261
247
|
end
|
|
262
248
|
pos
|
|
263
249
|
end
|
|
264
250
|
|
|
265
|
-
def line_pos(line, char)
|
|
266
|
-
case @position_encoding
|
|
267
|
-
when 'utf-8'
|
|
268
|
-
line.byteslice(0, char).size
|
|
269
|
-
when 'utf-32'
|
|
270
|
-
char
|
|
271
|
-
else # 'utf-16'
|
|
272
|
-
# utf-16 is default position encoding on LSP
|
|
273
|
-
# https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/
|
|
274
|
-
line.encode('utf-16be').byteslice(0, char * 2).size
|
|
275
|
-
end
|
|
276
|
-
end
|
|
277
|
-
|
|
278
251
|
def convert_file_uri_to_path(uri)
|
|
279
252
|
URI.decode_www_form_component(uri.delete_prefix('file://'))
|
|
280
253
|
end
|
data/lib/rubocop/lsp/runtime.rb
CHANGED
|
@@ -44,14 +44,14 @@ module RuboCop
|
|
|
44
44
|
@runner.formatted_source
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
-
def offenses(path, text,
|
|
47
|
+
def offenses(path, text, document_encoding = nil, prism_result: nil)
|
|
48
48
|
diagnostic_options = {}
|
|
49
49
|
diagnostic_options[:only] = config_only_options if @lint_mode || @layout_mode
|
|
50
50
|
|
|
51
51
|
@runner.run(path, text, diagnostic_options, prism_result: prism_result)
|
|
52
52
|
@runner.offenses.map do |offense|
|
|
53
53
|
Diagnostic.new(
|
|
54
|
-
|
|
54
|
+
document_encoding, offense, path, @cop_registry[offense.cop_name]&.first
|
|
55
55
|
).to_lsp_diagnostic(@runner.config_for_working_directory)
|
|
56
56
|
end
|
|
57
57
|
end
|
data/lib/rubocop/lsp/server.rb
CHANGED
|
@@ -51,8 +51,8 @@ module RuboCop
|
|
|
51
51
|
@runtime.format(path, text, command: command)
|
|
52
52
|
end
|
|
53
53
|
|
|
54
|
-
def offenses(path, text
|
|
55
|
-
@runtime.offenses(path, text
|
|
54
|
+
def offenses(path, text)
|
|
55
|
+
@runtime.offenses(path, text)
|
|
56
56
|
end
|
|
57
57
|
|
|
58
58
|
def configure(options)
|
|
@@ -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; ' \
|