rubocop 1.51.0 → 1.54.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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/config/default.yml +62 -3
  4. data/lib/rubocop/cli/command/lsp.rb +19 -0
  5. data/lib/rubocop/cli.rb +3 -0
  6. data/lib/rubocop/config_loader_resolver.rb +4 -3
  7. data/lib/rubocop/cop/base.rb +1 -1
  8. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  9. data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
  10. data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
  11. data/lib/rubocop/cop/internal_affairs/cop_description.rb +32 -8
  12. data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +3 -1
  13. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +3 -3
  14. data/lib/rubocop/cop/layout/class_structure.rb +7 -0
  15. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
  16. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +27 -4
  17. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
  18. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  19. data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
  20. data/lib/rubocop/cop/layout/line_end_string_concatenation_indentation.rb +2 -0
  21. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
  22. data/lib/rubocop/cop/layout/space_after_comma.rb +9 -1
  23. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -1
  24. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  25. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +2 -1
  26. data/lib/rubocop/cop/lint/debugger.rb +9 -5
  27. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
  28. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
  29. data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -2
  30. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
  31. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  32. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +1 -2
  33. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  34. data/lib/rubocop/cop/lint/missing_super.rb +34 -5
  35. data/lib/rubocop/cop/lint/mixed_case_range.rb +111 -0
  36. data/lib/rubocop/cop/lint/number_conversion.rb +5 -0
  37. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  38. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +130 -0
  39. data/lib/rubocop/cop/lint/redundant_require_statement.rb +8 -3
  40. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
  41. data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
  42. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  43. data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
  44. data/lib/rubocop/cop/lint/useless_assignment.rb +4 -1
  45. data/lib/rubocop/cop/lint/void.rb +12 -18
  46. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
  47. data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +30 -2
  48. data/lib/rubocop/cop/migration/department_name.rb +2 -2
  49. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  50. data/lib/rubocop/cop/mixin/comments_help.rb +1 -1
  51. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  52. data/lib/rubocop/cop/mixin/heredoc.rb +6 -2
  53. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  54. data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
  55. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +3 -3
  56. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  57. data/lib/rubocop/cop/style/accessor_grouping.rb +5 -1
  58. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  59. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  60. data/lib/rubocop/cop/style/block_delimiters.rb +3 -3
  61. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  62. data/lib/rubocop/cop/style/class_equality_comparison.rb +17 -39
  63. data/lib/rubocop/cop/style/collection_compact.rb +6 -0
  64. data/lib/rubocop/cop/style/conditional_assignment.rb +3 -1
  65. data/lib/rubocop/cop/style/dir.rb +1 -1
  66. data/lib/rubocop/cop/style/dir_empty.rb +8 -14
  67. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  68. data/lib/rubocop/cop/style/eval_with_location.rb +4 -4
  69. data/lib/rubocop/cop/style/exact_regexp_match.rb +8 -2
  70. data/lib/rubocop/cop/style/file_read.rb +2 -2
  71. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -22
  72. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  73. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  74. data/lib/rubocop/cop/style/identical_conditional_branches.rb +6 -2
  75. data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -2
  76. data/lib/rubocop/cop/style/invertible_unless_condition.rb +1 -1
  77. data/lib/rubocop/cop/style/lambda.rb +3 -3
  78. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +3 -4
  79. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  80. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  81. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
  82. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  83. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  84. data/lib/rubocop/cop/style/redundant_conditional.rb +1 -1
  85. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
  86. data/lib/rubocop/cop/style/redundant_filter_chain.rb +101 -0
  87. data/lib/rubocop/cop/style/redundant_line_continuation.rb +2 -2
  88. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  89. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +100 -0
  90. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  91. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
  92. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +3 -1
  93. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  94. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -0
  95. data/lib/rubocop/cop/style/require_order.rb +2 -1
  96. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  97. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +81 -0
  98. data/lib/rubocop/cop/style/select_by_regexp.rb +15 -5
  99. data/lib/rubocop/cop/style/signal_exception.rb +1 -1
  100. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  101. data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
  102. data/lib/rubocop/cop/style/special_global_vars.rb +1 -2
  103. data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
  104. data/lib/rubocop/cop/style/yoda_condition.rb +4 -2
  105. data/lib/rubocop/cop/util.rb +1 -1
  106. data/lib/rubocop/cop/utils/regexp_ranges.rb +100 -0
  107. data/lib/rubocop/cop/variable_force/assignment.rb +43 -4
  108. data/lib/rubocop/cop/variable_force.rb +1 -0
  109. data/lib/rubocop/cops_documentation_generator.rb +1 -1
  110. data/lib/rubocop/ext/regexp_parser.rb +4 -1
  111. data/lib/rubocop/lsp/logger.rb +22 -0
  112. data/lib/rubocop/lsp/routes.rb +231 -0
  113. data/lib/rubocop/lsp/runtime.rb +82 -0
  114. data/lib/rubocop/lsp/server.rb +66 -0
  115. data/lib/rubocop/lsp/severity.rb +27 -0
  116. data/lib/rubocop/options.rb +11 -1
  117. data/lib/rubocop/server/client_command/exec.rb +2 -1
  118. data/lib/rubocop/version.rb +8 -4
  119. data/lib/rubocop.rb +12 -0
  120. metadata +36 -5
