rubocop 1.50.2 → 1.53.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.
Files changed (141) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/config/default.yml +76 -6
  4. data/lib/rubocop/cli/command/lsp.rb +19 -0
  5. data/lib/rubocop/cli.rb +3 -0
  6. data/lib/rubocop/config.rb +4 -0
  7. data/lib/rubocop/config_loader_resolver.rb +4 -3
  8. data/lib/rubocop/config_obsoletion.rb +2 -2
  9. data/lib/rubocop/cop/base.rb +5 -1
  10. data/lib/rubocop/cop/bundler/gem_comment.rb +1 -1
  11. data/lib/rubocop/cop/bundler/gem_version.rb +2 -2
  12. data/lib/rubocop/cop/correctors/alignment_corrector.rb +1 -1
  13. data/lib/rubocop/cop/gemspec/dependency_version.rb +2 -2
  14. data/lib/rubocop/cop/gemspec/development_dependencies.rb +1 -1
  15. data/lib/rubocop/cop/internal_affairs/cop_description.rb +32 -8
  16. data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +5 -5
  17. data/lib/rubocop/cop/layout/class_structure.rb +7 -0
  18. data/lib/rubocop/cop/layout/closing_heredoc_indentation.rb +1 -2
  19. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +1 -1
  20. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +2 -0
  21. data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +2 -2
  22. data/lib/rubocop/cop/layout/indentation_style.rb +1 -1
  23. data/lib/rubocop/cop/layout/indentation_width.rb +2 -2
  24. data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -1
  25. data/lib/rubocop/cop/layout/space_inside_block_braces.rb +2 -0
  26. data/lib/rubocop/cop/layout/space_inside_range_literal.rb +1 -1
  27. data/lib/rubocop/cop/lint/ambiguous_block_association.rb +13 -1
  28. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  29. data/lib/rubocop/cop/lint/duplicate_hash_key.rb +2 -1
  30. data/lib/rubocop/cop/lint/duplicate_regexp_character_class_element.rb +46 -19
  31. data/lib/rubocop/cop/lint/erb_new_arguments.rb +3 -4
  32. data/lib/rubocop/cop/lint/heredoc_method_call_position.rb +1 -1
  33. data/lib/rubocop/cop/lint/identity_comparison.rb +0 -1
  34. data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +5 -3
  35. data/lib/rubocop/cop/lint/inherit_exception.rb +9 -0
  36. data/lib/rubocop/cop/lint/lambda_without_literal_block.rb +1 -1
  37. data/lib/rubocop/cop/lint/missing_super.rb +34 -5
  38. data/lib/rubocop/cop/lint/mixed_case_range.rb +109 -0
  39. data/lib/rubocop/cop/lint/number_conversion.rb +5 -0
  40. data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +2 -2
  41. data/lib/rubocop/cop/lint/ordered_magic_comments.rb +0 -1
  42. data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +2 -2
  43. data/lib/rubocop/cop/lint/redundant_regexp_quantifiers.rb +120 -0
  44. data/lib/rubocop/cop/lint/redundant_require_statement.rb +8 -3
  45. data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -1
  46. data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -2
  47. data/lib/rubocop/cop/lint/shadowed_exception.rb +5 -11
  48. data/lib/rubocop/cop/lint/suppressed_exception.rb +1 -1
  49. data/lib/rubocop/cop/lint/top_level_return_with_argument.rb +23 -9
  50. data/lib/rubocop/cop/lint/useless_assignment.rb +59 -1
  51. data/lib/rubocop/cop/lint/void.rb +63 -7
  52. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -2
  53. data/lib/rubocop/cop/migration/department_name.rb +2 -2
  54. data/lib/rubocop/cop/mixin/allowed_receivers.rb +34 -0
  55. data/lib/rubocop/cop/mixin/comments_help.rb +7 -3
  56. data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -1
  57. data/lib/rubocop/cop/mixin/percent_literal.rb +1 -1
  58. data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
  59. data/lib/rubocop/cop/naming/block_forwarding.rb +1 -1
  60. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  61. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +25 -10
  62. data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +11 -3
  63. data/lib/rubocop/cop/naming/variable_name.rb +6 -1
  64. data/lib/rubocop/cop/style/accessor_grouping.rb +5 -1
  65. data/lib/rubocop/cop/style/attr.rb +11 -1
  66. data/lib/rubocop/cop/style/begin_block.rb +1 -2
  67. data/lib/rubocop/cop/style/block_comments.rb +1 -1
  68. data/lib/rubocop/cop/style/block_delimiters.rb +3 -3
  69. data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
  70. data/lib/rubocop/cop/style/class_equality_comparison.rb +17 -39
  71. data/lib/rubocop/cop/style/collection_compact.rb +16 -6
  72. data/lib/rubocop/cop/style/colon_method_call.rb +2 -2
  73. data/lib/rubocop/cop/style/combinable_loops.rb +26 -6
  74. data/lib/rubocop/cop/style/conditional_assignment.rb +5 -3
  75. data/lib/rubocop/cop/style/copyright.rb +5 -2
  76. data/lib/rubocop/cop/style/dir.rb +1 -1
  77. data/lib/rubocop/cop/style/dir_empty.rb +8 -14
  78. data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
  79. data/lib/rubocop/cop/style/documentation.rb +1 -1
  80. data/lib/rubocop/cop/style/eval_with_location.rb +5 -5
  81. data/lib/rubocop/cop/style/exact_regexp_match.rb +68 -0
  82. data/lib/rubocop/cop/style/file_read.rb +2 -2
  83. data/lib/rubocop/cop/style/guard_clause.rb +2 -0
  84. data/lib/rubocop/cop/style/hash_each_methods.rb +1 -22
  85. data/lib/rubocop/cop/style/hash_except.rb +19 -8
  86. data/lib/rubocop/cop/style/hash_transform_keys.rb +2 -2
  87. data/lib/rubocop/cop/style/hash_transform_values.rb +2 -2
  88. data/lib/rubocop/cop/style/identical_conditional_branches.rb +6 -2
  89. data/lib/rubocop/cop/style/if_inside_else.rb +6 -0
  90. data/lib/rubocop/cop/style/if_unless_modifier.rb +3 -0
  91. data/lib/rubocop/cop/style/invertible_unless_condition.rb +10 -6
  92. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +3 -4
  93. data/lib/rubocop/cop/style/multiple_comparison.rb +14 -0
  94. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  95. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
  96. data/lib/rubocop/cop/style/preferred_hash_methods.rb +1 -1
  97. data/lib/rubocop/cop/style/redundant_array_constructor.rb +77 -0
  98. data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
  99. data/lib/rubocop/cop/style/redundant_conditional.rb +1 -1
  100. data/lib/rubocop/cop/style/redundant_current_directory_in_path.rb +38 -0
  101. data/lib/rubocop/cop/style/redundant_filter_chain.rb +101 -0
  102. data/lib/rubocop/cop/style/redundant_line_continuation.rb +7 -3
  103. data/lib/rubocop/cop/style/redundant_parentheses.rb +1 -1
  104. data/lib/rubocop/cop/style/redundant_regexp_argument.rb +86 -0
  105. data/lib/rubocop/cop/style/redundant_regexp_constructor.rb +46 -0
  106. data/lib/rubocop/cop/style/redundant_regexp_escape.rb +2 -1
  107. data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +3 -1
  108. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  109. data/lib/rubocop/cop/style/redundant_string_escape.rb +2 -0
  110. data/lib/rubocop/cop/style/regexp_literal.rb +11 -2
  111. data/lib/rubocop/cop/style/require_order.rb +11 -5
  112. data/lib/rubocop/cop/style/rescue_modifier.rb +1 -3
  113. data/lib/rubocop/cop/style/return_nil_in_predicate_method_definition.rb +81 -0
  114. data/lib/rubocop/cop/style/select_by_regexp.rb +15 -5
  115. data/lib/rubocop/cop/style/semicolon.rb +12 -1
  116. data/lib/rubocop/cop/style/signal_exception.rb +1 -1
  117. data/lib/rubocop/cop/style/single_line_methods.rb +1 -1
  118. data/lib/rubocop/cop/style/sole_nested_conditional.rb +3 -1
  119. data/lib/rubocop/cop/style/special_global_vars.rb +3 -4
  120. data/lib/rubocop/cop/style/yaml_file_read.rb +66 -0
  121. data/lib/rubocop/cop/team.rb +1 -1
  122. data/lib/rubocop/cop/util.rb +1 -1
  123. data/lib/rubocop/cop/utils/regexp_ranges.rb +100 -0
  124. data/lib/rubocop/cop/variable_force/assignment.rb +33 -1
  125. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  126. data/lib/rubocop/cop/variable_force.rb +1 -0
  127. data/lib/rubocop/cops_documentation_generator.rb +1 -1
  128. data/lib/rubocop/ext/regexp_parser.rb +4 -1
  129. data/lib/rubocop/lsp/logger.rb +22 -0
  130. data/lib/rubocop/lsp/routes.rb +223 -0
  131. data/lib/rubocop/lsp/runtime.rb +79 -0
  132. data/lib/rubocop/lsp/server.rb +62 -0
  133. data/lib/rubocop/lsp/severity.rb +27 -0
  134. data/lib/rubocop/options.rb +11 -1
  135. data/lib/rubocop/result_cache.rb +1 -1
  136. data/lib/rubocop/rspec/cop_helper.rb +1 -1
  137. data/lib/rubocop/server/client_command/exec.rb +2 -1
  138. data/lib/rubocop/target_ruby.rb +3 -2
  139. data/lib/rubocop/version.rb +10 -6
  140. data/lib/rubocop.rb +13 -0
  141. metadata +38 -6
