rubocop 1.60.0 → 1.61.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.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/assets/output.css.erb +159 -0
- data/assets/output.html.erb +1 -160
- data/config/default.yml +35 -12
- data/lib/rubocop/cli/command/lsp.rb +2 -2
- data/lib/rubocop/cli.rb +6 -1
- data/lib/rubocop/config_finder.rb +12 -2
- data/lib/rubocop/config_validator.rb +14 -5
- data/lib/rubocop/cop/autocorrect_logic.rb +6 -1
- data/lib/rubocop/cop/base.rb +12 -7
- data/lib/rubocop/cop/correctors/each_to_for_corrector.rb +4 -8
- data/lib/rubocop/cop/correctors/for_to_each_corrector.rb +5 -13
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +2 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +4 -4
- data/lib/rubocop/cop/internal_affairs/method_name_end_with.rb +8 -6
- data/lib/rubocop/cop/internal_affairs/redundant_expect_offense_arguments.rb +34 -0
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/end_alignment.rb +3 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +7 -1
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +19 -10
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +14 -9
- data/lib/rubocop/cop/lint/rescue_type.rb +1 -3
- data/lib/rubocop/cop/lint/script_permission.rb +3 -3
- data/lib/rubocop/cop/lint/syntax.rb +1 -1
- data/lib/rubocop/cop/lint/void.rb +6 -1
- data/lib/rubocop/cop/naming/predicate_name.rb +2 -2
- data/lib/rubocop/cop/registry.rb +5 -5
- data/lib/rubocop/cop/style/arguments_forwarding.rb +69 -13
- data/lib/rubocop/cop/style/case_like_if.rb +1 -1
- data/lib/rubocop/cop/style/collection_compact.rb +11 -2
- data/lib/rubocop/cop/style/commented_keyword.rb +5 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +4 -5
- data/lib/rubocop/cop/style/hash_each_methods.rb +26 -5
- data/lib/rubocop/cop/style/hash_syntax.rb +6 -2
- data/lib/rubocop/cop/style/inverse_methods.rb +8 -8
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -5
- data/lib/rubocop/cop/style/map_compact_with_conditional_block.rb +5 -8
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +4 -0
- data/lib/rubocop/cop/style/object_then.rb +5 -3
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
- data/lib/rubocop/cop/style/raise_args.rb +3 -0
- data/lib/rubocop/cop/style/redundant_argument.rb +2 -2
- data/lib/rubocop/cop/style/redundant_assignment.rb +10 -2
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +16 -5
- data/lib/rubocop/cop/style/redundant_parentheses.rb +8 -1
- data/lib/rubocop/cop/style/redundant_return.rb +6 -0
- data/lib/rubocop/cop/style/sample.rb +1 -3
- data/lib/rubocop/cops_documentation_generator.rb +4 -2
- data/lib/rubocop/formatter/html_formatter.rb +30 -10
- data/lib/rubocop/formatter/offense_count_formatter.rb +12 -2
- data/lib/rubocop/lsp/logger.rb +1 -1
- data/lib/rubocop/lsp/routes.rb +1 -1
- data/lib/rubocop/lsp/runtime.rb +1 -1
- data/lib/rubocop/lsp/server.rb +5 -2
- data/lib/rubocop/lsp/severity.rb +1 -1
- data/lib/rubocop/lsp.rb +29 -0
- data/lib/rubocop/options.rb +11 -0
- data/lib/rubocop/path_util.rb +6 -2
- data/lib/rubocop/rspec/shared_contexts.rb +10 -6
- data/lib/rubocop/rspec/support.rb +1 -1
- data/lib/rubocop/server/cache.rb +1 -1
- data/lib/rubocop/server/client_command/exec.rb +0 -1
- data/lib/rubocop/server/server_command/exec.rb +0 -1
- data/lib/rubocop/target_ruby.rb +79 -79
- data/lib/rubocop/version.rb +1 -1
- metadata +11 -8
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative '../../directive_comment'
|
|
4
|
+
|
|
3
5
|
module RuboCop
|
|
4
6
|
module Cop
|
|
5
7
|
module Style
|
|
@@ -49,8 +51,9 @@ module RuboCop
|
|
|
49
51
|
KEYWORDS = %w[begin class def end module].freeze
|
|
50
52
|
KEYWORD_REGEXES = KEYWORDS.map { |w| /^\s*#{w}\s/ }.freeze
|
|
51
53
|
|
|
52
|
-
ALLOWED_COMMENTS = %w[:nodoc: :yields:
|
|
53
|
-
ALLOWED_COMMENT_REGEXES = ALLOWED_COMMENTS.map { |c| /#\s*#{c}/ }
|
|
54
|
+
ALLOWED_COMMENTS = %w[:nodoc: :yields:].freeze
|
|
55
|
+
ALLOWED_COMMENT_REGEXES = (ALLOWED_COMMENTS.map { |c| /#\s*#{c}/ } +
|
|
56
|
+
[DirectiveComment::DIRECTIVE_COMMENT_REGEXP]).freeze
|
|
54
57
|
|
|
55
58
|
REGEXP = /(?<keyword>\S+).*#/.freeze
|
|
56
59
|
|
|
@@ -115,8 +115,8 @@ module RuboCop
|
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
# Check for `if` and `case` statements where each branch is used for
|
|
118
|
-
#
|
|
119
|
-
# condition can be used instead.
|
|
118
|
+
# both the assignment and comparison of the same variable
|
|
119
|
+
# when using the return of the condition can be used instead.
|
|
120
120
|
#
|
|
121
121
|
# @example EnforcedStyle: assign_to_condition (default)
|
|
122
122
|
# # bad
|
|
@@ -460,9 +460,8 @@ module RuboCop
|
|
|
460
460
|
|
|
461
461
|
def assignment(node)
|
|
462
462
|
*_, condition = *node
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
condition.source_range.begin_pos)
|
|
463
|
+
|
|
464
|
+
node.source_range.begin.join(condition.source_range.begin)
|
|
466
465
|
end
|
|
467
466
|
|
|
468
467
|
def correct_if_branches(corrector, cop, node)
|
|
@@ -40,6 +40,7 @@ module RuboCop
|
|
|
40
40
|
|
|
41
41
|
MSG = 'Use `%<prefer>s` instead of `%<current>s`.'
|
|
42
42
|
UNUSED_BLOCK_ARG_MSG = "#{MSG.chop} and remove the unused `%<unused_code>s` block argument."
|
|
43
|
+
ARRAY_CONVERTER_METHODS = %i[assoc flatten rassoc sort sort_by to_a].freeze
|
|
43
44
|
|
|
44
45
|
# @!method kv_each(node)
|
|
45
46
|
def_node_matcher :kv_each, <<~PATTERN
|
|
@@ -56,7 +57,6 @@ module RuboCop
|
|
|
56
57
|
(call $(call _ ${:keys :values}) :each (block_pass (sym _)))
|
|
57
58
|
PATTERN
|
|
58
59
|
|
|
59
|
-
# rubocop:disable Metrics/AbcSize
|
|
60
60
|
def on_block(node)
|
|
61
61
|
return unless handleable?(node)
|
|
62
62
|
|
|
@@ -66,12 +66,24 @@ module RuboCop
|
|
|
66
66
|
|
|
67
67
|
return unless (key, value = each_arguments(node))
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
check_unused_block_args(node, key, value)
|
|
70
|
+
end
|
|
71
|
+
alias on_numblock on_block
|
|
72
|
+
|
|
73
|
+
# rubocop:disable Metrics/AbcSize
|
|
74
|
+
def check_unused_block_args(node, key, value)
|
|
75
|
+
return if node.body.nil?
|
|
76
|
+
|
|
77
|
+
value_unused = unused_block_arg_exist?(node, value)
|
|
78
|
+
key_unused = unused_block_arg_exist?(node, key)
|
|
79
|
+
return if value_unused && key_unused
|
|
80
|
+
|
|
81
|
+
if value_unused
|
|
70
82
|
message = message('each_key', node.method_name, value.source)
|
|
71
83
|
unused_range = key.source_range.end.join(value.source_range.end)
|
|
72
84
|
|
|
73
85
|
register_each_args_offense(node, message, 'each_key', unused_range)
|
|
74
|
-
elsif
|
|
86
|
+
elsif key_unused
|
|
75
87
|
message = message('each_value', node.method_name, key.source)
|
|
76
88
|
unused_range = key.source_range.begin.join(value.source_range.begin)
|
|
77
89
|
|
|
@@ -80,8 +92,6 @@ module RuboCop
|
|
|
80
92
|
end
|
|
81
93
|
# rubocop:enable Metrics/AbcSize
|
|
82
94
|
|
|
83
|
-
alias on_numblock on_block
|
|
84
|
-
|
|
85
95
|
def on_block_pass(node)
|
|
86
96
|
kv_each_with_block_pass(node.parent) do |target, method|
|
|
87
97
|
register_kv_with_block_pass_offense(node, target, method)
|
|
@@ -91,6 +101,7 @@ module RuboCop
|
|
|
91
101
|
private
|
|
92
102
|
|
|
93
103
|
def handleable?(node)
|
|
104
|
+
return false if use_array_converter_method_as_preceding?(node)
|
|
94
105
|
return false unless (root_receiver = root_receiver(node))
|
|
95
106
|
|
|
96
107
|
!root_receiver.literal? || root_receiver.hash_type?
|
|
@@ -143,6 +154,16 @@ module RuboCop
|
|
|
143
154
|
end
|
|
144
155
|
end
|
|
145
156
|
|
|
157
|
+
def use_array_converter_method_as_preceding?(node)
|
|
158
|
+
return false unless (preceding_method = node.children.first.children.first)
|
|
159
|
+
unless preceding_method.call_type? ||
|
|
160
|
+
preceding_method.block_type? || preceding_method.numblock_type?
|
|
161
|
+
return false
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
ARRAY_CONVERTER_METHODS.include?(preceding_method.method_name)
|
|
165
|
+
end
|
|
166
|
+
|
|
146
167
|
def root_receiver(node)
|
|
147
168
|
receiver = node.receiver
|
|
148
169
|
if receiver&.receiver
|
|
@@ -195,6 +195,7 @@ module RuboCop
|
|
|
195
195
|
acceptable_19_syntax_symbol?(pair.key.source)
|
|
196
196
|
end
|
|
197
197
|
|
|
198
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
198
199
|
def acceptable_19_syntax_symbol?(sym_name)
|
|
199
200
|
sym_name.delete_prefix!(':')
|
|
200
201
|
|
|
@@ -209,9 +210,12 @@ module RuboCop
|
|
|
209
210
|
# Most hash keys can be matched against a simple regex.
|
|
210
211
|
return true if /\A[_a-z]\w*[?!]?\z/i.match?(sym_name)
|
|
211
212
|
|
|
212
|
-
|
|
213
|
-
|
|
213
|
+
return false if target_ruby_version <= 2.1
|
|
214
|
+
|
|
215
|
+
(sym_name.start_with?("'") && sym_name.end_with?("'")) ||
|
|
216
|
+
(sym_name.start_with?('"') && sym_name.end_with?('"'))
|
|
214
217
|
end
|
|
218
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
215
219
|
|
|
216
220
|
def check(pairs, delim, msg)
|
|
217
221
|
pairs.each do |pair|
|
|
@@ -76,9 +76,9 @@ module RuboCop
|
|
|
76
76
|
PATTERN
|
|
77
77
|
|
|
78
78
|
def on_send(node)
|
|
79
|
-
inverse_candidate?(node) do |
|
|
79
|
+
inverse_candidate?(node) do |method_call, lhs, method, rhs|
|
|
80
80
|
return unless inverse_methods.key?(method)
|
|
81
|
-
return if negated?(node)
|
|
81
|
+
return if negated?(node) || relational_comparison_with_safe_navigation?(method_call)
|
|
82
82
|
return if part_of_ignored_node?(node)
|
|
83
83
|
return if possible_class_hierarchy_check?(lhs, rhs, method)
|
|
84
84
|
|
|
@@ -155,16 +155,16 @@ module RuboCop
|
|
|
155
155
|
node.parent.respond_to?(:method?) && node.parent.method?(:!)
|
|
156
156
|
end
|
|
157
157
|
|
|
158
|
+
def relational_comparison_with_safe_navigation?(node)
|
|
159
|
+
node.csend_type? && CLASS_COMPARISON_METHODS.include?(node.method_name)
|
|
160
|
+
end
|
|
161
|
+
|
|
158
162
|
def not_to_receiver(node, method_call)
|
|
159
|
-
|
|
160
|
-
node.loc.selector.begin_pos,
|
|
161
|
-
method_call.source_range.begin_pos)
|
|
163
|
+
node.loc.selector.begin.join(method_call.source_range.begin)
|
|
162
164
|
end
|
|
163
165
|
|
|
164
166
|
def end_parentheses(node, method_call)
|
|
165
|
-
|
|
166
|
-
method_call.source_range.end_pos,
|
|
167
|
-
node.source_range.end_pos)
|
|
167
|
+
method_call.source_range.end.join(node.source_range.end)
|
|
168
168
|
end
|
|
169
169
|
|
|
170
170
|
# When comparing classes, `!(Integer < Numeric)` is not the same as
|
|
@@ -32,12 +32,14 @@ module RuboCop
|
|
|
32
32
|
# foo unless x != y
|
|
33
33
|
# foo unless x >= 10
|
|
34
34
|
# foo unless x.even?
|
|
35
|
+
# foo unless odd?
|
|
35
36
|
#
|
|
36
37
|
# # good
|
|
37
38
|
# foo if bar
|
|
38
39
|
# foo if x == y
|
|
39
40
|
# foo if x < 10
|
|
40
41
|
# foo if x.odd?
|
|
42
|
+
# foo if even?
|
|
41
43
|
#
|
|
42
44
|
# # bad (complex condition)
|
|
43
45
|
# foo unless x != y || x.even?
|
|
@@ -99,12 +101,15 @@ module RuboCop
|
|
|
99
101
|
end
|
|
100
102
|
end
|
|
101
103
|
|
|
102
|
-
def preferred_send_condition(node)
|
|
103
|
-
receiver_source = node.receiver
|
|
104
|
+
def preferred_send_condition(node) # rubocop:disable Metrics/CyclomaticComplexity
|
|
105
|
+
receiver_source = node.receiver&.source
|
|
104
106
|
return receiver_source if node.method?(:!)
|
|
105
107
|
|
|
108
|
+
# receiver may be implicit (self)
|
|
109
|
+
dotted_receiver_source = receiver_source ? "#{receiver_source}." : ''
|
|
110
|
+
|
|
106
111
|
inverse_method_name = inverse_methods[node.method_name]
|
|
107
|
-
return "#{
|
|
112
|
+
return "#{dotted_receiver_source}#{inverse_method_name}" unless node.arguments?
|
|
108
113
|
|
|
109
114
|
argument_list = node.arguments.map(&:source).join(', ')
|
|
110
115
|
if node.operator_method?
|
|
@@ -112,10 +117,10 @@ module RuboCop
|
|
|
112
117
|
end
|
|
113
118
|
|
|
114
119
|
if node.parenthesized?
|
|
115
|
-
return "#{
|
|
120
|
+
return "#{dotted_receiver_source}#{inverse_method_name}(#{argument_list})"
|
|
116
121
|
end
|
|
117
122
|
|
|
118
|
-
"#{
|
|
123
|
+
"#{dotted_receiver_source}#{inverse_method_name} #{argument_list}"
|
|
119
124
|
end
|
|
120
125
|
|
|
121
126
|
def preferred_logical_condition(node)
|
|
@@ -116,20 +116,17 @@ module RuboCop
|
|
|
116
116
|
def truthy_branch_for_guard?(node)
|
|
117
117
|
if_node = node.left_sibling
|
|
118
118
|
|
|
119
|
-
if if_node.if?
|
|
120
|
-
if_node.
|
|
121
|
-
|
|
122
|
-
if_node.if_branch.
|
|
119
|
+
if if_node.if?
|
|
120
|
+
if_node.if_branch.arguments.any?
|
|
121
|
+
else
|
|
122
|
+
if_node.if_branch.arguments.none?
|
|
123
123
|
end
|
|
124
124
|
end
|
|
125
125
|
|
|
126
126
|
def range(node)
|
|
127
|
-
buffer = node.source_range.source_buffer
|
|
128
127
|
map_node = node.receiver.send_node
|
|
129
|
-
begin_pos = map_node.loc.selector.begin_pos
|
|
130
|
-
end_pos = node.source_range.end_pos
|
|
131
128
|
|
|
132
|
-
|
|
129
|
+
map_node.loc.selector.join(node.source_range.end)
|
|
133
130
|
end
|
|
134
131
|
end
|
|
135
132
|
end
|
|
@@ -132,7 +132,7 @@ module RuboCop
|
|
|
132
132
|
call_in_match_pattern?(node) ||
|
|
133
133
|
hash_literal_in_arguments?(node) ||
|
|
134
134
|
node.descendants.any? do |n|
|
|
135
|
-
n.forwarded_args_type? || n.block_type? ||
|
|
135
|
+
n.forwarded_args_type? || n.block_type? || n.numblock_type? ||
|
|
136
136
|
ambiguous_literal?(n) || logical_operator?(n)
|
|
137
137
|
end
|
|
138
138
|
end
|
|
@@ -47,7 +47,11 @@ module RuboCop
|
|
|
47
47
|
message = enforce_single_line_ternary_operator?(node) ? MSG_SINGLE_LINE : MSG_IF
|
|
48
48
|
|
|
49
49
|
add_offense(node, message: message) do |corrector|
|
|
50
|
+
next if part_of_ignored_node?(node)
|
|
51
|
+
|
|
50
52
|
autocorrect(corrector, node)
|
|
53
|
+
|
|
54
|
+
ignore_node(node)
|
|
51
55
|
end
|
|
52
56
|
end
|
|
53
57
|
|
|
@@ -46,15 +46,17 @@ module RuboCop
|
|
|
46
46
|
private
|
|
47
47
|
|
|
48
48
|
def check_method_node(node)
|
|
49
|
-
return unless preferred_method(node)
|
|
49
|
+
return unless preferred_method?(node)
|
|
50
50
|
|
|
51
51
|
message = message(node)
|
|
52
52
|
add_offense(node.loc.selector, message: message) do |corrector|
|
|
53
|
-
|
|
53
|
+
prefer = style == :then && node.receiver.nil? ? 'self.then' : style
|
|
54
|
+
|
|
55
|
+
corrector.replace(node.loc.selector, prefer)
|
|
54
56
|
end
|
|
55
57
|
end
|
|
56
58
|
|
|
57
|
-
def preferred_method(node)
|
|
59
|
+
def preferred_method?(node)
|
|
58
60
|
case style
|
|
59
61
|
when :then
|
|
60
62
|
node.method?(:yield_self)
|
|
@@ -289,9 +289,7 @@ module RuboCop
|
|
|
289
289
|
private
|
|
290
290
|
|
|
291
291
|
def modifier_range(node)
|
|
292
|
-
|
|
293
|
-
node.loc.keyword.begin_pos,
|
|
294
|
-
node.source_range.end_pos)
|
|
292
|
+
node.loc.keyword.join(node.source_range.end)
|
|
295
293
|
end
|
|
296
294
|
end
|
|
297
295
|
end
|
|
@@ -16,6 +16,9 @@ module RuboCop
|
|
|
16
16
|
# The exploded style has an `AllowedCompactTypes` configuration
|
|
17
17
|
# option that takes an Array of exception name Strings.
|
|
18
18
|
#
|
|
19
|
+
# @safety
|
|
20
|
+
# This cop is unsafe because `raise Foo` calls `Foo.exception`, not `Foo.new`.
|
|
21
|
+
#
|
|
19
22
|
# @example EnforcedStyle: exploded (default)
|
|
20
23
|
# # bad
|
|
21
24
|
# raise StandardError.new('message')
|
|
@@ -81,14 +81,14 @@ module RuboCop
|
|
|
81
81
|
redundant_argument = redundant_arg_for_method(node.method_name.to_s)
|
|
82
82
|
return false if redundant_argument.nil?
|
|
83
83
|
|
|
84
|
-
node.first_argument == redundant_argument
|
|
84
|
+
node.first_argument.source.sub(/\A'/, '"').sub(/'\z/, '"') == redundant_argument
|
|
85
85
|
end
|
|
86
86
|
|
|
87
87
|
def redundant_arg_for_method(method_name)
|
|
88
88
|
arg = cop_config['Methods'].fetch(method_name) { return }
|
|
89
89
|
|
|
90
90
|
@mem ||= {}
|
|
91
|
-
@mem[method_name] ||=
|
|
91
|
+
@mem[method_name] ||= arg.inspect
|
|
92
92
|
end
|
|
93
93
|
|
|
94
94
|
def argument_range(node)
|
|
@@ -54,12 +54,14 @@ module RuboCop
|
|
|
54
54
|
|
|
55
55
|
private
|
|
56
56
|
|
|
57
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
57
58
|
def check_branch(node)
|
|
58
59
|
return unless node
|
|
59
60
|
|
|
60
61
|
case node.type
|
|
61
|
-
when :case
|
|
62
|
-
when :
|
|
62
|
+
when :case then check_case_node(node)
|
|
63
|
+
when :case_match then check_case_match_node(node)
|
|
64
|
+
when :if then check_if_node(node)
|
|
63
65
|
when :rescue, :resbody
|
|
64
66
|
check_rescue_node(node)
|
|
65
67
|
when :ensure then check_ensure_node(node)
|
|
@@ -67,12 +69,18 @@ module RuboCop
|
|
|
67
69
|
check_begin_node(node)
|
|
68
70
|
end
|
|
69
71
|
end
|
|
72
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
70
73
|
|
|
71
74
|
def check_case_node(node)
|
|
72
75
|
node.when_branches.each { |when_node| check_branch(when_node.body) }
|
|
73
76
|
check_branch(node.else_branch)
|
|
74
77
|
end
|
|
75
78
|
|
|
79
|
+
def check_case_match_node(node)
|
|
80
|
+
node.in_pattern_branches.each { |in_pattern_node| check_branch(in_pattern_node.body) }
|
|
81
|
+
check_branch(node.else_branch)
|
|
82
|
+
end
|
|
83
|
+
|
|
76
84
|
def check_if_node(node)
|
|
77
85
|
return if node.modifier_form? || node.ternary?
|
|
78
86
|
|
|
@@ -124,8 +124,10 @@ module RuboCop
|
|
|
124
124
|
return true unless (node = find_node_for_line(range.line))
|
|
125
125
|
return false if argument_newline?(node)
|
|
126
126
|
|
|
127
|
-
|
|
128
|
-
|
|
127
|
+
continuation_node = node.parent || node
|
|
128
|
+
return false if allowed_type?(node) || allowed_type?(continuation_node)
|
|
129
|
+
|
|
130
|
+
continuation_node.source.include?("\n") || continuation_node.source.include?("\\\n")
|
|
129
131
|
end
|
|
130
132
|
|
|
131
133
|
def inside_string_literal?(range, token)
|
|
@@ -140,17 +142,22 @@ module RuboCop
|
|
|
140
142
|
current_token.type == :tIDENTIFIER && ARGUMENT_TYPES.include?(next_token.type)
|
|
141
143
|
end
|
|
142
144
|
|
|
145
|
+
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
143
146
|
def argument_newline?(node)
|
|
147
|
+
node = node.to_a.last if node.assignment?
|
|
148
|
+
return false if node.parenthesized_call?
|
|
149
|
+
|
|
144
150
|
node = node.children.first if node.root? && node.begin_type?
|
|
145
151
|
|
|
146
|
-
if argument_is_method?(node)
|
|
147
|
-
argument_newline?(node.
|
|
152
|
+
if argument_is_method?(node) || node.begin_type?
|
|
153
|
+
argument_newline?(node.children.first)
|
|
148
154
|
else
|
|
149
155
|
return false unless method_call_with_arguments?(node)
|
|
150
156
|
|
|
151
|
-
node
|
|
157
|
+
!same_line?(node, node.first_argument)
|
|
152
158
|
end
|
|
153
159
|
end
|
|
160
|
+
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
154
161
|
|
|
155
162
|
def find_node_for_line(line)
|
|
156
163
|
processed_source.ast.each_node do |node|
|
|
@@ -158,6 +165,10 @@ module RuboCop
|
|
|
158
165
|
end
|
|
159
166
|
end
|
|
160
167
|
|
|
168
|
+
def allowed_type?(node)
|
|
169
|
+
node.and_type? || node.or_type? || (node.if_type? && node.ternary?)
|
|
170
|
+
end
|
|
171
|
+
|
|
161
172
|
def same_line?(node, line)
|
|
162
173
|
return false unless (source_range = node.source_range)
|
|
163
174
|
|
|
@@ -54,7 +54,7 @@ module RuboCop
|
|
|
54
54
|
return false unless (parent = node.parent)
|
|
55
55
|
|
|
56
56
|
parent.while_post_type? || parent.until_post_type? || parent.match_with_lvasgn_type? ||
|
|
57
|
-
like_method_argument_parentheses?(parent)
|
|
57
|
+
like_method_argument_parentheses?(parent) || multiline_control_flow_statements?(node)
|
|
58
58
|
end
|
|
59
59
|
|
|
60
60
|
def allowed_expression?(node)
|
|
@@ -104,6 +104,13 @@ module RuboCop
|
|
|
104
104
|
!node.arithmetic_operation? && node.first_argument.begin_type?
|
|
105
105
|
end
|
|
106
106
|
|
|
107
|
+
def multiline_control_flow_statements?(node)
|
|
108
|
+
return false unless (parent = node.parent)
|
|
109
|
+
return false if parent.single_line?
|
|
110
|
+
|
|
111
|
+
parent.return_type? || parent.next_type? || parent.break_type?
|
|
112
|
+
end
|
|
113
|
+
|
|
107
114
|
def empty_parentheses?(node)
|
|
108
115
|
# Don't flag `()`
|
|
109
116
|
node.children.empty?
|
|
@@ -113,6 +113,7 @@ module RuboCop
|
|
|
113
113
|
case node.type
|
|
114
114
|
when :return then check_return_node(node)
|
|
115
115
|
when :case then check_case_node(node)
|
|
116
|
+
when :case_match then check_case_match_node(node)
|
|
116
117
|
when :if then check_if_node(node)
|
|
117
118
|
when :rescue then check_rescue_node(node)
|
|
118
119
|
when :resbody then check_resbody_node(node)
|
|
@@ -140,6 +141,11 @@ module RuboCop
|
|
|
140
141
|
check_branch(node.else_branch)
|
|
141
142
|
end
|
|
142
143
|
|
|
144
|
+
def check_case_match_node(node)
|
|
145
|
+
node.in_pattern_branches.each { |in_pattern_node| check_branch(in_pattern_node.body) }
|
|
146
|
+
check_branch(node.else_branch)
|
|
147
|
+
end
|
|
148
|
+
|
|
143
149
|
def check_if_node(node)
|
|
144
150
|
return if node.ternary?
|
|
145
151
|
|
|
@@ -110,9 +110,7 @@ module RuboCop
|
|
|
110
110
|
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
111
111
|
|
|
112
112
|
def source_range(shuffle_node, node)
|
|
113
|
-
|
|
114
|
-
shuffle_node.loc.selector.begin_pos,
|
|
115
|
-
node.source_range.end_pos)
|
|
113
|
+
shuffle_node.loc.selector.join(node.source_range.end)
|
|
116
114
|
end
|
|
117
115
|
|
|
118
116
|
def message(shuffle_arg, method, method_args, range)
|
|
@@ -97,7 +97,9 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
97
97
|
'Version Changed'
|
|
98
98
|
]
|
|
99
99
|
autocorrect = if cop.support_autocorrect?
|
|
100
|
-
|
|
100
|
+
context = cop.new.always_autocorrect? ? 'Always' : 'Command-line only'
|
|
101
|
+
|
|
102
|
+
"#{context}#{' (Unsafe)' unless cop.new(config).safe_autocorrect?}"
|
|
101
103
|
else
|
|
102
104
|
'No'
|
|
103
105
|
end
|
|
@@ -276,7 +278,7 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
|
276
278
|
def print_cop_with_doc(cop) # rubocop:todo Metrics/AbcSize, Metrics/MethodLength
|
|
277
279
|
cop_config = config.for_cop(cop)
|
|
278
280
|
non_display_keys = %w[
|
|
279
|
-
Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
|
|
281
|
+
AutoCorrect Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
|
|
280
282
|
VersionChanged
|
|
281
283
|
]
|
|
282
284
|
pars = cop_config.reject { |k| non_display_keys.include? k }
|
|
@@ -9,6 +9,7 @@ module RuboCop
|
|
|
9
9
|
class HTMLFormatter < BaseFormatter
|
|
10
10
|
ELLIPSES = '<span class="extra-code">...</span>'
|
|
11
11
|
TEMPLATE_PATH = File.expand_path('../../../assets/output.html.erb', __dir__)
|
|
12
|
+
CSS_PATH = File.expand_path('../../../assets/output.css.erb', __dir__)
|
|
12
13
|
|
|
13
14
|
Color = Struct.new(:red, :green, :blue, :alpha) do
|
|
14
15
|
def to_s
|
|
@@ -50,8 +51,8 @@ module RuboCop
|
|
|
50
51
|
context = ERBContext.new(files, summary)
|
|
51
52
|
|
|
52
53
|
template = File.read(TEMPLATE_PATH, encoding: Encoding::UTF_8)
|
|
53
|
-
erb = ERB.new(template
|
|
54
|
-
html = erb.result(context.binding)
|
|
54
|
+
erb = ERB.new(template)
|
|
55
|
+
html = erb.result(context.binding).lines.map { (_1 =~ /^\s*$/).nil? ? _1 : "\n" }.join
|
|
55
56
|
|
|
56
57
|
output.write html
|
|
57
58
|
end
|
|
@@ -61,14 +62,6 @@ module RuboCop
|
|
|
61
62
|
include PathUtil
|
|
62
63
|
include TextUtil
|
|
63
64
|
|
|
64
|
-
SEVERITY_COLORS = {
|
|
65
|
-
refactor: Color.new(0xED, 0x9C, 0x28, 1.0),
|
|
66
|
-
convention: Color.new(0xED, 0x9C, 0x28, 1.0),
|
|
67
|
-
warning: Color.new(0x96, 0x28, 0xEF, 1.0),
|
|
68
|
-
error: Color.new(0xD2, 0x32, 0x2D, 1.0),
|
|
69
|
-
fatal: Color.new(0xD2, 0x32, 0x2D, 1.0)
|
|
70
|
-
}.freeze
|
|
71
|
-
|
|
72
65
|
LOGO_IMAGE_PATH = File.expand_path('../../../assets/logo.png', __dir__)
|
|
73
66
|
|
|
74
67
|
attr_reader :files, :summary
|
|
@@ -127,6 +120,33 @@ module RuboCop
|
|
|
127
120
|
# https://github.com/ruby/base64/blob/v0.1.1/lib/base64.rb#L27-L40
|
|
128
121
|
[image].pack('m')
|
|
129
122
|
end
|
|
123
|
+
|
|
124
|
+
def render_css
|
|
125
|
+
context = CSSContext.new
|
|
126
|
+
template = File.read(CSS_PATH, encoding: Encoding::UTF_8)
|
|
127
|
+
erb = ERB.new(template, trim_mode: '-')
|
|
128
|
+
erb.result(context.binding).lines.map do |line|
|
|
129
|
+
line == "\n" ? line : " #{line}"
|
|
130
|
+
end.join
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# This class provides helper methods used in the ERB CSS template.
|
|
135
|
+
class CSSContext
|
|
136
|
+
SEVERITY_COLORS = {
|
|
137
|
+
refactor: Color.new(0xED, 0x9C, 0x28, 1.0),
|
|
138
|
+
convention: Color.new(0xED, 0x9C, 0x28, 1.0),
|
|
139
|
+
warning: Color.new(0x96, 0x28, 0xEF, 1.0),
|
|
140
|
+
error: Color.new(0xD2, 0x32, 0x2D, 1.0),
|
|
141
|
+
fatal: Color.new(0xD2, 0x32, 0x2D, 1.0)
|
|
142
|
+
}.freeze
|
|
143
|
+
|
|
144
|
+
# Make Kernel#binding public.
|
|
145
|
+
# rubocop:disable Lint/UselessMethodDefinition
|
|
146
|
+
def binding
|
|
147
|
+
super
|
|
148
|
+
end
|
|
149
|
+
# rubocop:enable Lint/UselessMethodDefinition
|
|
130
150
|
end
|
|
131
151
|
end
|
|
132
152
|
end
|
|
@@ -61,8 +61,7 @@ module RuboCop
|
|
|
61
61
|
|
|
62
62
|
column_width = total_count.to_s.length + 2
|
|
63
63
|
per_cop_counts.each do |cop_name, count|
|
|
64
|
-
output.puts "#{count.to_s.ljust(column_width)}#{cop_name}"
|
|
65
|
-
"#{@style_guide_links[cop_name]}\n"
|
|
64
|
+
output.puts "#{count.to_s.ljust(column_width)}#{cop_information(cop_name)}"
|
|
66
65
|
end
|
|
67
66
|
output.puts '--'
|
|
68
67
|
output.puts "#{total_count} Total in #{offending_files_count} files"
|
|
@@ -78,6 +77,17 @@ module RuboCop
|
|
|
78
77
|
def total_offense_count(offense_counts)
|
|
79
78
|
offense_counts.values.sum
|
|
80
79
|
end
|
|
80
|
+
|
|
81
|
+
def cop_information(cop_name)
|
|
82
|
+
cop = RuboCop::Cop::Registry.global.find_by_cop_name(cop_name).new
|
|
83
|
+
|
|
84
|
+
if cop.correctable?
|
|
85
|
+
safety = cop.safe_autocorrect? ? 'Safe' : 'Unsafe'
|
|
86
|
+
correctable = Rainbow(" [#{safety} Correctable]").yellow
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
"#{cop_name}#{correctable}#{@style_guide_links[cop_name]}"
|
|
90
|
+
end
|
|
81
91
|
end
|
|
82
92
|
end
|
|
83
93
|
end
|
data/lib/rubocop/lsp/logger.rb
CHANGED
data/lib/rubocop/lsp/routes.rb
CHANGED
data/lib/rubocop/lsp/runtime.rb
CHANGED
data/lib/rubocop/lsp/server.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'language_server-protocol'
|
|
4
|
+
require_relative '../lsp'
|
|
4
5
|
require_relative 'logger'
|
|
5
6
|
require_relative 'routes'
|
|
6
7
|
require_relative 'runtime'
|
|
@@ -15,14 +16,16 @@ require_relative 'runtime'
|
|
|
15
16
|
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
|
16
17
|
#
|
|
17
18
|
module RuboCop
|
|
18
|
-
module
|
|
19
|
+
module LSP
|
|
19
20
|
# Language Server Protocol of RuboCop.
|
|
20
21
|
# @api private
|
|
21
22
|
class Server
|
|
22
23
|
def initialize(config_store)
|
|
24
|
+
RuboCop::LSP.enable
|
|
25
|
+
|
|
23
26
|
@reader = LanguageServer::Protocol::Transport::Io::Reader.new($stdin)
|
|
24
27
|
@writer = LanguageServer::Protocol::Transport::Io::Writer.new($stdout)
|
|
25
|
-
@runtime = RuboCop::
|
|
28
|
+
@runtime = RuboCop::LSP::Runtime.new(config_store)
|
|
26
29
|
@routes = Routes.new(self)
|
|
27
30
|
end
|
|
28
31
|
|