@@ -0,0 +1,231 @@
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
+ # Routes for Language Server Protocol of RuboCop.
17
+ # @api private
18
+ class Routes
19
+ def self.handle(name, &block)
20
+ define_method("handle_#{name}", &block)
21
+ end
22
+
23
+ private_class_method :handle
24
+
25
+ def initialize(server)
26
+ @server = server
27
+
28
+ @text_cache = {}
29
+ end
30
+
31
+ def for(name)
32
+ name = "handle_#{name}"
33
+ return unless respond_to?(name)
34
+
35
+ method(name)
36
+ end
37
+
38
+ handle 'initialize' do |request|
39
+ @server.configure(safe_autocorrect: safe_autocorrect?(request))
40
+
41
+ @server.write(
42
+ id: request[:id],
43
+ result: LanguageServer::Protocol::Interface::InitializeResult.new(
44
+ capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
45
+ document_formatting_provider: true,
46
+ diagnostic_provider: true,
47
+ text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
48
+ change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::FULL,
49
+ open_close: true
50
+ )
51
+ )
52
+ )
53
+ )
54
+ end
55
+
56
+ handle 'initialized' do |_request|
57
+ version = RuboCop::Version::STRING
58
+
59
+ Logger.log("RuboCop #{version} language server initialized, PID #{Process.pid}")
60
+ end
61
+
62
+ handle 'shutdown' do |request|
63
+ Logger.log('Client asked to shutdown RuboCop language server.')
64
+ @server.stop do
65
+ @server.write(id: request[:id], result: nil)
66
+ Logger.log('Exiting...')
67
+ end
68
+ end
69
+
70
+ handle 'textDocument/diagnostic' do |request|
71
+ doc = request[:params][:textDocument]
72
+ result = diagnostic(doc[:uri], doc[:text])
73
+ @server.write(result)
74
+ end
75
+
76
+ handle 'textDocument/didChange' do |request|
77
+ params = request[:params]
78
+ result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
79
+ @server.write(result)
80
+ end
81
+
82
+ handle 'textDocument/didOpen' do |request|
83
+ doc = request[:params][:textDocument]
84
+ result = diagnostic(doc[:uri], doc[:text])
85
+ @server.write(result)
86
+ end
87
+
88
+ handle 'textDocument/didClose' do |request|
89
+ @text_cache.delete(request.dig(:params, :textDocument, :uri))
90
+ end
91
+
92
+ handle 'textDocument/formatting' do |request|
93
+ uri = request[:params][:textDocument][:uri]
94
+ @server.write(id: request[:id], result: format_file(uri))
95
+ end
96
+
97
+ handle 'workspace/didChangeConfiguration' do |_request|
98
+ Logger.log('Ignoring workspace/didChangeConfiguration')
99
+ end
100
+
101
+ handle 'workspace/didChangeWatchedFiles' do |request|
102
+ changed = request[:params][:changes].any? do |change|
103
+ change[:uri].end_with?(RuboCop::ConfigFinder::DOTFILE)
104
+ end
105
+
106
+ if changed
107
+ Logger.log('Configuration file changed; restart required')
108
+ @server.stop
109
+ end
110
+ end
111
+
112
+ handle 'workspace/executeCommand' do |request|
113
+ if request[:params][:command] == 'rubocop.formatAutocorrects'
114
+ uri = request[:params][:arguments][0][:uri]
115
+ @server.write(
116
+ id: request[:id],
117
+ method: 'workspace/applyEdit',
118
+ params: {
119
+ label: 'Format with RuboCop autocorrects',
120
+ edit: {
121
+ changes: {
122
+ uri => format_file(uri)
123
+ }
124
+ }
125
+ }
126
+ )
127
+ else
128
+ handle_unsupported_method(request, request[:params][:command])
129
+ end
130
+ end
131
+
132
+ handle 'textDocument/willSave' do |_request|
133
+ # Nothing to do
134
+ end
135
+
136
+ handle 'textDocument/didSave' do |_request|
137
+ # Nothing to do
138
+ end
139
+
140
+ handle '$/cancelRequest' do |_request|
141
+ # Can't cancel anything because single-threaded
142
+ end
143
+
144
+ handle '$/setTrace' do |_request|
145
+ # No-op, we log everything
146
+ end
147
+
148
+ def handle_unsupported_method(request, method = request[:method])
149
+ @server.write(
150
+ id: request[:id],
151
+ error: LanguageServer::Protocol::Interface::ResponseError.new(
152
+ code: LanguageServer::Protocol::Constant::ErrorCodes::METHOD_NOT_FOUND,
153
+ message: "Unsupported Method: #{method}"
154
+ )
155
+ )
156
+ Logger.log("Unsupported Method: #{method}")
157
+ end
158
+
159
+ def handle_method_missing(request)
160
+ return unless request.key?(:id)
161
+
162
+ @server.write(id: request[:id], result: nil)
163
+ end
164
+
165
+ private
166
+
167
+ def safe_autocorrect?(request)
168
+ safe_autocorrect = request.dig(:params, :initializationOptions, :safeAutocorrect)
169
+
170
+ safe_autocorrect.nil? || safe_autocorrect == true
171
+ end
172
+
173
+ def format_file(file_uri)
174
+ unless (text = @text_cache[file_uri])
175
+ Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
176
+
177
+ return []
178
+ end
179
+
180
+ new_text = @server.format(remove_file_protocol_from(file_uri), text)
181
+
182
+ return [] if new_text == text
183
+
184
+ [
185
+ newText: new_text,
186
+ range: {
187
+ start: { line: 0, character: 0 },
188
+ end: { line: text.count("\n") + 1, character: 0 }
189
+ }
190
+ ]
191
+ end
192
+
193
+ def diagnostic(file_uri, text)
194
+ @text_cache[file_uri] = text
195
+ offenses = @server.offenses(remove_file_protocol_from(file_uri), text)
196
+ diagnostics = offenses.map { |offense| to_diagnostic(offense) }
197
+
198
+ {
199
+ method: 'textDocument/publishDiagnostics',
200
+ params: {
201
+ uri: file_uri,
202
+ diagnostics: diagnostics
203
+ }
204
+ }
205
+ end
206
+
207
+ def remove_file_protocol_from(uri)
208
+ uri.delete_prefix('file://')
209
+ end
210
+
211
+ def to_diagnostic(offense)
212
+ code = offense[:cop_name]
213
+ message = offense[:message]
214
+ loc = offense[:location]
215
+ rubocop_severity = offense[:severity]
216
+ severity = Severity.find_by(rubocop_severity)
217
+
218
+ {
219
+ code: code, message: message, range: to_range(loc), severity: severity, source: 'rubocop'
220
+ }
221
+ end
222
+
223
+ def to_range(location)
224
+ {
225
+ start: { character: location[:start_column] - 1, line: location[:start_line] - 1 },
226
+ end: { character: location[:last_column] - 1, line: location[:last_line] - 1 }
227
+ }
228
+ end
229
+ end
230
+ end
231
+ end
@@ -0,0 +1,82 @@
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
+ # Runtime for Language Server Protocol of RuboCop.
15
+ # @api private
16
+ class Runtime
17
+ attr_writer :safe_autocorrect
18
+
19
+ def initialize(config_store)
20
+ @config_store = config_store
21
+ @logged_paths = []
22
+ @safe_autocorrect = true
23
+ end
24
+
25
+ # This abuses the `--stdin` option of rubocop and reads the formatted text
26
+ # from the `options[:stdin]` that rubocop mutates. This depends on
27
+ # `parallel: false` as well as the fact that RuboCop doesn't otherwise dup
28
+ # or reassign that options object. Risky business!
29
+ #
30
+ # Reassigning `options[:stdin]` is done here:
31
+ # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cop/team.rb#L131
32
+ # Printing `options[:stdin]`
33
+ # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cli/command/execute_runner.rb#L95
34
+ # Setting `parallel: true` would break this here:
35
+ # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
36
+ def format(path, text)
37
+ formatting_options = {
38
+ stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: @safe_autocorrect
39
+ }
40
+
41
+ redirect_stdout { run_rubocop(formatting_options, path) }
42
+
43
+ formatting_options[:stdin]
44
+ end
45
+
46
+ def offenses(path, text)
47
+ diagnostic_options = {
48
+ stdin: text, force_exclusion: true, formatters: ['json'], format: 'json'
49
+ }
50
+
51
+ json = redirect_stdout { run_rubocop(diagnostic_options, path) }
52
+ results = JSON.parse(json, symbolize_names: true)
53
+
54
+ if results[:files].empty?
55
+ unless @logged_paths.include?(path)
56
+ Logger.log "Ignoring file, per configuration: #{path}"
57
+ @logged_paths << path
58
+ end
59
+ return []
60
+ end
61
+
62
+ results.dig(:files, 0, :offenses)
63
+ end
64
+
65
+ private
66
+
67
+ def redirect_stdout(&block)
68
+ stdout = StringIO.new
69
+
70
+ RuboCop::Server::Helper.redirect(stdout: stdout, &block)
71
+
72
+ stdout.string
73
+ end
74
+
75
+ def run_rubocop(options, path)
76
+ runner = RuboCop::Runner.new(options, @config_store)
77
+
78
+ runner.run([path])
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'language_server-protocol'
4
+ require_relative 'logger'
5
+ require_relative 'routes'
6
+ require_relative 'runtime'
7
+
8
+ #
9
+ # This code is based on https://github.com/standardrb/standard.
10
+ #
11
+ # Copyright (c) 2023 Test Double, Inc.
12
+ #
13
+ # The MIT License (MIT)
14
+ #
15
+ # https://github.com/standardrb/standard/blob/main/LICENSE.txt
16
+ #
17
+ module RuboCop
18
+ module Lsp
19
+ # Language Server Protocol of RuboCop.
20
+ # @api private
21
+ class Server
22
+ def initialize(config_store)
23
+ @reader = LanguageServer::Protocol::Transport::Io::Reader.new($stdin)
24
+ @writer = LanguageServer::Protocol::Transport::Io::Writer.new($stdout)
25
+ @runtime = RuboCop::Lsp::Runtime.new(config_store)
26
+ @routes = Routes.new(self)
27
+ end
28
+
29
+ def start
30
+ @reader.read do |request|
31
+ if !request.key?(:method)
32
+ @routes.handle_method_missing(request)
33
+ elsif (route = @routes.for(request[:method]))
34
+ route.call(request)
35
+ else
36
+ @routes.handle_unsupported_method(request)
37
+ end
38
+ rescue StandardError => e
39
+ Logger.log("Error #{e.class} #{e.message[0..100]}")
40
+ Logger.log(e.backtrace.inspect)
41
+ end
42
+ end
43
+
44
+ def write(response)
45
+ @writer.write(response)
46
+ end
47
+
48
+ def format(path, text)
49
+ @runtime.format(path, text)
50
+ end
51
+
52
+ def offenses(path, text)
53
+ @runtime.offenses(path, text)
54
+ end
55
+
56
+ def configure(safe_autocorrect: true)
57
+ @runtime.safe_autocorrect = safe_autocorrect
58
+ end
59
+
60
+ def stop(&block)
61
+ at_exit(&block) if block
62
+ exit
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Lsp
5
+ # Severity for Language Server Protocol of RuboCop.
6
+ # @api private
7
+ class Severity
8
+ SEVERITIES = {
9
+ fatal: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
10
+ error: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
11
+ warning: LanguageServer::Protocol::Constant::DiagnosticSeverity::WARNING,
12
+ convention: LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION,
13
+ refactor: LanguageServer::Protocol::Constant::DiagnosticSeverity::HINT,
14
+ info: LanguageServer::Protocol::Constant::DiagnosticSeverity::HINT
15
+ }.freeze
16
+
17
+ def self.find_by(rubocop_severity)
18
+ if (severity = SEVERITIES[rubocop_severity.to_sym])
19
+ return severity
20
+ end
21
+
22
+ Logger.log("Unknown severity: #{rubocop_severity}")
23
+ LanguageServer::Protocol::Constant::DiagnosticSeverity::HINT
24
+ end
25
+ end
26
+ end
27
+ end
@@ -16,7 +16,7 @@ module RuboCop
16
16
  'root of the project. RuboCop will use this path to determine which ' \