@@ -0,0 +1,223 @@
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.write(
40
+ id: request[:id],
41
+ result: LanguageServer::Protocol::Interface::InitializeResult.new(
42
+ capabilities: LanguageServer::Protocol::Interface::ServerCapabilities.new(
43
+ document_formatting_provider: true,
44
+ diagnostic_provider: true,
45
+ text_document_sync: LanguageServer::Protocol::Interface::TextDocumentSyncOptions.new(
46
+ change: LanguageServer::Protocol::Constant::TextDocumentSyncKind::FULL,
47
+ open_close: true
48
+ )
49
+ )
50
+ )
51
+ )
52
+ end
53
+
54
+ handle 'initialized' do |_request|
55
+ version = RuboCop::Version::STRING
56
+
57
+ Logger.log("RuboCop #{version} language server initialized, PID #{Process.pid}")
58
+ end
59
+
60
+ handle 'shutdown' do |request|
61
+ Logger.log('Client asked to shutdown RuboCop language server.')
62
+ @server.stop do
63
+ @server.write(id: request[:id], result: nil)
64
+ Logger.log('Exiting...')
65
+ end
66
+ end
67
+
68
+ handle 'textDocument/diagnostic' do |request|
69
+ doc = request[:params][:textDocument]
70
+ result = diagnostic(doc[:uri], doc[:text])
71
+ @server.write(result)
72
+ end
73
+
74
+ handle 'textDocument/didChange' do |request|
75
+ params = request[:params]
76
+ result = diagnostic(params[:textDocument][:uri], params[:contentChanges][0][:text])
77
+ @server.write(result)
78
+ end
79
+
80
+ handle 'textDocument/didOpen' do |request|
81
+ doc = request[:params][:textDocument]
82
+ result = diagnostic(doc[:uri], doc[:text])
83
+ @server.write(result)
84
+ end
85
+
86
+ handle 'textDocument/didClose' do |request|
87
+ @text_cache.delete(request.dig(:params, :textDocument, :uri))
88
+ end
89
+
90
+ handle 'textDocument/formatting' do |request|
91
+ uri = request[:params][:textDocument][:uri]
92
+ @server.write(id: request[:id], result: format_file(uri))
93
+ end
94
+
95
+ handle 'workspace/didChangeConfiguration' do |_request|
96
+ Logger.log('Ignoring workspace/didChangeConfiguration')
97
+ end
98
+
99
+ handle 'workspace/didChangeWatchedFiles' do |request|
100
+ changed = request[:params][:changes].any? do |change|
101
+ change[:uri].end_with?(RuboCop::ConfigFinder::DOTFILE)
102
+ end
103
+
104
+ if changed
105
+ Logger.log('Configuration file changed; restart required')
106
+ @server.stop
107
+ end
108
+ end
109
+
110
+ handle 'workspace/executeCommand' do |request|
111
+ if request[:params][:command] == 'rubocop.formatAutocorrects'
112
+ uri = request[:params][:arguments][0][:uri]
113
+ @server.write(
114
+ id: request[:id],
115
+ method: 'workspace/applyEdit',
116
+ params: {
117
+ label: 'Format with RuboCop autocorrects',
118
+ edit: {
119
+ changes: {
120
+ uri => format_file(uri)
121
+ }
122
+ }
123
+ }
124
+ )
125
+ else
126
+ handle_unsupported_method(request, request[:params][:command])
127
+ end
128
+ end
129
+
130
+ handle 'textDocument/willSave' do |_request|
131
+ # Nothing to do
132
+ end
133
+
134
+ handle 'textDocument/didSave' do |_request|
135
+ # Nothing to do
136
+ end
137
+
138
+ handle '$/cancelRequest' do |_request|
139
+ # Can't cancel anything because single-threaded
140
+ end
141
+
142
+ handle '$/setTrace' do |_request|
143
+ # No-op, we log everything
144
+ end
145
+
146
+ def handle_unsupported_method(request, method = request[:method])
147
+ @server.write(
148
+ id: request[:id],
149
+ error: LanguageServer::Protocol::Interface::ResponseError.new(
150
+ code: LanguageServer::Protocol::Constant::ErrorCodes::METHOD_NOT_FOUND,
151
+ message: "Unsupported Method: #{method}"
152
+ )
153
+ )
154
+ Logger.log("Unsupported Method: #{method}")
155
+ end
156
+
157
+ def handle_method_missing(request)
158
+ return unless request.key?(:id)
159
+
160
+ @server.write(id: request[:id], result: nil)
161
+ end
162
+
163
+ private
164
+
165
+ def format_file(file_uri)
166
+ unless (text = @text_cache[file_uri])
167
+ Logger.log("Format request arrived before text synchronized; skipping: `#{file_uri}'")
168
+
169
+ return []
170
+ end
171
+
172
+ new_text = @server.format(remove_file_protocol_from(file_uri), text)
173
+
174
+ return [] if new_text == text
175
+
176
+ [
177
+ newText: new_text,
178
+ range: {
179
+ start: { line: 0, character: 0 },
180
+ end: { line: text.count("\n") + 1, character: 0 }
181
+ }
182
+ ]
183
+ end
184
+
185
+ def diagnostic(file_uri, text)
186
+ @text_cache[file_uri] = text
187
+ offenses = @server.offenses(remove_file_protocol_from(file_uri), text)
188
+ diagnostics = offenses.map { |offense| to_diagnostic(offense) }
189
+
190
+ {
191
+ method: 'textDocument/publishDiagnostics',
192
+ params: {
193
+ uri: file_uri,
194
+ diagnostics: diagnostics
195
+ }
196
+ }
197
+ end
198
+
199
+ def remove_file_protocol_from(uri)
200
+ uri.delete_prefix('file://')
201
+ end
202
+
203
+ def to_diagnostic(offense)
204
+ code = offense[:cop_name]
205
+ message = offense[:message]
206
+ loc = offense[:location]
207
+ rubocop_severity = offense[:severity]
208
+ severity = Severity.find_by(rubocop_severity)
209
+
210
+ {
211
+ code: code, message: message, range: to_range(loc), severity: severity, source: 'rubocop'
212
+ }
213
+ end
214
+
215
+ def to_range(location)
216
+ {
217
+ start: { character: location[:start_column] - 1, line: location[:start_line] - 1 },
218
+ end: { character: location[:last_column] - 1, line: location[:last_line] - 1 }
219
+ }
220
+ end
221
+ end
222
+ end
223
+ end
@@ -0,0 +1,79 @@
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
+ def initialize(config_store)
18
+ @config_store = config_store
19
+ @logged_paths = []
20
+ end
21
+
22
+ # This abuses the `--stdin` option of rubocop and reads the formatted text
23
+ # from the `options[:stdin]` that rubocop mutates. This depends on
24
+ # `parallel: false` as well as the fact that RuboCop doesn't otherwise dup
25
+ # or reassign that options object. Risky business!
26
+ #
27
+ # Reassigning `options[:stdin]` is done here:
28
+ # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cop/team.rb#L131
29
+ # Printing `options[:stdin]`
30
+ # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/cli/command/execute_runner.rb#L95
31
+ # Setting `parallel: true` would break this here:
32
+ # https://github.com/rubocop/rubocop/blob/v1.52.0/lib/rubocop/runner.rb#L72
33
+ def format(path, text)
34
+ formatting_options = {
35
+ stdin: text, force_exclusion: true, autocorrect: true, safe_autocorrect: true
36
+ }
37
+
38
+ redirect_stdout { run_rubocop(formatting_options, path) }
39
+
40
+ formatting_options[:stdin]
41
+ end
42
+
43
+ def offenses(path, text)
44
+ diagnostic_options = {
45
+ stdin: text, force_exclusion: true, formatters: ['json'], format: 'json'
46
+ }
47
+
48
+ json = redirect_stdout { run_rubocop(diagnostic_options, path) }
49
+ results = JSON.parse(json, symbolize_names: true)
50
+
51
+ if results[:files].empty?
52
+ unless @logged_paths.include?(path)
53
+ Logger.log "Ignoring file, per configuration: #{path}"
54
+ @logged_paths << path
55
+ end
56
+ return []
57
+ end
58
+
59
+ results.dig(:files, 0, :offenses)
60
+ end
61
+
62
+ private
63
+
64
+ def redirect_stdout(&block)
65
+ stdout = StringIO.new
66
+
67
+ RuboCop::Server::Helper.redirect(stdout: stdout, &block)
68
+
69
+ stdout.string
70
+ end
71
+
72
+ def run_rubocop(options, path)
73
+ runner = RuboCop::Runner.new(options, @config_store)
74
+
75
+ runner.run([path])
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,62 @@
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
+ log("Error #{e.class} #{e.message[0..100]}")
40
+ 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 stop(&block)
57
+ at_exit(&block) if block
58
+ exit
59
+ end
60
+ end
61
+ end
62
+ 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.'],
@@ -83,7 +83,7 @@ module RuboCop
83
83
  config_store.for_pwd.for_all_cops['AllowSymlinksInCacheRootDirectory']
