rubocop 1.69.2 → 1.70.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/LICENSE.txt +1 -1
- data/README.md +2 -2
- data/config/default.yml +19 -2
- data/lib/rubocop/cli/command/execute_runner.rb +3 -3
- data/lib/rubocop/config.rb +13 -4
- data/lib/rubocop/config_loader.rb +4 -0
- data/lib/rubocop/config_loader_resolver.rb +14 -3
- data/lib/rubocop/config_validator.rb +18 -8
- data/lib/rubocop/cop/base.rb +6 -0
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_enabled.rb +85 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +4 -3
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -7
- data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +1 -0
- data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +2 -7
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -6
- data/lib/rubocop/cop/layout/hash_alignment.rb +6 -4
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
- data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +1 -0
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +24 -0
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
- data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
- data/lib/rubocop/cop/layout/space_around_operators.rb +3 -3
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +5 -3
- data/lib/rubocop/cop/lint/constant_reassignment.rb +152 -0
- data/lib/rubocop/cop/lint/duplicate_set_element.rb +20 -7
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +11 -3
- data/lib/rubocop/cop/lint/nested_method_definition.rb +5 -1
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +4 -3
- data/lib/rubocop/cop/lint/numeric_operation_with_constant_result.rb +6 -14
- data/lib/rubocop/cop/lint/shared_mutable_default.rb +65 -0
- data/lib/rubocop/cop/lint/syntax.rb +4 -1
- data/lib/rubocop/cop/lint/unescaped_bracket_in_regexp.rb +1 -4
- data/lib/rubocop/cop/lint/void.rb +3 -2
- data/lib/rubocop/cop/metrics/method_length.rb +8 -1
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +7 -7
- data/lib/rubocop/cop/mixin/comments_help.rb +2 -0
- data/lib/rubocop/cop/mixin/dig_help.rb +1 -1
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +26 -16
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +32 -1
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +1 -4
- data/lib/rubocop/cop/style/class_and_module_children.rb +5 -2
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +3 -6
- data/lib/rubocop/cop/style/empty_else.rb +4 -2
- data/lib/rubocop/cop/style/empty_literal.rb +1 -1
- data/lib/rubocop/cop/style/empty_method.rb +1 -1
- data/lib/rubocop/cop/style/exact_regexp_match.rb +2 -9
- data/lib/rubocop/cop/style/exponential_notation.rb +1 -1
- data/lib/rubocop/cop/style/float_division.rb +8 -4
- data/lib/rubocop/cop/style/hash_except.rb +54 -67
- data/lib/rubocop/cop/style/hash_syntax.rb +5 -2
- data/lib/rubocop/cop/style/it_assignment.rb +36 -0
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +11 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +2 -0
- data/lib/rubocop/cop/style/missing_else.rb +2 -0
- data/lib/rubocop/cop/style/multiple_comparison.rb +26 -20
- data/lib/rubocop/cop/style/mutable_constant.rb +1 -1
- data/lib/rubocop/cop/style/object_then.rb +13 -15
- data/lib/rubocop/cop/style/quoted_symbols.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +5 -3
- data/lib/rubocop/cop/style/random_with_offset.rb +3 -3
- data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +2 -1
- data/lib/rubocop/cop/style/redundant_initialize.rb +12 -3
- data/lib/rubocop/cop/style/redundant_line_continuation.rb +7 -3
- data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -4
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +3 -0
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +6 -5
- data/lib/rubocop/cop/style/safe_navigation.rb +1 -1
- data/lib/rubocop/cop/style/send_with_literal_method_name.rb +2 -1
- data/lib/rubocop/cop/style/single_line_do_end_block.rb +1 -2
- data/lib/rubocop/cop/style/single_line_methods.rb +2 -3
- data/lib/rubocop/cop/style/slicing_with_range.rb +40 -11
- data/lib/rubocop/cop/style/super_arguments.rb +63 -15
- data/lib/rubocop/cop/style/yoda_condition.rb +8 -4
- data/lib/rubocop/cop/style/yoda_expression.rb +1 -0
- data/lib/rubocop/cop/util.rb +9 -2
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/lsp/diagnostic.rb +189 -0
- data/lib/rubocop/lsp/logger.rb +2 -2
- data/lib/rubocop/lsp/routes.rb +7 -23
- data/lib/rubocop/lsp/runtime.rb +15 -49
- data/lib/rubocop/lsp/stdin_runner.rb +83 -0
- data/lib/rubocop/path_util.rb +11 -8
- data/lib/rubocop/rspec/shared_contexts.rb +4 -1
- data/lib/rubocop/runner.rb +5 -6
- data/lib/rubocop/target_ruby.rb +15 -0
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +3 -0
- data/lib/ruby_lsp/rubocop/addon.rb +78 -0
- data/lib/ruby_lsp/rubocop/wraps_built_in_lsp_runtime.rb +50 -0
- metadata +12 -4
@@ -85,6 +85,12 @@ module RuboCop
|
|
85
85
|
NONCOMMUTATIVE_OPERATORS = %i[===].freeze
|
86
86
|
PROGRAM_NAMES = %i[$0 $PROGRAM_NAME].freeze
|
87
87
|
RESTRICT_ON_SEND = RuboCop::AST::Node::COMPARISON_OPERATORS
|
88
|
+
ENFORCE_YODA_STYLES = %i[
|
89
|
+
require_for_all_comparison_operators require_for_equality_operators_only
|
90
|
+
].freeze
|
91
|
+
EQUALITY_ONLY_STYLES = %i[
|
92
|
+
forbid_for_equality_operators_only require_for_equality_operators_only
|
93
|
+
].freeze
|
88
94
|
|
89
95
|
# @!method file_constant_equal_program_name?(node)
|
90
96
|
def_node_matcher :file_constant_equal_program_name?, <<~PATTERN
|
@@ -105,13 +111,11 @@ module RuboCop
|
|
105
111
|
private
|
106
112
|
|
107
113
|
def enforce_yoda?
|
108
|
-
style
|
109
|
-
style == :require_for_equality_operators_only
|
114
|
+
ENFORCE_YODA_STYLES.include?(style)
|
110
115
|
end
|
111
116
|
|
112
117
|
def equality_only?
|
113
|
-
style
|
114
|
-
style == :require_for_equality_operators_only
|
118
|
+
EQUALITY_ONLY_STYLES.include?(style)
|
115
119
|
end
|
116
120
|
|
117
121
|
def yoda_compatible_condition?(node)
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -193,11 +193,18 @@ module RuboCop
|
|
193
193
|
enforced_style.sub(/^Enforced/, 'Supported').sub('Style', 'Styles')
|
194
194
|
end
|
195
195
|
|
196
|
+
def parse_regexp(text)
|
197
|
+
Regexp::Parser.parse(text)
|
198
|
+
rescue Regexp::Parser::Error
|
199
|
+
# Upon encountering an invalid regular expression,
|
200
|
+
# we aim to proceed and identify any remaining potential offenses.
|
201
|
+
nil
|
202
|
+
end
|
203
|
+
|
196
204
|
private
|
197
205
|
|
198
206
|
def compatible_external_encoding_for?(src)
|
199
|
-
src
|
200
|
-
src.force_encoding(Encoding.default_external).valid_encoding?
|
207
|
+
src.dup.force_encoding(Encoding.default_external).valid_encoding?
|
201
208
|
end
|
202
209
|
|
203
210
|
def include_or_equal?(source, target)
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'severity'
|
4
|
+
|
5
|
+
#
|
6
|
+
# This code is based on https://github.com/standardrb/standard.
|
7
|
+
#
|
8
|
+
# Copyright (c) 2023 Test Double, Inc.
|
9
|
+
#
|
10
|
+
# The MIT License (MIT)
|
11
|
+
#
|
12
|
+
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
13
|
+
#
|
14
|
+
module RuboCop
|
15
|
+
module LSP
|
16
|
+
# Diagnostic for Language Server Protocol of RuboCop.
|
17
|
+
# @api private
|
18
|
+
class Diagnostic
|
19
|
+
def initialize(document_encoding, offense, uri, cop_class)
|
20
|
+
@document_encoding = document_encoding
|
21
|
+
@offense = offense
|
22
|
+
@uri = uri
|
23
|
+
@cop_class = cop_class
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_lsp_code_actions
|
27
|
+
code_actions = []
|
28
|
+
|
29
|
+
code_actions << autocorrect_action if correctable?
|
30
|
+
code_actions << disable_line_action
|
31
|
+
|
32
|
+
code_actions
|
33
|
+
end
|
34
|
+
|
35
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
36
|
+
def to_lsp_diagnostic(config)
|
37
|
+
highlighted = @offense.highlighted_area
|
38
|
+
|
39
|
+
LanguageServer::Protocol::Interface::Diagnostic.new(
|
40
|
+
message: message,
|
41
|
+
source: 'RuboCop',
|
42
|
+
code: @offense.cop_name,
|
43
|
+
code_description: code_description(config),
|
44
|
+
severity: severity,
|
45
|
+
range: LanguageServer::Protocol::Interface::Range.new(
|
46
|
+
start: LanguageServer::Protocol::Interface::Position.new(
|
47
|
+
line: @offense.line - 1,
|
48
|
+
character: highlighted.begin_pos
|
49
|
+
),
|
50
|
+
end: LanguageServer::Protocol::Interface::Position.new(
|
51
|
+
line: @offense.line - 1,
|
52
|
+
character: highlighted.end_pos
|
53
|
+
)
|
54
|
+
),
|
55
|
+
data: {
|
56
|
+
correctable: correctable?,
|
57
|
+
code_actions: to_lsp_code_actions
|
58
|
+
}
|
59
|
+
)
|
60
|
+
end
|
61
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def message
|
66
|
+
message = @offense.message
|
67
|
+
message += "\n\nThis offense is not autocorrectable.\n" unless correctable?
|
68
|
+
message
|
69
|
+
end
|
70
|
+
|
71
|
+
def severity
|
72
|
+
Severity.find_by(@offense.severity.name)
|
73
|
+
end
|
74
|
+
|
75
|
+
def code_description(config)
|
76
|
+
return unless @cop_class
|
77
|
+
return unless (doc_url = @cop_class.documentation_url(config))
|
78
|
+
|
79
|
+
LanguageServer::Protocol::Interface::CodeDescription.new(href: doc_url)
|
80
|
+
end
|
81
|
+
|
82
|
+
# rubocop:disable Layout/LineLength, Metrics/MethodLength
|
83
|
+
def autocorrect_action
|
84
|
+
LanguageServer::Protocol::Interface::CodeAction.new(
|
85
|
+
title: "Autocorrect #{@offense.cop_name}",
|
86
|
+
kind: LanguageServer::Protocol::Constant::CodeActionKind::QUICK_FIX,
|
87
|
+
edit: LanguageServer::Protocol::Interface::WorkspaceEdit.new(
|
88
|
+
document_changes: [
|
89
|
+
LanguageServer::Protocol::Interface::TextDocumentEdit.new(
|
90
|
+
text_document: LanguageServer::Protocol::Interface::OptionalVersionedTextDocumentIdentifier.new(
|
91
|
+
uri: ensure_uri_scheme(@uri.to_s).to_s,
|
92
|
+
version: nil
|
93
|
+
),
|
94
|
+
edits: correctable? ? offense_replacements : []
|
95
|
+
)
|
96
|
+
]
|
97
|
+
),
|
98
|
+
is_preferred: true
|
99
|
+
)
|
100
|
+
end
|
101
|
+
# rubocop:enable Layout/LineLength, Metrics/MethodLength
|
102
|
+
|
103
|
+
# rubocop:disable Metrics/MethodLength
|
104
|
+
def offense_replacements
|
105
|
+
@offense.corrector.as_replacements.map do |range, replacement|
|
106
|
+
LanguageServer::Protocol::Interface::TextEdit.new(
|
107
|
+
range: LanguageServer::Protocol::Interface::Range.new(
|
108
|
+
start: LanguageServer::Protocol::Interface::Position.new(
|
109
|
+
line: range.line - 1,
|
110
|
+
character: range.column
|
111
|
+
),
|
112
|
+
end: LanguageServer::Protocol::Interface::Position.new(
|
113
|
+
line: range.last_line - 1,
|
114
|
+
character: range.last_column
|
115
|
+
)
|
116
|
+
),
|
117
|
+
new_text: replacement
|
118
|
+
)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
# rubocop:enable Metrics/MethodLength
|
122
|
+
|
123
|
+
# rubocop:disable Layout/LineLength, Metrics/MethodLength
|
124
|
+
def disable_line_action
|
125
|
+
LanguageServer::Protocol::Interface::CodeAction.new(
|
126
|
+
title: "Disable #{@offense.cop_name} for this line",
|
127
|
+
kind: LanguageServer::Protocol::Constant::CodeActionKind::QUICK_FIX,
|
128
|
+
edit: LanguageServer::Protocol::Interface::WorkspaceEdit.new(
|
129
|
+
document_changes: [
|
130
|
+
LanguageServer::Protocol::Interface::TextDocumentEdit.new(
|
131
|
+
text_document: LanguageServer::Protocol::Interface::OptionalVersionedTextDocumentIdentifier.new(
|
132
|
+
uri: ensure_uri_scheme(@uri.to_s).to_s,
|
133
|
+
version: nil
|
134
|
+
),
|
135
|
+
edits: line_disable_comment
|
136
|
+
)
|
137
|
+
]
|
138
|
+
)
|
139
|
+
)
|
140
|
+
end
|
141
|
+
# rubocop:enable Layout/LineLength, Metrics/MethodLength
|
142
|
+
|
143
|
+
def line_disable_comment
|
144
|
+
new_text = if @offense.source_line.include?(' # rubocop:disable ')
|
145
|
+
",#{@offense.cop_name}"
|
146
|
+
else
|
147
|
+
" # rubocop:disable #{@offense.cop_name}"
|
148
|
+
end
|
149
|
+
|
150
|
+
eol = LanguageServer::Protocol::Interface::Position.new(
|
151
|
+
line: @offense.line - 1,
|
152
|
+
character: length_of_line(@offense.source_line)
|
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]
|
163
|
+
end
|
164
|
+
|
165
|
+
def length_of_line(line)
|
166
|
+
if @document_encoding == Encoding::UTF_16LE
|
167
|
+
line_length = 0
|
168
|
+
line.codepoints.each do |codepoint|
|
169
|
+
line_length += 1
|
170
|
+
line_length += 1 if codepoint > RubyLsp::Document::Scanner::SURROGATE_PAIR_START
|
171
|
+
end
|
172
|
+
line_length
|
173
|
+
else
|
174
|
+
line.length
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def correctable?
|
179
|
+
!@offense.corrector.nil?
|
180
|
+
end
|
181
|
+
|
182
|
+
def ensure_uri_scheme(uri)
|
183
|
+
uri = URI.parse(uri)
|
184
|
+
uri.scheme = 'file' if uri.scheme.nil?
|
185
|
+
uri
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
data/lib/rubocop/lsp/logger.rb
CHANGED
data/lib/rubocop/lsp/routes.rb
CHANGED
@@ -16,6 +16,11 @@ module RuboCop
|
|
16
16
|
# Routes for Language Server Protocol of RuboCop.
|
17
17
|
# @api private
|
18
18
|
class Routes
|
19
|
+
CONFIGURATION_FILE_PATTERNS = [
|
20
|
+
RuboCop::ConfigFinder::DOTFILE,
|
21
|
+
RuboCop::CLI::Command::AutoGenerateConfig::AUTO_GENERATED_FILE
|
22
|
+
].freeze
|
23
|
+
|
19
24
|
def self.handle(name, &block)
|
20
25
|
define_method(:"handle_#{name}", &block)
|
21
26
|
end
|
@@ -96,7 +101,7 @@ module RuboCop
|
|
96
101
|
|
97
102
|
handle 'workspace/didChangeWatchedFiles' do |request|
|
98
103
|
changed = request[:params][:changes].any? do |change|
|
99
|
-
change[:uri].end_with?(
|
104
|
+
CONFIGURATION_FILE_PATTERNS.any? { |path| change[:uri].end_with?(path) }
|
100
105
|
end
|
101
106
|
|
102
107
|
if changed
|
@@ -204,14 +209,12 @@ module RuboCop
|
|
204
209
|
|
205
210
|
def diagnostic(file_uri, text)
|
206
211
|
@text_cache[file_uri] = text
|
207
|
-
offenses = @server.offenses(remove_file_protocol_from(file_uri), text)
|
208
|
-
diagnostics = offenses.map { |offense| to_diagnostic(offense) }
|
209
212
|
|
210
213
|
{
|
211
214
|
method: 'textDocument/publishDiagnostics',
|
212
215
|
params: {
|
213
216
|
uri: file_uri,
|
214
|
-
diagnostics:
|
217
|
+
diagnostics: @server.offenses(remove_file_protocol_from(file_uri), text)
|
215
218
|
}
|
216
219
|
}
|
217
220
|
end
|
@@ -219,25 +222,6 @@ module RuboCop
|
|
219
222
|
def remove_file_protocol_from(uri)
|
220
223
|
uri.delete_prefix('file://')
|
221
224
|
end
|
222
|
-
|
223
|
-
def to_diagnostic(offense)
|
224
|
-
code = offense[:cop_name]
|
225
|
-
message = offense[:message]
|
226
|
-
loc = offense[:location]
|
227
|
-
rubocop_severity = offense[:severity]
|
228
|
-
severity = Severity.find_by(rubocop_severity)
|
229
|
-
|
230
|
-
{
|
231
|
-
code: code, message: message, range: to_range(loc), severity: severity, source: 'rubocop'
|
232
|
-
}
|
233
|
-
end
|
234
|
-
|
235
|
-
def to_range(location)
|
236
|
-
{
|
237
|
-
start: { character: location[:start_column] - 1, line: location[:start_line] - 1 },
|
238
|
-
end: { character: location[:last_column], line: location[:last_line] - 1 }
|
239
|
-
}
|
240
|
-
end
|
241
225
|
end
|
242
226
|
end
|
243
227
|
end
|
data/lib/rubocop/lsp/runtime.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
3
|
+
require_relative 'diagnostic'
|
4
|
+
require_relative 'stdin_runner'
|
4
5
|
|
5
6
|
#
|
6
7
|
# This code is based on https://github.com/standardrb/standard.
|
@@ -19,24 +20,14 @@ module RuboCop
|
|
19
20
|
attr_writer :safe_autocorrect, :lint_mode, :layout_mode
|
20
21
|
|
21
22
|
def initialize(config_store)
|
22
|
-
@
|
23
|
-
@
|
23
|
+
@runner = RuboCop::Lsp::StdinRunner.new(config_store)
|
24
|
+
@cop_registry = RuboCop::Cop::Registry.global.to_h
|
25
|
+
|
24
26
|
@safe_autocorrect = true
|
25
27
|
@lint_mode = false
|
26
28
|
@layout_mode = false
|
27
29
|
end
|
28
30
|
|
29
|
-
# This abuses the `--stdin` option of rubocop and reads the formatted text
|
30
|
-
# from the `options[:stdin]` that rubocop mutates. This depends on
|
31
|
-
# `parallel: false` as well as the fact that RuboCop doesn't otherwise dup
|
32
|
-
# or reassign that options object. Risky business!
|
33
|
-
#
|
34
|
-
# Reassigning `options[:stdin]` is done here:
|
35
|
-
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cop/team.rb#L131
|
36
|
-
# Printing `options[:stdin]`
|
37
|
-
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cli/command/execute_runner.rb#L95
|
38
|
-
# Setting `parallel: true` would break this here:
|
39
|
-
# https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
|
40
31
|
def format(path, text, command:)
|
41
32
|
safe_autocorrect = if command
|
42
33
|
command == 'rubocop.formatAutocorrects'
|
@@ -44,34 +35,23 @@ module RuboCop
|
|
44
35
|
@safe_autocorrect
|
45
36
|
end
|
46
37
|
|
47
|
-
formatting_options = {
|
48
|
-
stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: safe_autocorrect
|
49
|
-
}
|
38
|
+
formatting_options = { autocorrect: true, safe_autocorrect: safe_autocorrect }
|
50
39
|
formatting_options[:only] = config_only_options if @lint_mode || @layout_mode
|
51
40
|
|
52
|
-
|
53
|
-
|
54
|
-
formatting_options[:stdin]
|
41
|
+
@runner.run(path, text, formatting_options)
|
42
|
+
@runner.formatted_source
|
55
43
|
end
|
56
44
|
|
57
|
-
def offenses(path, text)
|
58
|
-
diagnostic_options = {
|
59
|
-
stdin: text, force_exclusion: true, formatters: ['json'], format: 'json'
|
60
|
-
}
|
45
|
+
def offenses(path, text, document_encoding = nil)
|
46
|
+
diagnostic_options = {}
|
61
47
|
diagnostic_options[:only] = config_only_options if @lint_mode || @layout_mode
|
62
48
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
Logger.log "Ignoring file, per configuration: #{path}"
|
69
|
-
@logged_paths << path
|
70
|
-
end
|
71
|
-
return []
|
49
|
+
@runner.run(path, text, diagnostic_options)
|
50
|
+
@runner.offenses.map do |offense|
|
51
|
+
Diagnostic.new(
|
52
|
+
document_encoding, offense, path, @cop_registry[offense.cop_name]&.first
|
53
|
+
).to_lsp_diagnostic(@runner.config_for_working_directory)
|
72
54
|
end
|
73
|
-
|
74
|
-
results.dig(:files, 0, :offenses)
|
75
55
|
end
|
76
56
|
|
77
57
|
private
|
@@ -82,20 +62,6 @@ module RuboCop
|
|
82
62
|
only_options << 'Layout' if @layout_mode
|
83
63
|
only_options
|
84
64
|
end
|
85
|
-
|
86
|
-
def redirect_stdout(&block)
|
87
|
-
stdout = StringIO.new
|
88
|
-
|
89
|
-
RuboCop::Server::Helper.redirect(stdout: stdout, &block)
|
90
|
-
|
91
|
-
stdout.string
|
92
|
-
end
|
93
|
-
|
94
|
-
def run_rubocop(options, path)
|
95
|
-
runner = RuboCop::Runner.new(options, @config_store)
|
96
|
-
|
97
|
-
runner.run([path])
|
98
|
-
end
|
99
65
|
end
|
100
66
|
end
|
101
67
|
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# This code is based on https://github.com/standardrb/standard.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2023 Test Double, Inc.
|
7
|
+
#
|
8
|
+
# The MIT License (MIT)
|
9
|
+
#
|
10
|
+
# https://github.com/standardrb/standard/blob/main/LICENSE.txt
|
11
|
+
#
|
12
|
+
module RuboCop
|
13
|
+
module Lsp
|
14
|
+
# Originally lifted from:
|
15
|
+
# https://github.com/Shopify/ruby-lsp/blob/8d4c17efce4e8ecc8e7c557ab2981db6b22c0b6d/lib/ruby_lsp/requests/support/rubocop_runner.rb#L20
|
16
|
+
# @api private
|
17
|
+
class StdinRunner < RuboCop::Runner
|
18
|
+
class ConfigurationError < StandardError; end
|
19
|
+
|
20
|
+
attr_reader :offenses, :config_for_working_directory
|
21
|
+
|
22
|
+
DEFAULT_RUBOCOP_OPTIONS = {
|
23
|
+
stderr: true,
|
24
|
+
force_exclusion: true,
|
25
|
+
formatters: ['RuboCop::Formatter::BaseFormatter'],
|
26
|
+
raise_cop_error: true,
|
27
|
+
todo_file: nil,
|
28
|
+
todo_ignore_files: []
|
29
|
+
}.freeze
|
30
|
+
|
31
|
+
def initialize(config_store)
|
32
|
+
@options = {}
|
33
|
+
|
34
|
+
@offenses = []
|
35
|
+
@warnings = []
|
36
|
+
@errors = []
|
37
|
+
|
38
|
+
@config_for_working_directory = config_store.for_pwd
|
39
|
+
|
40
|
+
super(@options, config_store)
|
41
|
+
end
|
42
|
+
|
43
|
+
# rubocop:disable Metrics/MethodLength
|
44
|
+
def run(path, contents, options)
|
45
|
+
@options = options.merge(DEFAULT_RUBOCOP_OPTIONS)
|
46
|
+
@options[:stdin] = contents
|
47
|
+
|
48
|
+
@offenses = []
|
49
|
+
@warnings = []
|
50
|
+
@errors = []
|
51
|
+
|
52
|
+
super([path])
|
53
|
+
|
54
|
+
raise Interrupt if aborting?
|
55
|
+
rescue RuboCop::Runner::InfiniteCorrectionLoop => e
|
56
|
+
if defined?(::RubyLsp::Requests::Formatting::Error)
|
57
|
+
raise ::RubyLsp::Requests::Formatting::Error, e.message
|
58
|
+
end
|
59
|
+
|
60
|
+
raise e
|
61
|
+
rescue RuboCop::ValidationError => e
|
62
|
+
raise ConfigurationError, e.message
|
63
|
+
rescue StandardError => e
|
64
|
+
if defined?(::RubyLsp::Requests::Formatting::Error)
|
65
|
+
raise ::RubyLsp::Requests::Support::InternalRuboCopError, e
|
66
|
+
end
|
67
|
+
|
68
|
+
raise e
|
69
|
+
end
|
70
|
+
# rubocop:enable Metrics/MethodLength
|
71
|
+
|
72
|
+
def formatted_source
|
73
|
+
@options[:stdin]
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def file_finished(_file, offenses)
|
79
|
+
@offenses = offenses
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
data/lib/rubocop/path_util.rb
CHANGED
@@ -32,16 +32,19 @@ module RuboCop
|
|
32
32
|
private_constant :SMART_PATH_CACHE
|
33
33
|
|
34
34
|
def smart_path(path)
|
35
|
-
SMART_PATH_CACHE[path] ||=
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
if path.start_with? base_dir
|
40
|
-
relative_path(path, base_dir)
|
35
|
+
SMART_PATH_CACHE[path] ||=
|
36
|
+
if path.is_a?(RemoteConfig)
|
37
|
+
path.uri.to_s
|
41
38
|
else
|
42
|
-
|
39
|
+
# Ideally, we calculate this relative to the project root.
|
40
|
+
base_dir = Dir.pwd
|
41
|
+
|
42
|
+
if path.start_with? base_dir
|
43
|
+
relative_path(path, base_dir)
|
44
|
+
else
|
45
|
+
path
|
46
|
+
end
|
43
47
|
end
|
44
|
-
end
|
45
48
|
end
|
46
49
|
|
47
50
|
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
@@ -98,6 +98,8 @@ RSpec.shared_context 'config' do # rubocop:disable Metrics/BlockLength
|
|
98
98
|
|
99
99
|
let(:cop_options) { {} }
|
100
100
|
|
101
|
+
let(:gem_versions) { {} }
|
102
|
+
|
101
103
|
### Utilities
|
102
104
|
|
103
105
|
def source_range(range, buffer: source_buffer)
|
@@ -138,7 +140,8 @@ RSpec.shared_context 'config' do # rubocop:disable Metrics/BlockLength
|
|
138
140
|
|
139
141
|
allow(config).to receive(:gem_versions_in_target).and_return(
|
140
142
|
{
|
141
|
-
'railties' => rails_version_in_gemfile
|
143
|
+
'railties' => rails_version_in_gemfile,
|
144
|
+
**gem_versions.transform_values { |value| Gem::Version.new(value) }
|
142
145
|
}
|
143
146
|
)
|
144
147
|
|
data/lib/rubocop/runner.rb
CHANGED
@@ -20,11 +20,7 @@ module RuboCop
|
|
20
20
|
message = 'Infinite loop detected'
|
21
21
|
message += " in #{path}" if path
|
22
22
|
message += " and caused by #{root_cause}" if root_cause
|
23
|
-
message
|
24
|
-
hint = 'Hint: Please update to the latest RuboCop version if not already in use, ' \
|
25
|
-
"and report a bug if the issue still occurs on this version.\n" \
|
26
|
-
'Please check the latest version at https://rubygems.org/gems/rubocop.'
|
27
|
-
super(Rainbow(message).red + Rainbow(hint).yellow)
|
23
|
+
super(message)
|
28
24
|
end
|
29
25
|
end
|
30
26
|
|
@@ -157,8 +153,11 @@ module RuboCop
|
|
157
153
|
file_started(file)
|
158
154
|
offenses = file_offenses(file)
|
159
155
|
rescue InfiniteCorrectionLoop => e
|
156
|
+
raise e if @options[:raise_cop_error]
|
157
|
+
|
158
|
+
errors << e
|
159
|
+
warn Rainbow(e.message).red
|
160
160
|
offenses = e.offenses.compact.sort.freeze
|
161
|
-
raise
|
162
161
|
ensure
|
163
162
|
file_finished(file, offenses || [])
|
164
163
|
end
|
data/lib/rubocop/target_ruby.rb
CHANGED
@@ -34,6 +34,20 @@ module RuboCop
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
+
# The target ruby version may be configured by setting the
|
38
|
+
# `RUBOCOP_TARGET_RUBY_VERSION` environment variable.
|
39
|
+
class RuboCopEnvVar < Source
|
40
|
+
def name
|
41
|
+
'`RUBOCOP_TARGET_RUBY_VERSION` environment variable'
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def find_version
|
47
|
+
ENV.fetch('RUBOCOP_TARGET_RUBY_VERSION', nil)&.to_f
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
37
51
|
# The target ruby version may be configured in RuboCop's config.
|
38
52
|
# @api private
|
39
53
|
class RuboCopConfig < Source
|
@@ -246,6 +260,7 @@ module RuboCop
|
|
246
260
|
end
|
247
261
|
|
248
262
|
SOURCES = [
|
263
|
+
RuboCopEnvVar,
|
249
264
|
RuboCopConfig,
|
250
265
|
GemspecFile,
|
251
266
|
RubyVersionFile,
|
data/lib/rubocop/version.rb
CHANGED
data/lib/rubocop.rb
CHANGED
@@ -300,6 +300,7 @@ require_relative 'rubocop/cop/lint/boolean_symbol'
|
|
300
300
|
require_relative 'rubocop/cop/lint/circular_argument_reference'
|
301
301
|
require_relative 'rubocop/cop/lint/constant_definition_in_block'
|
302
302
|
require_relative 'rubocop/cop/lint/constant_overwritten_in_rescue'
|
303
|
+
require_relative 'rubocop/cop/lint/constant_reassignment'
|
303
304
|
require_relative 'rubocop/cop/lint/constant_resolution'
|
304
305
|
require_relative 'rubocop/cop/lint/debugger'
|
305
306
|
require_relative 'rubocop/cop/lint/deprecated_class_methods'
|
@@ -329,6 +330,7 @@ require_relative 'rubocop/cop/lint/empty_in_pattern'
|
|
329
330
|
require_relative 'rubocop/cop/lint/empty_interpolation'
|
330
331
|
require_relative 'rubocop/cop/lint/empty_when'
|
331
332
|
require_relative 'rubocop/cop/lint/ensure_return'
|
333
|
+
require_relative 'rubocop/cop/lint/shared_mutable_default'
|
332
334
|
require_relative 'rubocop/cop/lint/erb_new_arguments'
|
333
335
|
require_relative 'rubocop/cop/lint/flip_flop'
|
334
336
|
require_relative 'rubocop/cop/lint/float_comparison'
|
@@ -573,6 +575,7 @@ require_relative 'rubocop/cop/style/inverse_methods'
|
|
573
575
|
require_relative 'rubocop/cop/style/inline_comment'
|
574
576
|
require_relative 'rubocop/cop/style/invertible_unless_condition'
|
575
577
|
require_relative 'rubocop/cop/style/ip_addresses'
|
578
|
+
require_relative 'rubocop/cop/style/it_assignment'
|
576
579
|
require_relative 'rubocop/cop/style/keyword_arguments_merging'
|
577
580
|
require_relative 'rubocop/cop/style/keyword_parameters_order'
|
578
581
|
require_relative 'rubocop/cop/style/lambda'
|