17
17
  'cops are enabled (via eg. Include/Exclude), and so that certain cops ' \
18
18
  'like Naming/FileName can be checked.'
19
- EXITING_OPTIONS = %i[version verbose_version show_cops show_docs_url].freeze
19
+ EXITING_OPTIONS = %i[version verbose_version show_cops show_docs_url lsp].freeze
20
20
  DEFAULT_MAXIMUM_EXCLUSION_ITEMS = 15
21
21
 
22
22
  def initialize
@@ -49,12 +49,14 @@ module RuboCop
49
49
 
50
50
  private
51
51
 
52
+ # rubocop:disable Metrics/AbcSize
52
53
  def define_options
53
54
  OptionParser.new do |opts|
54
55
  opts.banner = rainbow.wrap('Usage: rubocop [options] [file1, file2, ...]').bright
55
56
 
56
57
  add_check_options(opts)
57
58
  add_cache_options(opts)
59
+ add_lsp_option(opts)
58
60
  add_server_options(opts)
59
61
  add_output_options(opts)
60
62
  add_autocorrection_options(opts)
@@ -66,6 +68,7 @@ module RuboCop
66
68
  add_profile_options(opts) if RUBY_ENGINE == 'ruby' && !Platform.windows?
67
69
  end
68
70
  end