84
84
  end
85
85
 
86
- attr :path
86
+ attr_reader :path
87
87
 
88
88
  def initialize(file, team, options, config_store, cache_root = nil)
89
89
  cache_root ||= File.join(options[:cache_root], 'rubocop_cache') if options[:cache_root]
@@ -6,7 +6,7 @@ require 'tempfile'
6
6
  module CopHelper
7
7
  extend RSpec::SharedContext
8
8
 
9
- let(:ruby_version) { 2.6 }
9
+ let(:ruby_version) { RuboCop::TargetRuby::DEFAULT_VERSION }
10
10
  let(:rails_version) { false }
11
11
 
12
12
  def inspect_source(source, file = nil)
@@ -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
@@ -5,7 +5,7 @@ module RuboCop
5
5
  # @api private
6
6
  class TargetRuby
7
7
  KNOWN_RUBIES = [2.0, 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3].freeze
8
- DEFAULT_VERSION = 2.6
8
+ DEFAULT_VERSION = 2.7
9
9
 
10
10
  OBSOLETE_RUBIES = {
11
11
  1.9 => '0.41',
@@ -14,7 +14,8 @@ module RuboCop
14
14
  2.2 => '0.68',
15
15
  2.3 => '0.81',
16
16
  2.4 => '1.12',
17
- 2.5 => '1.28'
17
+ 2.5 => '1.28',
18
+ 2.6 => '1.50'
18
19
  }.freeze
