rubocop 1.84.0 → 1.84.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/config/default.yml +7 -4
- data/lib/rubocop/comment_config.rb +33 -34
- data/lib/rubocop/config_loader.rb +10 -19
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +14 -13
- data/lib/rubocop/cop/layout/indentation_width.rb +4 -4
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +155 -39
- data/lib/rubocop/cop/naming/predicate_method.rb +11 -0
- data/lib/rubocop/cop/style/guard_clause.rb +20 -10
- data/lib/rubocop/cop/style/if_unless_modifier.rb +40 -11
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +4 -1
- data/lib/rubocop/cop/style/module_member_existence_check.rb +1 -1
- data/lib/rubocop/cop/style/negative_array_index.rb +2 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +4 -1
- data/lib/rubocop/cop/team.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +8 -20
- data/lib/rubocop/lsp/disable_comment_edits.rb +135 -0
- data/lib/rubocop/lsp/runtime.rb +13 -3
- data/lib/rubocop/lsp/stdin_runner.rb +8 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 358bce5232f7b6e4e490a3d173d09cb4d3df8fc9e92355b550d0047e10e0f462
|
|
4
|
+
data.tar.gz: 8e65d98bd3478db7eee250dd05ffc6fd4f4d17d144207950fc12f5e83f7995f6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4b6cf48e7582909807829dd43e7fd379a9e4ec46cd387659a16321f4fd3ee7a321ac16859ce86870d41fae2602abde14197e1bb91094abb8bf9dd809dc6e648e
|
|
7
|
+
data.tar.gz: c619779f7ac9d8563aadc5f6675333f22d7c8d2300d6ac1c996260d442210f6b2b809f24e7fa1479b6b908a0ca16bc8f61bc23200f3e2f302e03369bce6dafac
|
data/config/default.yml
CHANGED
|
@@ -3113,6 +3113,7 @@ Naming/PredicateMethod:
|
|
|
3113
3113
|
AllowBangMethods: false
|
|
3114
3114
|
# Methods that are known to not return a boolean value, despite ending in `?`.
|
|
3115
3115
|
WaywardPredicates:
|
|
3116
|
+
- infinite?
|
|
3116
3117
|
- nonzero?
|
|
3117
3118
|
|
|
3118
3119
|
Naming/PredicatePrefix:
|
|
@@ -3980,7 +3981,7 @@ Style/EmptyCaseCondition:
|
|
|
3980
3981
|
Style/EmptyClassDefinition:
|
|
3981
3982
|
Description: 'Enforces consistent style for empty class definitions.'
|
|
3982
3983
|
Enabled: pending
|
|
3983
|
-
VersionAdded: '1.
|
|
3984
|
+
VersionAdded: '1.84'
|
|
3984
3985
|
EnforcedStyle: class_definition
|
|
3985
3986
|
SupportedStyles:
|
|
3986
3987
|
- class_definition
|
|
@@ -4341,7 +4342,7 @@ Style/HashLookupMethod:
|
|
|
4341
4342
|
Description: 'Enforces the use of either `Hash#[]` or `Hash#fetch` for hash lookup.'
|
|
4342
4343
|
Enabled: false
|
|
4343
4344
|
Safe: false
|
|
4344
|
-
VersionAdded: '1.
|
|
4345
|
+
VersionAdded: '1.84'
|
|
4345
4346
|
EnforcedStyle: brackets
|
|
4346
4347
|
SupportedStyles:
|
|
4347
4348
|
- brackets
|
|
@@ -4444,6 +4445,7 @@ Style/IfWithBooleanLiteralBranches:
|
|
|
4444
4445
|
VersionAdded: '1.9'
|
|
4445
4446
|
SafeAutoCorrect: false
|
|
4446
4447
|
AllowedMethods:
|
|
4448
|
+
- infinite?
|
|
4447
4449
|
- nonzero?
|
|
4448
4450
|
|
|
4449
4451
|
Style/IfWithSemicolon:
|
|
@@ -4912,7 +4914,7 @@ Style/NegativeArrayIndex:
|
|
|
4912
4914
|
Also handles range patterns with length calculations. Recognizes preserving methods
|
|
4913
4915
|
and their combinations, allowing safe replacement when the receiver matches.
|
|
4914
4916
|
Enabled: pending
|
|
4915
|
-
VersionAdded: '1.
|
|
4917
|
+
VersionAdded: '1.84'
|
|
4916
4918
|
|
|
4917
4919
|
Style/NestedFileDirname:
|
|
4918
4920
|
Description: 'Checks for nested `File.dirname`.'
|
|
@@ -5317,6 +5319,7 @@ Style/RedundantCondition:
|
|
|
5317
5319
|
VersionAdded: '0.76'
|
|
5318
5320
|
VersionChanged: '1.73'
|
|
5319
5321
|
AllowedMethods:
|
|
5322
|
+
- infinite?
|
|
5320
5323
|
- nonzero?
|
|
5321
5324
|
|
|
5322
5325
|
Style/RedundantConditional:
|
|
@@ -5569,7 +5572,7 @@ Style/ReverseFind:
|
|
|
5569
5572
|
Description: 'Use `array.rfind` instead of `array.reverse.find`.'
|
|
5570
5573
|
Enabled: pending
|
|
5571
5574
|
Safe: false
|
|
5572
|
-
VersionAdded: '1.
|
|
5575
|
+
VersionAdded: '1.84'
|
|
5573
5576
|
|
|
5574
5577
|
Style/SafeNavigation:
|
|
5575
5578
|
Description: >-
|
|
@@ -103,8 +103,9 @@ module RuboCop
|
|
|
103
103
|
|
|
104
104
|
each_directive do |directive|
|
|
105
105
|
if directive.push?
|
|
106
|
-
|
|
107
|
-
|
|
106
|
+
resolved = resolve_push_cops(directive)
|
|
107
|
+
@stack.push(snapshot_cops(analyses, resolved.values.flatten))
|
|
108
|
+
apply_push(analyses, resolved, directive.line_number)
|
|
108
109
|
elsif directive.pop?
|
|
109
110
|
pop_state(analyses, directive.line_number) if @stack.any?
|
|
110
111
|
else
|
|
@@ -121,48 +122,46 @@ module RuboCop
|
|
|
121
122
|
end
|
|
122
123
|
end
|
|
123
124
|
|
|
124
|
-
def
|
|
125
|
-
|
|
125
|
+
def snapshot_cops(analyses, cop_names)
|
|
126
|
+
cop_names.to_h { |name| [name, analyses[name].dup] }
|
|
126
127
|
end
|
|
127
128
|
|
|
128
|
-
def
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
analyses[cop_name] = CopAnalysis.new(
|
|
133
|
-
analysis.line_ranges + [analysis.start_line_number...pop_line], nil
|
|
134
|
-
)
|
|
129
|
+
def resolve_push_cops(directive)
|
|
130
|
+
directive.push_args.transform_values do |names|
|
|
131
|
+
names.flat_map { |name| expand_cop_name(name) }
|
|
135
132
|
end
|
|
133
|
+
end
|
|
136
134
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
end
|
|
135
|
+
def expand_cop_name(name)
|
|
136
|
+
registry = Cop::Registry.global
|
|
137
|
+
cops = registry.department?(name) ? registry.names_for_department(name) : [name]
|
|
138
|
+
cops.map { |c| qualified_cop_name(c) }
|
|
142
139
|
end
|
|
143
140
|
|
|
144
|
-
def
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
apply_cop_operation(analyses, operation, qualified_cop_name(cop_name),
|
|
148
|
-
directive.line_number)
|
|
149
|
-
end
|
|
141
|
+
def apply_push(analyses, resolved_cops, line)
|
|
142
|
+
resolved_cops.each do |op, cops|
|
|
143
|
+
cops.each { |cop| apply_cop_op(analyses, op, cop, line) }
|
|
150
144
|
end
|
|
151
145
|
end
|
|
152
146
|
|
|
153
|
-
def
|
|
154
|
-
analysis = analyses[
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
when '-' # Disable cop
|
|
163
|
-
return if start_line
|
|
147
|
+
def apply_cop_op(analyses, operation, cop, line)
|
|
148
|
+
analysis = analyses[cop]
|
|
149
|
+
if operation == '-' && !analysis.start_line_number
|
|
150
|
+
analyses[cop] = CopAnalysis.new(analysis.line_ranges, line)
|
|
151
|
+
elsif operation == '+' && analysis.start_line_number
|
|
152
|
+
analyses[cop] =
|
|
153
|
+
CopAnalysis.new(analysis.line_ranges + [analysis.start_line_number..line], nil)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
164
156
|
|
|
165
|
-
|
|
157
|
+
def pop_state(analyses, line)
|
|
158
|
+
saved = @stack.pop
|
|
159
|
+
saved.each do |cop, old|
|
|
160
|
+
cur = analyses[cop]
|
|
161
|
+
new_range = cur.start_line_number ? [cur.start_line_number..(line - 1)] : []
|
|
162
|
+
ranges = cur.line_ranges + new_range
|
|
163
|
+
new_start = old.start_line_number ? line : nil
|
|
164
|
+
analyses[cop] = CopAnalysis.new(ranges, new_start)
|
|
166
165
|
end
|
|
167
166
|
end
|
|
168
167
|
|
|
@@ -151,31 +151,22 @@ module RuboCop
|
|
|
151
151
|
# When testing a plugin using `rubocop/rspec/support`, the plugin is loaded automatically,
|
|
152
152
|
# so this API is usually not needed. It is intended to be used only when implementing tests
|
|
153
153
|
# that do not use `rubocop/rspec/support`.
|
|
154
|
-
# rubocop:disable Metrics/MethodLength
|
|
155
154
|
def inject_defaults!(config_yml_path)
|
|
156
155
|
if Pathname(config_yml_path).directory?
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
Use config YAML file path instead of project root directory.
|
|
164
|
-
e.g., `path/to/config/default.yml`
|
|
165
|
-
MESSAGE
|
|
166
|
-
end
|
|
167
|
-
# NOTE: For compatibility.
|
|
168
|
-
project_root = config_yml_path
|
|
169
|
-
path = File.join(project_root, 'config', 'default.yml')
|
|
170
|
-
config = load_file(path)
|
|
171
|
-
else
|
|
172
|
-
hash = ConfigLoader.load_yaml_configuration(config_yml_path.to_s)
|
|
173
|
-
config = Config.new(hash, config_yml_path).tap(&:make_excludes_absolute)
|
|
156
|
+
warn Rainbow(<<~MESSAGE).yellow, uplevel: 1
|
|
157
|
+
Use config YAML file path instead of project root directory.
|
|
158
|
+
e.g., `path/to/config/default.yml`
|
|
159
|
+
MESSAGE
|
|
160
|
+
raise ArgumentError,
|
|
161
|
+
'Passing a project root directory to `inject_defaults!` is no longer supported.'
|
|
174
162
|
end
|
|
175
163
|
|
|
164
|
+
path = config_yml_path.to_s
|
|
165
|
+
hash = ConfigLoader.load_yaml_configuration(path)
|
|
166
|
+
config = Config.new(hash, path).tap(&:make_excludes_absolute)
|
|
167
|
+
|
|
176
168
|
@default_configuration = ConfigLoader.merge_with_default(config, path)
|
|
177
169
|
end
|
|
178
|
-
# rubocop:enable Metrics/MethodLength
|
|
179
170
|
|
|
180
171
|
# Returns the path RuboCop inferred as the root of the project. No file
|
|
181
172
|
# searches will go past this directory.
|
|
@@ -179,15 +179,24 @@ module RuboCop
|
|
|
179
179
|
|
|
180
180
|
top_level_send = find_top_level_send(send_node)
|
|
181
181
|
node_to_correct =
|
|
182
|
-
|
|
183
|
-
top_level_send
|
|
184
|
-
else
|
|
185
|
-
node
|
|
186
|
-
end
|
|
182
|
+
should_correct_entire_chain?(send_node, top_level_send) ? top_level_send : node
|
|
187
183
|
|
|
188
184
|
AlignmentCorrector.correct(corrector, processed_source, node_to_correct, column_delta)
|
|
189
185
|
end
|
|
190
186
|
|
|
187
|
+
def should_correct_entire_chain?(send_node, top_level_send)
|
|
188
|
+
return false unless style == :special_for_inner_method_call_in_parentheses
|
|
189
|
+
return false unless inner_call?(top_level_send)
|
|
190
|
+
|
|
191
|
+
top_level_send != send_node || begins_its_line?(top_level_send.loc.end)
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def inner_call?(top_level_send)
|
|
195
|
+
outer_call = top_level_send.parent
|
|
196
|
+
|
|
197
|
+
outer_call&.send_type? && outer_call.parenthesized?
|
|
198
|
+
end
|
|
199
|
+
|
|
191
200
|
def find_top_level_send(send_node)
|
|
192
201
|
top_level_send = send_node
|
|
193
202
|
while top_level_send.parent&.send_type? &&
|
|
@@ -198,14 +207,6 @@ module RuboCop
|
|
|
198
207
|
top_level_send
|
|
199
208
|
end
|
|
200
209
|
|
|
201
|
-
def should_correct_entire_method_call?(send_node)
|
|
202
|
-
return false unless style == :special_for_inner_method_call_in_parentheses
|
|
203
|
-
return false unless special_inner_call_indentation?(send_node)
|
|
204
|
-
|
|
205
|
-
closing_paren = send_node.loc.end
|
|
206
|
-
closing_paren && begins_its_line?(closing_paren)
|
|
207
|
-
end
|
|
208
|
-
|
|
209
210
|
def bare_operator?(node)
|
|
210
211
|
node.operator_method? && !node.dot?
|
|
211
212
|
end
|
|
@@ -424,7 +424,7 @@ module RuboCop
|
|
|
424
424
|
end
|
|
425
425
|
|
|
426
426
|
def contains_access_modifier?(body_node)
|
|
427
|
-
return false unless body_node
|
|
427
|
+
return false unless body_node&.begin_type?
|
|
428
428
|
|
|
429
429
|
body_node.children.any? { |child| child.send_type? && child.bare_access_modifier? }
|
|
430
430
|
end
|
|
@@ -473,10 +473,10 @@ module RuboCop
|
|
|
473
473
|
end
|
|
474
474
|
|
|
475
475
|
def block_body_indentation_base(node, end_loc)
|
|
476
|
-
if
|
|
477
|
-
end_loc
|
|
478
|
-
else
|
|
476
|
+
if dot_on_new_line?(node)
|
|
479
477
|
node.send_node.loc.dot
|
|
478
|
+
else
|
|
479
|
+
end_loc
|
|
480
480
|
end
|
|
481
481
|
end
|
|
482
482
|
|
|
@@ -46,10 +46,12 @@ module RuboCop
|
|
|
46
46
|
# .a
|
|
47
47
|
# .b
|
|
48
48
|
# .c
|
|
49
|
-
|
|
49
|
+
#
|
|
50
|
+
class MultilineMethodCallIndentation < Base # rubocop:disable Metrics/ClassLength
|
|
50
51
|
include ConfigurableEnforcedStyle
|
|
51
52
|
include Alignment
|
|
52
53
|
include MultilineExpressionIndentation
|
|
54
|
+
include RangeHelp
|
|
53
55
|
extend AutoCorrector
|
|
54
56
|
|
|
55
57
|
def validate_config
|
|
@@ -64,8 +66,39 @@ module RuboCop
|
|
|
64
66
|
|
|
65
67
|
private
|
|
66
68
|
|
|
69
|
+
def find_base_receiver(node)
|
|
70
|
+
base_receiver = node
|
|
71
|
+
base_receiver = base_receiver.receiver while base_receiver.receiver
|
|
72
|
+
base_receiver
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def find_pair_ancestor(node)
|
|
76
|
+
node.each_ancestor.find(&:pair_type?)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def unwrap_block_node(node)
|
|
80
|
+
node&.any_block_type? ? node.send_node : node
|
|
81
|
+
end
|
|
82
|
+
|
|
67
83
|
def autocorrect(corrector, node)
|
|
68
|
-
|
|
84
|
+
if @send_node.block_node
|
|
85
|
+
correct_selector_only(corrector, node)
|
|
86
|
+
correct_block(corrector, @send_node.block_node)
|
|
87
|
+
else
|
|
88
|
+
AlignmentCorrector.correct(corrector, processed_source, node, @column_delta)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def correct_selector_only(corrector, node)
|
|
93
|
+
selector_line = processed_source.buffer.line_range(node.first_line)
|
|
94
|
+
selector_range = range_between(selector_line.begin_pos, selector_line.end_pos)
|
|
95
|
+
AlignmentCorrector.correct(corrector, processed_source, selector_range, @column_delta)
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def correct_block(corrector, block_node)
|
|
99
|
+
AlignmentCorrector.correct(corrector, processed_source, block_node.body, @column_delta)
|
|
100
|
+
end_range = range_by_whole_lines(block_node.loc.end, include_final_newline: false)
|
|
101
|
+
AlignmentCorrector.correct(corrector, processed_source, end_range, @column_delta)
|
|
69
102
|
end
|
|
70
103
|
|
|
71
104
|
def relevant_node?(send_node)
|
|
@@ -84,11 +117,55 @@ module RuboCop
|
|
|
84
117
|
end
|
|
85
118
|
end
|
|
86
119
|
|
|
87
|
-
# rubocop:disable Metrics/AbcSize
|
|
88
120
|
def offending_range(node, lhs, rhs, given_style)
|
|
89
121
|
return false unless begins_its_line?(rhs)
|
|
90
|
-
return false if not_for_this_cop?(node)
|
|
91
122
|
|
|
123
|
+
@send_node = node # Store for use in autocorrect
|
|
124
|
+
pair_ancestor = find_pair_ancestor(node)
|
|
125
|
+
if hash_pair_aligned?(pair_ancestor, given_style)
|
|
126
|
+
return check_hash_pair_indentation(node, lhs, rhs)
|
|
127
|
+
end
|
|
128
|
+
if hash_pair_indented?(node, pair_ancestor, given_style)
|
|
129
|
+
return check_hash_pair_indented_style(rhs, pair_ancestor)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
return false if !pair_ancestor && not_for_this_cop?(node)
|
|
133
|
+
|
|
134
|
+
check_regular_indentation(node, lhs, rhs, given_style)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def hash_pair_aligned?(pair_ancestor, given_style)
|
|
138
|
+
pair_ancestor && given_style == :aligned
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def hash_pair_indented?(node, pair_ancestor, given_style)
|
|
142
|
+
pair_ancestor && given_style == :indented && find_base_receiver(node).hash_type?
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
def check_hash_pair_indented_style(rhs, pair_ancestor)
|
|
146
|
+
pair_key = pair_ancestor.key
|
|
147
|
+
double_indentation = configured_indentation_width * 2
|
|
148
|
+
correct_column = pair_key.source_range.column + double_indentation
|
|
149
|
+
@hash_pair_base_column = pair_key.source_range.column + configured_indentation_width
|
|
150
|
+
|
|
151
|
+
calculate_column_delta_offense(rhs, correct_column)
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def check_hash_pair_indentation(node, lhs, rhs)
|
|
155
|
+
@base = find_hash_pair_alignment_base(node) || lhs.source_range
|
|
156
|
+
|
|
157
|
+
calculate_column_delta_offense(rhs, @base.column)
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def find_hash_pair_alignment_base(node)
|
|
161
|
+
base_receiver = find_base_receiver(node.receiver)
|
|
162
|
+
return unless base_receiver.hash_type?
|
|
163
|
+
|
|
164
|
+
first_call = first_call_has_a_dot(node)
|
|
165
|
+
first_call.loc.dot.join(first_call.loc.selector)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def check_regular_indentation(node, lhs, rhs, given_style)
|
|
92
169
|
@base = alignment_base(node, rhs, given_style)
|
|
93
170
|
correct_column = if @base
|
|
94
171
|
parent = node.parent
|
|
@@ -97,20 +174,22 @@ module RuboCop
|
|
|
97
174
|
else
|
|
98
175
|
indentation(lhs) + correct_indentation(node)
|
|
99
176
|
end
|
|
177
|
+
|
|
178
|
+
calculate_column_delta_offense(rhs, correct_column)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
def calculate_column_delta_offense(rhs, correct_column)
|
|
100
182
|
@column_delta = correct_column - rhs.column
|
|
101
183
|
rhs if @column_delta.nonzero?
|
|
102
184
|
end
|
|
103
|
-
# rubocop:enable Metrics/AbcSize
|
|
104
185
|
|
|
105
186
|
def extra_indentation(given_style, parent)
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
configured_indentation_width
|
|
111
|
-
end
|
|
187
|
+
return 0 unless given_style == :indented_relative_to_receiver
|
|
188
|
+
|
|
189
|
+
if parent&.type?(:splat, :kwsplat)
|
|
190
|
+
configured_indentation_width - parent.loc.operator.length
|
|
112
191
|
else
|
|
113
|
-
|
|
192
|
+
configured_indentation_width
|
|
114
193
|
end
|
|
115
194
|
end
|
|
116
195
|
|
|
@@ -129,7 +208,7 @@ module RuboCop
|
|
|
129
208
|
end
|
|
130
209
|
|
|
131
210
|
def should_align_with_base?
|
|
132
|
-
@base && style
|
|
211
|
+
@base && style == :aligned
|
|
133
212
|
end
|
|
134
213
|
|
|
135
214
|
def relative_to_receiver_message(rhs)
|
|
@@ -146,10 +225,16 @@ module RuboCop
|
|
|
146
225
|
end
|
|
147
226
|
|
|
148
227
|
def no_base_message(lhs, rhs, node)
|
|
149
|
-
|
|
228
|
+
if @hash_pair_base_column
|
|
229
|
+
used_indentation = rhs.column - @hash_pair_base_column
|
|
230
|
+
expected_indentation = configured_indentation_width
|
|
231
|
+
else
|
|
232
|
+
used_indentation = rhs.column - indentation(lhs)
|
|
233
|
+
expected_indentation = correct_indentation(node)
|
|
234
|
+
end
|
|
150
235
|
what = operation_description(node, rhs)
|
|
151
236
|
|
|
152
|
-
"Use #{
|
|
237
|
+
"Use #{expected_indentation} (not #{used_indentation}) " \
|
|
153
238
|
"spaces for indenting #{what} spanning multiple lines."
|
|
154
239
|
end
|
|
155
240
|
|
|
@@ -157,8 +242,6 @@ module RuboCop
|
|
|
157
242
|
case given_style
|
|
158
243
|
when :aligned
|
|
159
244
|
semantic_alignment_base(node, rhs) || syntactic_alignment_base(node, rhs)
|
|
160
|
-
when :indented
|
|
161
|
-
nil
|
|
162
245
|
when :indented_relative_to_receiver
|
|
163
246
|
receiver_alignment_base(node)
|
|
164
247
|
end
|
|
@@ -195,29 +278,55 @@ module RuboCop
|
|
|
195
278
|
# .b
|
|
196
279
|
# .c
|
|
197
280
|
def receiver_alignment_base(node)
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
281
|
+
hash_method_base = find_hash_method_base_in_receiver_chain(node)
|
|
282
|
+
return hash_method_base if hash_method_base
|
|
283
|
+
|
|
284
|
+
first_call = first_call_has_a_dot(node)
|
|
285
|
+
first_call.receiver.source_range
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
def find_hash_method_base_in_receiver_chain(node)
|
|
289
|
+
receiver_chain = unwrap_block_node(node.receiver)
|
|
290
|
+
while receiver_chain&.call_type?
|
|
291
|
+
base_receiver = unwrap_block_node(receiver_chain.receiver)
|
|
292
|
+
if alignment_base_for_chained_receiver?(receiver_chain, base_receiver)
|
|
293
|
+
return receiver_chain.loc.dot.join(receiver_chain.loc.selector)
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
receiver_chain = base_receiver
|
|
297
|
+
end
|
|
298
|
+
end
|
|
201
299
|
|
|
202
|
-
|
|
300
|
+
def alignment_base_for_chained_receiver?(receiver_chain, base_receiver)
|
|
301
|
+
base_receiver&.hash_type? ||
|
|
302
|
+
method_on_receiver_last_line?(receiver_chain, base_receiver, :begin)
|
|
203
303
|
end
|
|
204
304
|
|
|
205
305
|
def semantic_alignment_node(node)
|
|
206
306
|
return if argument_in_method_call(node, :with_parentheses)
|
|
207
307
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return multiline_block_chain_node
|
|
213
|
-
end
|
|
308
|
+
get_dot_right_above(node) ||
|
|
309
|
+
find_multiline_block_chain_node(node) ||
|
|
310
|
+
first_call_alignment_node(node)
|
|
311
|
+
end
|
|
214
312
|
|
|
313
|
+
def first_call_alignment_node(node)
|
|
215
314
|
node = first_call_has_a_dot(node)
|
|
315
|
+
base_receiver = find_base_receiver(node)
|
|
316
|
+
|
|
317
|
+
return node if method_on_receiver_last_line?(node, base_receiver, :array)
|
|
216
318
|
return if node.loc.dot.line != node.first_line
|
|
319
|
+
return if method_on_receiver_last_line?(node, base_receiver, :begin)
|
|
217
320
|
|
|
218
321
|
node
|
|
219
322
|
end
|
|
220
323
|
|
|
324
|
+
def method_on_receiver_last_line?(node, base_receiver, type)
|
|
325
|
+
base_receiver &&
|
|
326
|
+
node.loc.dot.line == base_receiver.last_line &&
|
|
327
|
+
base_receiver.type?(type)
|
|
328
|
+
end
|
|
329
|
+
|
|
221
330
|
def get_dot_right_above(node)
|
|
222
331
|
node.each_ancestor.find do |a|
|
|
223
332
|
dot = a.loc.dot if a.loc?(:dot)
|
|
@@ -228,23 +337,30 @@ module RuboCop
|
|
|
228
337
|
end
|
|
229
338
|
|
|
230
339
|
def find_multiline_block_chain_node(node)
|
|
231
|
-
return
|
|
232
|
-
return unless block_node.multiline? && block_node.parent.call_type?
|
|
340
|
+
return find_continuation_receiver(node) if node.block_node
|
|
233
341
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
342
|
+
handle_descendant_block(node)
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
def find_continuation_receiver(node)
|
|
346
|
+
receiver = node.receiver
|
|
347
|
+
return unless receiver.call_type? && receiver.loc.dot && receiver.receiver
|
|
348
|
+
return unless receiver.loc.dot.line > receiver.receiver.last_line
|
|
349
|
+
|
|
350
|
+
receiver
|
|
351
|
+
end
|
|
352
|
+
|
|
353
|
+
def handle_descendant_block(node)
|
|
354
|
+
block_node = node.each_descendant(:any_block).first
|
|
355
|
+
return unless block_node&.multiline?
|
|
356
|
+
|
|
357
|
+
node.receiver.call_type? ? node.receiver : block_node.parent
|
|
239
358
|
end
|
|
240
359
|
|
|
241
360
|
def first_call_has_a_dot(node)
|
|
242
|
-
|
|
243
|
-
node =
|
|
244
|
-
# ascend to first call which has a dot
|
|
245
|
-
node = node.parent
|
|
361
|
+
base = find_base_receiver(node)
|
|
362
|
+
node = base.parent
|
|
246
363
|
node = node.parent until node.loc?(:dot)
|
|
247
|
-
|
|
248
364
|
node
|
|
249
365
|
end
|
|
250
366
|
|
|
@@ -137,6 +137,17 @@ module RuboCop
|
|
|
137
137
|
# true
|
|
138
138
|
# end
|
|
139
139
|
#
|
|
140
|
+
# @example WaywardPredicates: ['infinite?', 'nonzero?'] (default)
|
|
141
|
+
# # good
|
|
142
|
+
# def non_predicate_method(num)
|
|
143
|
+
# num.infinite?
|
|
144
|
+
# end
|
|
145
|
+
#
|
|
146
|
+
# # good
|
|
147
|
+
# def non_predicate_method(num)
|
|
148
|
+
# num.nonzero?
|
|
149
|
+
# end
|
|
150
|
+
#
|
|
140
151
|
class PredicateMethod < Base
|
|
141
152
|
include AllowedMethods
|
|
142
153
|
include AllowedPattern
|
|
@@ -196,7 +196,7 @@ module RuboCop
|
|
|
196
196
|
end
|
|
197
197
|
end
|
|
198
198
|
|
|
199
|
-
# rubocop:disable Metrics/AbcSize
|
|
199
|
+
# rubocop:disable Metrics/AbcSize
|
|
200
200
|
def autocorrect(corrector, node, condition, replacement, guard)
|
|
201
201
|
corrector.replace(node.loc.keyword.join(condition.source_range), replacement)
|
|
202
202
|
|
|
@@ -205,10 +205,10 @@ module RuboCop
|
|
|
205
205
|
|
|
206
206
|
corrector.replace(node.loc.begin, "\n") if node.then?
|
|
207
207
|
|
|
208
|
-
if
|
|
209
|
-
autocorrect_heredoc_argument(corrector, node,
|
|
210
|
-
elsif
|
|
211
|
-
autocorrect_heredoc_argument(corrector, node,
|
|
208
|
+
if (if_heredoc = find_heredoc_argument(if_branch))
|
|
209
|
+
autocorrect_heredoc_argument(corrector, node, if_heredoc, else_branch, guard)
|
|
210
|
+
elsif (else_heredoc = find_heredoc_argument(else_branch))
|
|
211
|
+
autocorrect_heredoc_argument(corrector, node, else_heredoc, if_branch, guard)
|
|
212
212
|
else
|
|
213
213
|
corrector.remove(node.loc.end)
|
|
214
214
|
return unless node.else?
|
|
@@ -217,21 +217,31 @@ module RuboCop
|
|
|
217
217
|
corrector.remove(range_of_branch_to_remove(node, guard))
|
|
218
218
|
end
|
|
219
219
|
end
|
|
220
|
-
# rubocop:enable Metrics/AbcSize
|
|
220
|
+
# rubocop:enable Metrics/AbcSize
|
|
221
221
|
|
|
222
222
|
def heredoc?(argument)
|
|
223
223
|
argument.respond_to?(:heredoc?) && argument.heredoc?
|
|
224
224
|
end
|
|
225
225
|
|
|
226
|
-
def
|
|
226
|
+
def find_heredoc_argument(node)
|
|
227
|
+
return unless node&.call_type?
|
|
228
|
+
|
|
229
|
+
last_arg = node.last_argument
|
|
230
|
+
|
|
231
|
+
if heredoc?(last_arg)
|
|
232
|
+
last_arg
|
|
233
|
+
elsif last_arg&.call_type?
|
|
234
|
+
find_heredoc_argument(last_arg)
|
|
235
|
+
end
|
|
236
|
+
end
|
|
237
|
+
|
|
238
|
+
def autocorrect_heredoc_argument(corrector, node, heredoc_node, leave_branch, guard)
|
|
227
239
|
remove_whole_lines(corrector, node.loc.end)
|
|
228
240
|
return unless node.else?
|
|
229
241
|
|
|
230
242
|
if leave_branch
|
|
231
243
|
remove_whole_lines(corrector, leave_branch.source_range)
|
|
232
|
-
corrector.insert_after(
|
|
233
|
-
heredoc_branch.last_argument.loc.heredoc_end, "\n#{leave_branch.source}"
|
|
234
|
-
)
|
|
244
|
+
corrector.insert_after(heredoc_node.loc.heredoc_end, "\n#{leave_branch.source}")
|
|
235
245
|
end
|
|
236
246
|
|
|
237
247
|
remove_whole_lines(corrector, node.loc.else)
|
|
@@ -71,7 +71,8 @@ module RuboCop
|
|
|
71
71
|
# if short_condition # a long comment that makes it too long if it were just a single line
|
|
72
72
|
# do_something
|
|
73
73
|
# end
|
|
74
|
-
|
|
74
|
+
#
|
|
75
|
+
class IfUnlessModifier < Base # rubocop:disable Metrics/ClassLength
|
|
75
76
|
include StatementModifier
|
|
76
77
|
include LineLengthHelp
|
|
77
78
|
include AllowedPattern
|
|
@@ -230,15 +231,6 @@ module RuboCop
|
|
|
230
231
|
true
|
|
231
232
|
end
|
|
232
233
|
|
|
233
|
-
def too_long_line_based_on_allow_qualified_name?(line)
|
|
234
|
-
if allow_qualified_name?
|
|
235
|
-
namespace_range = find_excessive_range(line, :namespace)
|
|
236
|
-
return false if namespace_range && allowed_position?(line, namespace_range)
|
|
237
|
-
end
|
|
238
|
-
|
|
239
|
-
true
|
|
240
|
-
end
|
|
241
|
-
|
|
242
234
|
def line_length_enabled_at_line?(line)
|
|
243
235
|
processed_source.comment_config.cop_enabled_at_line?('Layout/LineLength', line)
|
|
244
236
|
end
|
|
@@ -248,7 +240,44 @@ module RuboCop
|
|
|
248
240
|
end
|
|
249
241
|
|
|
250
242
|
def non_eligible_node?(node)
|
|
251
|
-
non_simple_if_unless?(node) || node.chained? || node.nested_conditional? ||
|
|
243
|
+
non_simple_if_unless?(node) || node.chained? || node.nested_conditional? ||
|
|
244
|
+
multiline_inside_collection?(node) || super
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def multiline_inside_collection?(node)
|
|
248
|
+
return false if node.modifier_form?
|
|
249
|
+
return false unless (collection = find_containing_collection(node))
|
|
250
|
+
|
|
251
|
+
collection.children.any? { |child| sibling_if_shares_line?(child, node) }
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def sibling_if_shares_line?(child, node)
|
|
255
|
+
inner = unwrap_begin(child)
|
|
256
|
+
inner&.if_type? && shares_line_with?(inner, node)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
def unwrap_begin(node)
|
|
260
|
+
return unless node.is_a?(RuboCop::AST::Node)
|
|
261
|
+
|
|
262
|
+
node = node.value if node.pair_type?
|
|
263
|
+
node.begin_type? ? node.children.first : node
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def shares_line_with?(inner, node)
|
|
267
|
+
inner.loc.line == node.loc.end.line || inner.loc.end.line == node.loc.line
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def find_containing_collection(node)
|
|
271
|
+
parent = node.parent
|
|
272
|
+
return collection_from_ancestor(parent) unless parent&.begin_type?
|
|
273
|
+
|
|
274
|
+
collection_from_ancestor(parent.parent)
|
|
275
|
+
end
|
|
276
|
+
|
|
277
|
+
def collection_from_ancestor(node)
|
|
278
|
+
return node if node&.type?(:array, :call)
|
|
279
|
+
|
|
280
|
+
node.parent if node&.type?(:pair)
|
|
252
281
|
end
|
|
253
282
|
|
|
254
283
|
def non_simple_if_unless?(node)
|
|
@@ -54,7 +54,10 @@ module RuboCop
|
|
|
54
54
|
# # good (but potentially an unsafe correction)
|
|
55
55
|
# foo.do_something?
|
|
56
56
|
#
|
|
57
|
-
# @example AllowedMethods: ['nonzero?'] (default)
|
|
57
|
+
# @example AllowedMethods: ['infinite?', 'nonzero?'] (default)
|
|
58
|
+
# # good
|
|
59
|
+
# num.infinite? ? true : false
|
|
60
|
+
#
|
|
58
61
|
# # good
|
|
59
62
|
# num.nonzero? ? true : false
|
|
60
63
|
#
|
|
@@ -182,6 +182,8 @@ module RuboCop
|
|
|
182
182
|
end
|
|
183
183
|
|
|
184
184
|
def receivers_match?(length_receiver, array_receiver)
|
|
185
|
+
return array_receiver.self_type? unless length_receiver
|
|
186
|
+
|
|
185
187
|
unless preserving_method?(array_receiver) && preserving_method?(length_receiver)
|
|
186
188
|
return false
|
|
187
189
|
end
|
|
@@ -58,7 +58,10 @@ module RuboCop
|
|
|
58
58
|
# # good
|
|
59
59
|
# a.nil? || a
|
|
60
60
|
#
|
|
61
|
-
# @example AllowedMethods: ['nonzero?'] (default)
|
|
61
|
+
# @example AllowedMethods: ['infinite?', 'nonzero?'] (default)
|
|
62
|
+
# # good
|
|
63
|
+
# num.infinite? ? true : false
|
|
64
|
+
#
|
|
62
65
|
# # good
|
|
63
66
|
# num.nonzero? ? true : false
|
|
64
67
|
#
|
data/lib/rubocop/cop/team.rb
CHANGED
|
@@ -177,8 +177,8 @@ module RuboCop
|
|
|
177
177
|
# @return [Array<cop>]
|
|
178
178
|
def roundup_relevant_cops(processed_source)
|
|
179
179
|
cops.select do |cop|
|
|
180
|
-
next true if processed_source.comment_config.cop_opted_in?(cop)
|
|
181
180
|
next false if cop.excluded_file?(processed_source.file_path)
|
|
181
|
+
next true if processed_source.comment_config.cop_opted_in?(cop)
|
|
182
182
|
next false unless @registry.enabled?(cop, @config)
|
|
183
183
|
|
|
184
184
|
support_target_ruby_version?(cop) && support_target_rails_version?(cop)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'disable_comment_edits'
|
|
3
4
|
require_relative 'severity'
|
|
4
5
|
|
|
5
6
|
#
|
|
@@ -16,11 +17,12 @@ module RuboCop
|
|
|
16
17
|
# Diagnostic for Language Server Protocol of RuboCop.
|
|
17
18
|
# @api private
|
|
18
19
|
class Diagnostic
|
|
19
|
-
def initialize(document_encoding, offense, uri, cop_class)
|
|
20
|
+
def initialize(document_encoding, offense, uri, cop_class, processed_source = nil)
|
|
20
21
|
@document_encoding = document_encoding
|
|
21
22
|
@offense = offense
|
|
22
23
|
@uri = uri
|
|
23
24
|
@cop_class = cop_class
|
|
25
|
+
@processed_source = processed_source
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
def to_lsp_code_actions
|
|
@@ -141,25 +143,11 @@ module RuboCop
|
|
|
141
143
|
# rubocop:enable Metrics/MethodLength
|
|
142
144
|
|
|
143
145
|
def line_disable_comment
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
eol = LanguageServer::Protocol::Interface::Position.new(
|
|
151
|
-
line: @offense.line - 1,
|
|
152
|
-
character: to_position_character(@offense.source_line.length)
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
# TODO: fails for multiline strings - may be preferable to use block
|
|
156
|
-
# comments to disable some offenses
|
|
157
|
-
inline_comment = LanguageServer::Protocol::Interface::TextEdit.new(
|
|
158
|
-
range: LanguageServer::Protocol::Interface::Range.new(start: eol, end: eol),
|
|
159
|
-
new_text: new_text
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
[inline_comment]
|
|
146
|
+
DisableCommentEdits.new(
|
|
147
|
+
offense: @offense,
|
|
148
|
+
document_encoding: @document_encoding,
|
|
149
|
+
processed_source: @processed_source
|
|
150
|
+
).edits
|
|
163
151
|
end
|
|
164
152
|
|
|
165
153
|
def to_position_character(utf8_index)
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RuboCop
|
|
4
|
+
module LSP
|
|
5
|
+
# Builds LSP text edits for rubocop:disable comments.
|
|
6
|
+
# @api private
|
|
7
|
+
class DisableCommentEdits
|
|
8
|
+
def initialize(offense:, document_encoding:, processed_source:)
|
|
9
|
+
@offense = offense
|
|
10
|
+
@document_encoding = document_encoding
|
|
11
|
+
@processed_source = processed_source
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def edits
|
|
15
|
+
literal_range = multiline_literal_range
|
|
16
|
+
return block_disable_comments(literal_range) if literal_range
|
|
17
|
+
|
|
18
|
+
inline_disable_comment
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def inline_disable_comment
|
|
24
|
+
eol = position(@offense.line - 1, @offense.source_line.length, @offense.source_line)
|
|
25
|
+
[text_edit(eol, inline_comment_text)]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def inline_comment_text
|
|
29
|
+
if @offense.source_line.include?(' # rubocop:disable ')
|
|
30
|
+
",#{@offense.cop_name}"
|
|
31
|
+
else
|
|
32
|
+
" # rubocop:disable #{@offense.cop_name}"
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def block_disable_comments(range)
|
|
37
|
+
full_line_range = range_by_lines(range)
|
|
38
|
+
leading_whitespace = full_line_range.source_line[/^\s*/].to_s
|
|
39
|
+
[
|
|
40
|
+
disable_edit(full_line_range.first_line, leading_whitespace),
|
|
41
|
+
enable_edit(full_line_range, leading_whitespace)
|
|
42
|
+
]
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def disable_edit(first_line, leading_whitespace)
|
|
46
|
+
position = position(first_line - 1, 0, '')
|
|
47
|
+
text_edit(position, "#{leading_whitespace}# rubocop:disable #{@offense.cop_name}\n")
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def enable_edit(full_line_range, leading_whitespace)
|
|
51
|
+
last_line = full_line_range.last_line
|
|
52
|
+
last_line_text = full_line_range.source_buffer.source_line(last_line)
|
|
53
|
+
position = position(last_line - 1, last_line_text.length, last_line_text)
|
|
54
|
+
text_edit(position, "\n#{leading_whitespace}# rubocop:enable #{@offense.cop_name}")
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def text_edit(position, new_text)
|
|
58
|
+
range = LanguageServer::Protocol::Interface::Range.new(start: position, end: position)
|
|
59
|
+
LanguageServer::Protocol::Interface::TextEdit.new(range: range, new_text: new_text)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def position(line, utf8_index, line_text)
|
|
63
|
+
LanguageServer::Protocol::Interface::Position.new(
|
|
64
|
+
line: line,
|
|
65
|
+
character: position_character(utf8_index, line_text)
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def position_character(utf8_index, line_text)
|
|
70
|
+
str = line_text[0, utf8_index]
|
|
71
|
+
if @document_encoding == Encoding::UTF_16LE || @document_encoding.nil?
|
|
72
|
+
str.length + str.b.count("\xf0-\xff".b)
|
|
73
|
+
else
|
|
74
|
+
str.length
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def multiline_literal_range
|
|
79
|
+
return unless @processed_source&.ast
|
|
80
|
+
|
|
81
|
+
offense_range = @offense.location
|
|
82
|
+
multiline_ranges&.find do |range|
|
|
83
|
+
eol_comment_would_be_inside_literal?(offense_range, range)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def multiline_ranges
|
|
88
|
+
@processed_source.ast.each_node.filter_map do |node|
|
|
89
|
+
if surrounding_heredoc?(node)
|
|
90
|
+
heredoc_range(node)
|
|
91
|
+
elsif string_continuation?(node)
|
|
92
|
+
range_by_lines(node.source_range)
|
|
93
|
+
elsif surrounding_percent_array?(node) || multiline_string?(node)
|
|
94
|
+
node.source_range
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def eol_comment_would_be_inside_literal?(offense_range, literal_range)
|
|
100
|
+
offense_line = offense_range.line
|
|
101
|
+
offense_line >= literal_range.first_line && offense_line < literal_range.last_line
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def surrounding_heredoc?(node)
|
|
105
|
+
node.any_str_type? && node.heredoc?
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def heredoc_range(node)
|
|
109
|
+
node.source_range.join(node.loc.heredoc_end)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def surrounding_percent_array?(node)
|
|
113
|
+
node.array_type? && node.percent_literal?
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def string_continuation?(node)
|
|
117
|
+
node.any_str_type? && node.source.match?(/\\\s*$/)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def multiline_string?(node)
|
|
121
|
+
node.dstr_type? && node.multiline?
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def range_by_lines(range)
|
|
125
|
+
begin_of_first_line = range.begin_pos - range.column
|
|
126
|
+
|
|
127
|
+
last_line = range.source_buffer.source_line(range.last_line)
|
|
128
|
+
last_line_offset = last_line.length - range.last_column
|
|
129
|
+
end_of_last_line = range.end_pos + last_line_offset
|
|
130
|
+
|
|
131
|
+
Parser::Source::Range.new(range.source_buffer, begin_of_first_line, end_of_last_line)
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
end
|
data/lib/rubocop/lsp/runtime.rb
CHANGED
|
@@ -49,15 +49,25 @@ module RuboCop
|
|
|
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
|
+
processed_source = @runner.processed_source
|
|
53
|
+
config = @runner.config_for_working_directory
|
|
52
54
|
@runner.offenses.map do |offense|
|
|
53
|
-
|
|
54
|
-
document_encoding, offense, path, @cop_registry[offense.cop_name]&.first
|
|
55
|
-
).to_lsp_diagnostic(@runner.config_for_working_directory)
|
|
55
|
+
build_diagnostic(offense, path, document_encoding, processed_source, config)
|
|
56
56
|
end
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
private
|
|
60
60
|
|
|
61
|
+
def build_diagnostic(offense, path, document_encoding, processed_source, config)
|
|
62
|
+
Diagnostic.new(
|
|
63
|
+
document_encoding,
|
|
64
|
+
offense,
|
|
65
|
+
path,
|
|
66
|
+
@cop_registry[offense.cop_name]&.first,
|
|
67
|
+
processed_source
|
|
68
|
+
).to_lsp_diagnostic(config)
|
|
69
|
+
end
|
|
70
|
+
|
|
61
71
|
def config_only_options
|
|
62
72
|
only_options = []
|
|
63
73
|
only_options << 'Lint' if @lint_mode
|
|
@@ -17,7 +17,7 @@ module RuboCop
|
|
|
17
17
|
class StdinRunner < RuboCop::Runner
|
|
18
18
|
class ConfigurationError < StandardError; end
|
|
19
19
|
|
|
20
|
-
attr_reader :offenses, :config_for_working_directory
|
|
20
|
+
attr_reader :offenses, :config_for_working_directory, :processed_source
|
|
21
21
|
|
|
22
22
|
DEFAULT_RUBOCOP_OPTIONS = {
|
|
23
23
|
stderr: true,
|
|
@@ -45,6 +45,7 @@ module RuboCop
|
|
|
45
45
|
@options[:stdin] = contents
|
|
46
46
|
|
|
47
47
|
@prism_result = prism_result
|
|
48
|
+
@processed_source = nil
|
|
48
49
|
|
|
49
50
|
@offenses = []
|
|
50
51
|
@warnings = []
|
|
@@ -64,6 +65,12 @@ module RuboCop
|
|
|
64
65
|
def file_finished(_file, offenses)
|
|
65
66
|
@offenses = offenses
|
|
66
67
|
end
|
|
68
|
+
|
|
69
|
+
def do_inspection_loop(file)
|
|
70
|
+
source, offenses = super
|
|
71
|
+
@processed_source = source
|
|
72
|
+
[source, offenses]
|
|
73
|
+
end
|
|
67
74
|
end
|
|
68
75
|
end
|
|
69
76
|
end
|
data/lib/rubocop/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rubocop
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.84.
|
|
4
|
+
version: 1.84.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bozhidar Batsov
|
|
@@ -1038,6 +1038,7 @@ files:
|
|
|
1038
1038
|
- lib/rubocop/lockfile.rb
|
|
1039
1039
|
- lib/rubocop/lsp.rb
|
|
1040
1040
|
- lib/rubocop/lsp/diagnostic.rb
|
|
1041
|
+
- lib/rubocop/lsp/disable_comment_edits.rb
|
|
1041
1042
|
- lib/rubocop/lsp/logger.rb
|
|
1042
1043
|
- lib/rubocop/lsp/routes.rb
|
|
1043
1044
|
- lib/rubocop/lsp/runtime.rb
|
|
@@ -1096,7 +1097,7 @@ licenses:
|
|
|
1096
1097
|
- MIT
|
|
1097
1098
|
metadata:
|
|
1098
1099
|
homepage_uri: https://rubocop.org/
|
|
1099
|
-
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.84.
|
|
1100
|
+
changelog_uri: https://github.com/rubocop/rubocop/releases/tag/v1.84.1
|
|
1100
1101
|
source_code_uri: https://github.com/rubocop/rubocop/
|
|
1101
1102
|
documentation_uri: https://docs.rubocop.org/rubocop/1.84/
|
|
1102
1103
|
bug_tracker_uri: https://github.com/rubocop/rubocop/issues
|