71
+ # rubocop:enable Metrics/AbcSize
69
72
 
70
73
  def add_check_options(opts) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
71
74
  section(opts, 'Basic Options') do # rubocop:disable Metrics/BlockLength
@@ -205,6 +208,12 @@ module RuboCop
205
208
  end
206
209
  end
207
210
 
211
+ def add_lsp_option(opts)
212
+ section(opts, 'LSP Option') do
213
+ option(opts, '--lsp')
214
+ end
215
+ end
216
+
208
217
  def add_server_options(opts)
209
218
  section(opts, 'Server Options') do
210
219
  option(opts, '--[no-]server')
@@ -620,6 +629,7 @@ module RuboCop
620
629
  stop_server: 'Stop server process.',
621
630
  server_status: 'Show server status.',
622
631
  no_detach: 'Run the server process in the foreground.',
632
+ lsp: 'Start a language server listening on STDIN.',
623
633
  raise_cop_error: ['Raise cop-related errors with cause and location.',
624
634
  'This is used to prevent cops from failing silently.',
625
635
  'Default is false.'],
@@ -18,10 +18,11 @@ module RuboCop
18
18
  def run
19
19
  ensure_server!
20
20
  Cache.status_path.delete if Cache.status_path.file?
21
+ read_stdin = ARGV.include?('-s') || ARGV.include?('--stdin')
21
22
  send_request(
22
23
  command: 'exec',
23
24
  args: ARGV.dup,
24
- body: $stdin.tty? ? '' : $stdin.read
25
+ body: read_stdin ? $stdin.read : ''
25
26
  )