19
20
  private_constant :KNOWN_RUBIES, :OBSOLETE_RUBIES
20
21
 
@@ -3,15 +3,19 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.50.2'
6
+ STRING = '1.53.0'
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)
@@ -43,7 +47,7 @@ module RuboCop
43
47
  env.config_store.unvalidated.for_pwd.loaded_features.sort
44
48
  end
45
49
 
46
- features.map do |loaded_feature|
50
+ features.filter_map do |loaded_feature|
47
51
  next unless (match = loaded_feature.match(/rubocop-(?<feature>.*)/))
48
52
 
49
53
  # Get the expected name of the folder containing the extension code.
@@ -61,7 +65,7 @@ module RuboCop
61
65
  next unless (feature_version = feature_version(feature))
62
66
 
63
67
  " - #{loaded_feature} #{feature_version}"
64
- end.compact
68
+ end
65
69
  end
66
70
 
67
71
  # Returns feature version in one of two ways:
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'
@@ -507,6 +511,7 @@ require_relative 'rubocop/cop/style/end_block'
507
511
  require_relative 'rubocop/cop/style/env_home'
508
512
  require_relative 'rubocop/cop/style/eval_with_location'
509
513
  require_relative 'rubocop/cop/style/even_odd'
514
+ require_relative 'rubocop/cop/style/exact_regexp_match'
510
515
  require_relative 'rubocop/cop/style/expand_path_arguments'
511
516
  require_relative 'rubocop/cop/style/explicit_block_argument'
512
517
  require_relative 'rubocop/cop/style/exponential_notation'
@@ -557,15 +562,20 @@ require_relative 'rubocop/cop/style/multiline_in_pattern_then'
557
562
  require_relative 'rubocop/cop/style/numbered_parameters'
558
563
  require_relative 'rubocop/cop/style/open_struct_use'
559
564
  require_relative 'rubocop/cop/style/operator_method_call'
565
+ require_relative 'rubocop/cop/style/redundant_array_constructor'
560
566
  require_relative 'rubocop/cop/style/redundant_assignment'
561
567
  require_relative 'rubocop/cop/style/redundant_constant_base'
568
+ require_relative 'rubocop/cop/style/redundant_current_directory_in_path'
562
569
  require_relative 'rubocop/cop/style/redundant_double_splat_hash_braces'
563
570
  require_relative 'rubocop/cop/style/redundant_each'
564
571
  require_relative 'rubocop/cop/style/redundant_fetch_block'
565
572
  require_relative 'rubocop/cop/style/redundant_file_extension_in_require'
573
+ require_relative 'rubocop/cop/style/redundant_filter_chain'
566
574
  require_relative 'rubocop/cop/style/redundant_heredoc_delimiter_quotes'