26
27
  warn stderr unless stderr.empty?
27
28
  status
@@ -3,15 +3,19 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.51.0'
6
+ STRING = '1.54.1'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, ' \
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
10
10
  'running on %<ruby_engine>s %<ruby_version>s)%<server_mode>s [%<ruby_platform>s]'
11
11
 
12
- CANONICAL_FEATURE_NAMES = { 'Rspec' => 'RSpec', 'Graphql' => 'GraphQL', 'Md' => 'Markdown',
13
- 'Thread_safety' => 'ThreadSafety' }.freeze
14
- EXTENSION_PATH_NAMES = { 'rubocop-md' => 'markdown' }.freeze
12
+ CANONICAL_FEATURE_NAMES = {
13
+ 'Rspec' => 'RSpec', 'Graphql' => 'GraphQL', 'Md' => 'Markdown', 'Factory_bot' => 'FactoryBot',
14
+ 'Thread_safety' => 'ThreadSafety'
15
+ }.freeze
16
+ EXTENSION_PATH_NAMES = {
17
+ 'rubocop-md' => 'markdown', 'rubocop-factory_bot' => 'factory_bot'
18
+ }.freeze
15
19
 
16
20
  # @api private
17
21
  def self.version(debug: false, env: nil)
data/lib/rubocop.rb CHANGED
@@ -69,6 +69,7 @@ require_relative 'rubocop/cop/mixin/alignment'
69
69
  require_relative 'rubocop/cop/mixin/allowed_identifiers'
70
70
  require_relative 'rubocop/cop/mixin/allowed_methods'
71
71
  require_relative 'rubocop/cop/mixin/allowed_pattern'
72
+ require_relative 'rubocop/cop/mixin/allowed_receivers'
72
73
  require_relative 'rubocop/cop/mixin/auto_corrector' # rubocop:todo Naming/InclusiveLanguage
73
74
  require_relative 'rubocop/cop/mixin/check_assignment'
74
75
  require_relative 'rubocop/cop/mixin/check_line_breakable'
@@ -138,6 +139,7 @@ require_relative 'rubocop/cop/mixin/comments_help' # relies on visibility_help
138
139
  require_relative 'rubocop/cop/mixin/def_node' # relies on visibility_help
139
140
 
140
141
  require_relative 'rubocop/cop/utils/format_string'
142
+ require_relative 'rubocop/cop/utils/regexp_ranges'
141
143
 
142
144
  require_relative 'rubocop/cop/migration/department_name'
143
145
 
@@ -335,6 +337,7 @@ require_relative 'rubocop/cop/lint/literal_in_interpolation'
335
337
  require_relative 'rubocop/cop/lint/loop'
336
338
  require_relative 'rubocop/cop/lint/missing_cop_enable_directive'
337
339
  require_relative 'rubocop/cop/lint/missing_super'
340
+ require_relative 'rubocop/cop/lint/mixed_case_range'
338
341
  require_relative 'rubocop/cop/lint/mixed_regexp_capture_types'
339
342
  require_relative 'rubocop/cop/lint/multiple_comparison'
340
343
  require_relative 'rubocop/cop/lint/nested_method_definition'
@@ -357,6 +360,7 @@ require_relative 'rubocop/cop/lint/rand_one'
357
360
  require_relative 'rubocop/cop/lint/redundant_cop_disable_directive'