567
575
  require_relative 'rubocop/cop/style/redundant_initialize'
568
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'
569
579
  require_relative 'rubocop/cop/style/redundant_self_assignment'
570
580
  require_relative 'rubocop/cop/style/redundant_self_assignment_branch'
571
581
  require_relative 'rubocop/cop/style/require_order'
@@ -643,6 +653,7 @@ require_relative 'rubocop/cop/style/regexp_literal'
643
653
  require_relative 'rubocop/cop/style/rescue_modifier'
644
654
  require_relative 'rubocop/cop/style/rescue_standard_error'
645
655
  require_relative 'rubocop/cop/style/return_nil'
656
+ require_relative 'rubocop/cop/style/return_nil_in_predicate_method_definition'
646
657
  require_relative 'rubocop/cop/style/safe_navigation'
647
658
  require_relative 'rubocop/cop/style/sample'
648
659
  require_relative 'rubocop/cop/style/select_by_regexp'
@@ -689,6 +700,7 @@ require_relative 'rubocop/cop/style/when_then'
689
700
  require_relative 'rubocop/cop/style/while_until_do'
690
701
  require_relative 'rubocop/cop/style/while_until_modifier'
691
702
  require_relative 'rubocop/cop/style/word_array'
703
+ require_relative 'rubocop/cop/style/yaml_file_read'
692
704
  require_relative 'rubocop/cop/style/yoda_condition'
693
705
  require_relative 'rubocop/cop/style/yoda_expression'
694
706
  require_relative 'rubocop/cop/style/zero_length_predicate'
@@ -734,6 +746,7 @@ require_relative 'rubocop/cli/command/base'
734
746
  require_relative 'rubocop/cli/command/auto_generate_config'
735
747
  require_relative 'rubocop/cli/command/execute_runner'
736
748
  require_relative 'rubocop/cli/command/init_dotfile'
749
+ require_relative 'rubocop/cli/command/lsp'
737
750
  require_relative 'rubocop/cli/command/show_cops'
738
751
  require_relative 'rubocop/cli/command/show_docs_url'
739
752
  require_relative 'rubocop/cli/command/suggest_extensions'