358
361
  require_relative 'rubocop/cop/lint/redundant_cop_enable_directive'
359
362
  require_relative 'rubocop/cop/lint/redundant_dir_glob_sort'
363
+ require_relative 'rubocop/cop/lint/redundant_regexp_quantifiers'
360
364
  require_relative 'rubocop/cop/lint/redundant_require_statement'
361
365
  require_relative 'rubocop/cop/lint/redundant_safe_navigation'
362
366
  require_relative 'rubocop/cop/lint/redundant_splat_expansion'
@@ -558,15 +562,20 @@ require_relative 'rubocop/cop/style/multiline_in_pattern_then'
558
562
  require_relative 'rubocop/cop/style/numbered_parameters'
559
563
  require_relative 'rubocop/cop/style/open_struct_use'
560
564
  require_relative 'rubocop/cop/style/operator_method_call'
565
+ require_relative 'rubocop/cop/style/redundant_array_constructor'
561
566
  require_relative 'rubocop/cop/style/redundant_assignment'
562
567
  require_relative 'rubocop/cop/style/redundant_constant_base'
568
+ require_relative 'rubocop/cop/style/redundant_current_directory_in_path'
563
569
  require_relative 'rubocop/cop/style/redundant_double_splat_hash_braces'
564
570
  require_relative 'rubocop/cop/style/redundant_each'
565
571
  require_relative 'rubocop/cop/style/redundant_fetch_block'
566
572
  require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
573
+ require_relative 'rubocop/cop/style/redundant_filter_chain'
567
574
  require_relative 'rubocop/cop/style/redundant_heredoc_delimiter_quotes'
568
575
  require_relative 'rubocop/cop/style/redundant_initialize'
569
576
  require_relative 'rubocop/cop/style/redundant_line_continuation'
577
+ require_relative 'rubocop/cop/style/redundant_regexp_argument'
578
+ require_relative 'rubocop/cop/style/redundant_regexp_constructor'
570
579
  require_relative 'rubocop/cop/style/redundant_self_assignment'
571
580
  require_relative 'rubocop/cop/style/redundant_self_assignment_branch'
572
581
  require_relative 'rubocop/cop/style/require_order'
@@ -644,6 +653,7 @@ require_relative 'rubocop/cop/style/regexp_literal'
644
653
  require_relative 'rubocop/cop/style/rescue_modifier'
645
654
  require_relative 'rubocop/cop/style/rescue_standard_error'
646
655
  require_relative 'rubocop/cop/style/return_nil'
656
+ require_relative 'rubocop/cop/style/return_nil_in_predicate_method_definition'
647
657
  require_relative 'rubocop/cop/style/safe_navigation'
648
658
  require_relative 'rubocop/cop/style/sample'
649
659
  require_relative 'rubocop/cop/style/select_by_regexp'
@@ -690,6 +700,7 @@ require_relative 'rubocop/cop/style/when_then'
690
700
  require_relative 'rubocop/cop/style/while_until_do'
691
701
  require_relative 'rubocop/cop/style/while_until_modifier'
692
702
  require_relative 'rubocop/cop/style/word_array'
703
+ require_relative 'rubocop/cop/style/yaml_file_read'
693
704
  require_relative 'rubocop/cop/style/yoda_condition'
694
705
  require_relative 'rubocop/cop/style/yoda_expression'
695
706
  require_relative 'rubocop/cop/style/zero_length_predicate'
@@ -735,6 +746,7 @@ require_relative 'rubocop/cli/command/base'
735
746
  require_relative 'rubocop/cli/command/auto_generate_config'
736
747
  require_relative 'rubocop/cli/command/execute_runner'
737
748
  require_relative 'rubocop/cli/command/init_dotfile'
749
+ require_relative 'rubocop/cli/command/lsp'
738
750
  require_relative 'rubocop/cli/command/show_cops'
739
751
  require_relative 'rubocop/cli/command/show_docs_url'
740
752
  require_relative 'rubocop/cli/command/suggest_extensions'