ruby-lsp 0.15.0 → 0.16.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/VERSION +1 -1
- data/exe/ruby-lsp-doctor +9 -0
- data/lib/ruby_indexer/lib/ruby_indexer/collector.rb +14 -1
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +4 -0
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +46 -0
- data/lib/ruby_lsp/addon.rb +9 -13
- data/lib/ruby_lsp/global_state.rb +11 -0
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/requests/code_lens.rb +1 -1
- data/lib/ruby_lsp/requests/completion.rb +1 -1
- data/lib/ruby_lsp/requests/definition.rb +1 -1
- data/lib/ruby_lsp/requests/diagnostics.rb +6 -12
- data/lib/ruby_lsp/requests/formatting.rb +7 -43
- data/lib/ruby_lsp/requests/hover.rb +1 -1
- data/lib/ruby_lsp/requests/request.rb +2 -0
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +1 -1
- data/lib/ruby_lsp/requests/support/formatter.rb +26 -0
- data/lib/ruby_lsp/requests/support/rubocop_formatter.rb +50 -0
- data/lib/ruby_lsp/requests/support/{syntax_tree_formatting_runner.rb → syntax_tree_formatter.rb} +13 -3
- data/lib/ruby_lsp/requests.rb +1 -1
- data/lib/ruby_lsp/server.rb +34 -20
- data/lib/ruby_lsp/test_helper.rb +8 -1
- metadata +5 -6
- data/lib/ruby_lsp/requests/support/formatter_runner.rb +0 -18
- data/lib/ruby_lsp/requests/support/rubocop_diagnostics_runner.rb +0 -34
- data/lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: faf267ef6ce1eb7c9471d0a63b07c8da3d60ae1aeb656b63eedb64c493746e18
|
4
|
+
data.tar.gz: 56cd98100e674d8e3de391cb107efb7c4b713715494f212f879e687d2c26cda4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 75077a56844015e9915c1232102eca5e5bcc40687207579367b9ce836525a369e4d87e2a3e89223ca4af3bad1b8fdf09648d2839a756d171fefdc2c7d38c9df4
|
7
|
+
data.tar.gz: '025321865d6799a4ca874296d2552d8ec71f7ffa3023a104f74633ae9b858ab757dd5babee429aa38b04c1820ce64c4f7416aa626267189ac43d262744698369'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.16.0
|
data/exe/ruby-lsp-doctor
CHANGED
@@ -4,6 +4,15 @@
|
|
4
4
|
$LOAD_PATH.unshift(File.expand_path("../lib", __dir__))
|
5
5
|
require "ruby_lsp/internal"
|
6
6
|
|
7
|
+
if File.exist?(".index.yml")
|
8
|
+
begin
|
9
|
+
config = YAML.parse_file(".index.yml").to_ruby
|
10
|
+
rescue => e
|
11
|
+
abort("Error parsing config: #{e.message}")
|
12
|
+
end
|
13
|
+
RubyIndexer.configuration.apply_config(config)
|
14
|
+
end
|
15
|
+
|
7
16
|
index = RubyIndexer::Index.new
|
8
17
|
|
9
18
|
puts "Globbing for indexable files"
|
@@ -154,6 +154,8 @@ module RubyIndexer
|
|
154
154
|
handle_attribute(node, reader: true, writer: true)
|
155
155
|
when :include
|
156
156
|
handle_include(node)
|
157
|
+
when :prepend
|
158
|
+
handle_prepend(node)
|
157
159
|
end
|
158
160
|
end
|
159
161
|
|
@@ -355,6 +357,16 @@ module RubyIndexer
|
|
355
357
|
|
356
358
|
sig { params(node: Prism::CallNode).void }
|
357
359
|
def handle_include(node)
|
360
|
+
handle_module_operation(node, :included_modules)
|
361
|
+
end
|
362
|
+
|
363
|
+
sig { params(node: Prism::CallNode).void }
|
364
|
+
def handle_prepend(node)
|
365
|
+
handle_module_operation(node, :prepended_modules)
|
366
|
+
end
|
367
|
+
|
368
|
+
sig { params(node: Prism::CallNode, operation: Symbol).void }
|
369
|
+
def handle_module_operation(node, operation)
|
358
370
|
return unless @current_owner
|
359
371
|
|
360
372
|
arguments = node.arguments&.arguments
|
@@ -369,7 +381,8 @@ module RubyIndexer
|
|
369
381
|
# If a constant path reference is dynamic or missing parts, we can't
|
370
382
|
# index it
|
371
383
|
end
|
372
|
-
@current_owner.included_modules.
|
384
|
+
collection = operation == :included_modules ? @current_owner.included_modules : @current_owner.prepended_modules
|
385
|
+
collection.concat(names)
|
373
386
|
end
|
374
387
|
end
|
375
388
|
end
|
@@ -43,6 +43,9 @@ module RubyIndexer
|
|
43
43
|
sig { returns(T::Array[String]) }
|
44
44
|
attr_accessor :included_modules
|
45
45
|
|
46
|
+
sig { returns(T::Array[String]) }
|
47
|
+
attr_accessor :prepended_modules
|
48
|
+
|
46
49
|
sig do
|
47
50
|
params(
|
48
51
|
name: String,
|
@@ -54,6 +57,7 @@ module RubyIndexer
|
|
54
57
|
def initialize(name, file_path, location, comments)
|
55
58
|
super(name, file_path, location, comments)
|
56
59
|
@included_modules = T.let([], T::Array[String])
|
60
|
+
@prepended_modules = T.let([], T::Array[String])
|
57
61
|
end
|
58
62
|
|
59
63
|
sig { returns(String) }
|
@@ -327,5 +327,51 @@ module RubyIndexer
|
|
327
327
|
constant_path_references = T.must(@index["ConstantPathReferences"][0])
|
328
328
|
assert_equal(["Foo::Bar", "Foo::Bar2"], constant_path_references.included_modules)
|
329
329
|
end
|
330
|
+
|
331
|
+
def test_keeping_track_of_prepended_modules
|
332
|
+
index(<<~RUBY)
|
333
|
+
class Foo
|
334
|
+
# valid syntaxes that we can index
|
335
|
+
prepend A1
|
336
|
+
self.prepend A2
|
337
|
+
prepend A3, A4
|
338
|
+
self.prepend A5, A6
|
339
|
+
|
340
|
+
# valid syntaxes that we cannot index because of their dynamic nature
|
341
|
+
prepend some_variable_or_method_call
|
342
|
+
self.prepend some_variable_or_method_call
|
343
|
+
|
344
|
+
def something
|
345
|
+
prepend A7 # We should not index this because of this dynamic nature
|
346
|
+
end
|
347
|
+
|
348
|
+
# Valid inner class syntax definition with its own modules prepended
|
349
|
+
class Qux
|
350
|
+
prepend Corge
|
351
|
+
self.prepend Corge
|
352
|
+
prepend Baz
|
353
|
+
|
354
|
+
prepend some_variable_or_method_call
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
class ConstantPathReferences
|
359
|
+
prepend Foo::Bar
|
360
|
+
self.prepend Foo::Bar2
|
361
|
+
|
362
|
+
prepend dynamic::Bar
|
363
|
+
prepend Foo::
|
364
|
+
end
|
365
|
+
RUBY
|
366
|
+
|
367
|
+
foo = T.must(@index["Foo"][0])
|
368
|
+
assert_equal(["A1", "A2", "A3", "A4", "A5", "A6"], foo.prepended_modules)
|
369
|
+
|
370
|
+
qux = T.must(@index["Foo::Qux"][0])
|
371
|
+
assert_equal(["Corge", "Corge", "Baz"], qux.prepended_modules)
|
372
|
+
|
373
|
+
constant_path_references = T.must(@index["ConstantPathReferences"][0])
|
374
|
+
assert_equal(["Foo::Bar", "Foo::Bar2"], constant_path_references.prepended_modules)
|
375
|
+
end
|
330
376
|
end
|
331
377
|
end
|
data/lib/ruby_lsp/addon.rb
CHANGED
@@ -50,8 +50,8 @@ module RubyLsp
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# Discovers and loads all addons. Returns the list of activated addons
|
53
|
-
sig { params(
|
54
|
-
def load_addons(
|
53
|
+
sig { params(global_state: GlobalState, outgoing_queue: Thread::Queue).returns(T::Array[Addon]) }
|
54
|
+
def load_addons(global_state, outgoing_queue)
|
55
55
|
# Require all addons entry points, which should be placed under
|
56
56
|
# `some_gem/lib/ruby_lsp/your_gem_name/addon.rb`
|
57
57
|
Gem.find_files("ruby_lsp/**/addon.rb").each do |addon|
|
@@ -67,7 +67,7 @@ module RubyLsp
|
|
67
67
|
# Activate each one of the discovered addons. If any problems occur in the addons, we don't want to
|
68
68
|
# fail to boot the server
|
69
69
|
addons.each do |addon|
|
70
|
-
addon.activate(
|
70
|
+
addon.activate(global_state, outgoing_queue)
|
71
71
|
rescue => e
|
72
72
|
addon.add_error(e)
|
73
73
|
end
|
@@ -105,8 +105,8 @@ module RubyLsp
|
|
105
105
|
|
106
106
|
# Each addon should implement `MyAddon#activate` and use to perform any sort of initialization, such as
|
107
107
|
# reading information into memory or even spawning a separate process
|
108
|
-
sig { abstract.params(
|
109
|
-
def activate(
|
108
|
+
sig { abstract.params(global_state: GlobalState, outgoing_queue: Thread::Queue).void }
|
109
|
+
def activate(global_state, outgoing_queue); end
|
110
110
|
|
111
111
|
# Each addon should implement `MyAddon#deactivate` and use to perform any clean up, like shutting down a
|
112
112
|
# child process
|
@@ -121,23 +121,21 @@ module RubyLsp
|
|
121
121
|
sig do
|
122
122
|
overridable.params(
|
123
123
|
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CodeLens],
|
124
|
-
global_state: GlobalState,
|
125
124
|
uri: URI::Generic,
|
126
125
|
dispatcher: Prism::Dispatcher,
|
127
126
|
).void
|
128
127
|
end
|
129
|
-
def create_code_lens_listener(response_builder,
|
128
|
+
def create_code_lens_listener(response_builder, uri, dispatcher); end
|
130
129
|
|
131
130
|
# Creates a new Hover listener. This method is invoked on every Hover request
|
132
131
|
sig do
|
133
132
|
overridable.params(
|
134
133
|
response_builder: ResponseBuilders::Hover,
|
135
|
-
global_state: GlobalState,
|
136
134
|
nesting: T::Array[String],
|
137
135
|
dispatcher: Prism::Dispatcher,
|
138
136
|
).void
|
139
137
|
end
|
140
|
-
def create_hover_listener(response_builder,
|
138
|
+
def create_hover_listener(response_builder, nesting, dispatcher); end
|
141
139
|
|
142
140
|
# Creates a new DocumentSymbol listener. This method is invoked on every DocumentSymbol request
|
143
141
|
sig do
|
@@ -160,24 +158,22 @@ module RubyLsp
|
|
160
158
|
sig do
|
161
159
|
overridable.params(
|
162
160
|
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::Location],
|
163
|
-
global_state: GlobalState,
|
164
161
|
uri: URI::Generic,
|
165
162
|
nesting: T::Array[String],
|
166
163
|
dispatcher: Prism::Dispatcher,
|
167
164
|
).void
|
168
165
|
end
|
169
|
-
def create_definition_listener(response_builder,
|
166
|
+
def create_definition_listener(response_builder, uri, nesting, dispatcher); end
|
170
167
|
|
171
168
|
# Creates a new Completion listener. This method is invoked on every Completion request
|
172
169
|
sig do
|
173
170
|
overridable.params(
|
174
171
|
response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::CompletionItem],
|
175
|
-
global_state: GlobalState,
|
176
172
|
nesting: T::Array[String],
|
177
173
|
dispatcher: Prism::Dispatcher,
|
178
174
|
uri: URI::Generic,
|
179
175
|
).void
|
180
176
|
end
|
181
|
-
def create_completion_listener(response_builder,
|
177
|
+
def create_completion_listener(response_builder, nesting, dispatcher, uri); end
|
182
178
|
end
|
183
179
|
end
|
@@ -25,6 +25,17 @@ module RubyLsp
|
|
25
25
|
@test_library = T.let(detect_test_library, String)
|
26
26
|
@typechecker = T.let(detect_typechecker, T::Boolean)
|
27
27
|
@index = T.let(RubyIndexer::Index.new, RubyIndexer::Index)
|
28
|
+
@supported_formatters = T.let({}, T::Hash[String, Requests::Support::Formatter])
|
29
|
+
end
|
30
|
+
|
31
|
+
sig { params(identifier: String, instance: Requests::Support::Formatter).void }
|
32
|
+
def register_formatter(identifier, instance)
|
33
|
+
@supported_formatters[identifier] = instance
|
34
|
+
end
|
35
|
+
|
36
|
+
sig { returns(T.nilable(Requests::Support::Formatter)) }
|
37
|
+
def active_formatter
|
38
|
+
@supported_formatters[@formatter]
|
28
39
|
end
|
29
40
|
|
30
41
|
sig { params(options: T::Hash[Symbol, T.untyped]).void }
|
data/lib/ruby_lsp/internal.rb
CHANGED
@@ -48,7 +48,7 @@ module RubyLsp
|
|
48
48
|
Listeners::CodeLens.new(@response_builder, global_state, uri, dispatcher)
|
49
49
|
|
50
50
|
Addon.addons.each do |addon|
|
51
|
-
addon.create_code_lens_listener(@response_builder,
|
51
|
+
addon.create_code_lens_listener(@response_builder, uri, dispatcher)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
@@ -78,7 +78,7 @@ module RubyLsp
|
|
78
78
|
)
|
79
79
|
|
80
80
|
Addon.addons.each do |addon|
|
81
|
-
addon.create_completion_listener(@response_builder,
|
81
|
+
addon.create_completion_listener(@response_builder, nesting, dispatcher, document.uri)
|
82
82
|
end
|
83
83
|
|
84
84
|
return unless matched && parent
|
@@ -67,7 +67,7 @@ module RubyLsp
|
|
67
67
|
)
|
68
68
|
|
69
69
|
Addon.addons.each do |addon|
|
70
|
-
addon.create_definition_listener(@response_builder,
|
70
|
+
addon.create_definition_listener(@response_builder, document.uri, nesting, dispatcher)
|
71
71
|
end
|
72
72
|
|
73
73
|
@target = T.let(target, T.nilable(Prism::Node))
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "ruby_lsp/requests/support/rubocop_diagnostics_runner"
|
5
|
-
|
6
4
|
module RubyLsp
|
7
5
|
module Requests
|
8
6
|
# 
|
@@ -33,9 +31,10 @@ module RubyLsp
|
|
33
31
|
end
|
34
32
|
end
|
35
33
|
|
36
|
-
sig { params(document: Document).void }
|
37
|
-
def initialize(document)
|
34
|
+
sig { params(global_state: GlobalState, document: Document).void }
|
35
|
+
def initialize(global_state, document)
|
38
36
|
super()
|
37
|
+
@active_formatter = T.let(global_state.active_formatter, T.nilable(Support::Formatter))
|
39
38
|
@document = document
|
40
39
|
@uri = T.let(document.uri, URI::Generic)
|
41
40
|
end
|
@@ -46,15 +45,10 @@ module RubyLsp
|
|
46
45
|
diagnostics.concat(syntax_error_diagnostics, syntax_warning_diagnostics)
|
47
46
|
|
48
47
|
# Running RuboCop is slow, so to avoid excessive runs we only do so if the file is syntactically valid
|
49
|
-
return diagnostics if @document.syntax_error?
|
50
|
-
|
51
|
-
diagnostics.concat(
|
52
|
-
Support::RuboCopDiagnosticsRunner.instance.run(
|
53
|
-
@uri,
|
54
|
-
@document,
|
55
|
-
).map!(&:to_lsp_diagnostic),
|
56
|
-
) if defined?(Support::RuboCopDiagnosticsRunner)
|
48
|
+
return diagnostics if @document.syntax_error? || !@active_formatter
|
57
49
|
|
50
|
+
formatter_diagnostics = @active_formatter.run_diagnostic(@uri, @document)
|
51
|
+
diagnostics.concat(formatter_diagnostics) if formatter_diagnostics
|
58
52
|
diagnostics
|
59
53
|
end
|
60
54
|
|
@@ -1,9 +1,6 @@
|
|
1
1
|
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "ruby_lsp/requests/support/rubocop_formatting_runner"
|
5
|
-
require "ruby_lsp/requests/support/syntax_tree_formatting_runner"
|
6
|
-
|
7
4
|
module RubyLsp
|
8
5
|
module Requests
|
9
6
|
# 
|
@@ -26,47 +23,24 @@ module RubyLsp
|
|
26
23
|
# end
|
27
24
|
# ```
|
28
25
|
class Formatting < Request
|
29
|
-
class Error < StandardError; end
|
30
|
-
class InvalidFormatter < StandardError; end
|
31
|
-
|
32
|
-
@formatters = T.let({}, T::Hash[String, Support::FormatterRunner])
|
33
|
-
|
34
|
-
class << self
|
35
|
-
extend T::Sig
|
36
|
-
|
37
|
-
sig { returns(T::Hash[String, Support::FormatterRunner]) }
|
38
|
-
attr_reader :formatters
|
39
|
-
|
40
|
-
sig { params(identifier: String, instance: Support::FormatterRunner).void }
|
41
|
-
def register_formatter(identifier, instance)
|
42
|
-
@formatters[identifier] = instance
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
if defined?(Support::RuboCopFormattingRunner)
|
47
|
-
register_formatter("rubocop", Support::RuboCopFormattingRunner.instance)
|
48
|
-
end
|
49
|
-
|
50
|
-
if defined?(Support::SyntaxTreeFormattingRunner)
|
51
|
-
register_formatter("syntax_tree", Support::SyntaxTreeFormattingRunner.instance)
|
52
|
-
end
|
53
|
-
|
54
26
|
extend T::Sig
|
55
27
|
|
56
|
-
|
57
|
-
|
28
|
+
class Error < StandardError; end
|
29
|
+
|
30
|
+
sig { params(global_state: GlobalState, document: Document).void }
|
31
|
+
def initialize(global_state, document)
|
58
32
|
super()
|
59
33
|
@document = document
|
34
|
+
@active_formatter = T.let(global_state.active_formatter, T.nilable(Support::Formatter))
|
60
35
|
@uri = T.let(document.uri, URI::Generic)
|
61
|
-
@formatter = formatter
|
62
36
|
end
|
63
37
|
|
64
38
|
sig { override.returns(T.nilable(T.all(T::Array[Interface::TextEdit], Object))) }
|
65
39
|
def perform
|
66
|
-
return
|
40
|
+
return unless @active_formatter
|
67
41
|
return if @document.syntax_error?
|
68
42
|
|
69
|
-
formatted_text =
|
43
|
+
formatted_text = @active_formatter.run_formatting(@uri, @document)
|
70
44
|
return unless formatted_text
|
71
45
|
|
72
46
|
size = @document.source.size
|
@@ -82,16 +56,6 @@ module RubyLsp
|
|
82
56
|
),
|
83
57
|
]
|
84
58
|
end
|
85
|
-
|
86
|
-
private
|
87
|
-
|
88
|
-
sig { returns(T.nilable(String)) }
|
89
|
-
def formatted_file
|
90
|
-
formatter_runner = Formatting.formatters[@formatter]
|
91
|
-
raise InvalidFormatter, "Formatter is not available: #{@formatter}" unless formatter_runner
|
92
|
-
|
93
|
-
formatter_runner.run(@uri, @document)
|
94
|
-
end
|
95
59
|
end
|
96
60
|
end
|
97
61
|
end
|
@@ -64,7 +64,7 @@ module RubyLsp
|
|
64
64
|
@response_builder = T.let(ResponseBuilders::Hover.new, ResponseBuilders::Hover)
|
65
65
|
Listeners::Hover.new(@response_builder, global_state, uri, nesting, dispatcher, typechecker_enabled)
|
66
66
|
Addon.addons.each do |addon|
|
67
|
-
addon.create_hover_listener(@response_builder,
|
67
|
+
addon.create_hover_listener(@response_builder, nesting, dispatcher)
|
68
68
|
end
|
69
69
|
|
70
70
|
@dispatcher = dispatcher
|
@@ -29,7 +29,7 @@ module RubyLsp
|
|
29
29
|
sig { returns(Interface::SemanticTokensRegistrationOptions) }
|
30
30
|
def provider
|
31
31
|
Interface::SemanticTokensRegistrationOptions.new(
|
32
|
-
document_selector: {
|
32
|
+
document_selector: [{ language: "ruby" }],
|
33
33
|
legend: Interface::SemanticTokensLegend.new(
|
34
34
|
token_types: ResponseBuilders::SemanticHighlighting::TOKEN_TYPES.keys,
|
35
35
|
token_modifiers: ResponseBuilders::SemanticHighlighting::TOKEN_MODIFIERS.keys,
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module Requests
|
6
|
+
module Support
|
7
|
+
module Formatter
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
|
11
|
+
interface!
|
12
|
+
|
13
|
+
sig { abstract.params(uri: URI::Generic, document: Document).returns(T.nilable(String)) }
|
14
|
+
def run_formatting(uri, document); end
|
15
|
+
|
16
|
+
sig do
|
17
|
+
abstract.params(
|
18
|
+
uri: URI::Generic,
|
19
|
+
document: Document,
|
20
|
+
).returns(T.nilable(T::Array[Interface::Diagnostic]))
|
21
|
+
end
|
22
|
+
def run_diagnostic(uri, document); end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
return unless defined?(RubyLsp::Requests::Support::RuboCopRunner)
|
5
|
+
|
6
|
+
require "singleton"
|
7
|
+
|
8
|
+
module RubyLsp
|
9
|
+
module Requests
|
10
|
+
module Support
|
11
|
+
class RuboCopFormatter
|
12
|
+
extend T::Sig
|
13
|
+
include Formatter
|
14
|
+
include Singleton
|
15
|
+
|
16
|
+
sig { void }
|
17
|
+
def initialize
|
18
|
+
@diagnostic_runner = T.let(RuboCopRunner.new, RuboCopRunner)
|
19
|
+
# -a is for "--auto-correct" (or "--autocorrect" on newer versions of RuboCop)
|
20
|
+
@format_runner = T.let(RuboCopRunner.new("-a"), RuboCopRunner)
|
21
|
+
end
|
22
|
+
|
23
|
+
sig { override.params(uri: URI::Generic, document: Document).returns(T.nilable(String)) }
|
24
|
+
def run_formatting(uri, document)
|
25
|
+
filename = T.must(uri.to_standardized_path || uri.opaque)
|
26
|
+
|
27
|
+
# Invoke RuboCop with just this file in `paths`
|
28
|
+
@format_runner.run(filename, document.source)
|
29
|
+
@format_runner.formatted_source
|
30
|
+
end
|
31
|
+
|
32
|
+
sig do
|
33
|
+
override.params(
|
34
|
+
uri: URI::Generic,
|
35
|
+
document: Document,
|
36
|
+
).returns(T.nilable(T::Array[Interface::Diagnostic]))
|
37
|
+
end
|
38
|
+
def run_diagnostic(uri, document)
|
39
|
+
filename = T.must(uri.to_standardized_path || uri.opaque)
|
40
|
+
# Invoke RuboCop with just this file in `paths`
|
41
|
+
@diagnostic_runner.run(filename, document.source)
|
42
|
+
|
43
|
+
@diagnostic_runner.offenses.map do |offense|
|
44
|
+
Support::RuboCopDiagnostic.new(document, offense, uri).to_lsp_diagnostic
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/lib/ruby_lsp/requests/support/{syntax_tree_formatting_runner.rb → syntax_tree_formatter.rb}
RENAMED
@@ -14,10 +14,10 @@ module RubyLsp
|
|
14
14
|
module Requests
|
15
15
|
module Support
|
16
16
|
# :nodoc:
|
17
|
-
class
|
17
|
+
class SyntaxTreeFormatter
|
18
18
|
extend T::Sig
|
19
19
|
include Singleton
|
20
|
-
include Support::
|
20
|
+
include Support::Formatter
|
21
21
|
|
22
22
|
sig { void }
|
23
23
|
def initialize
|
@@ -33,12 +33,22 @@ module RubyLsp
|
|
33
33
|
end
|
34
34
|
|
35
35
|
sig { override.params(uri: URI::Generic, document: Document).returns(T.nilable(String)) }
|
36
|
-
def
|
36
|
+
def run_formatting(uri, document)
|
37
37
|
path = uri.to_standardized_path
|
38
38
|
return if path && @options.ignore_files.any? { |pattern| File.fnmatch?("*/#{pattern}", path) }
|
39
39
|
|
40
40
|
SyntaxTree.format(document.source, @options.print_width, options: @options.formatter_options)
|
41
41
|
end
|
42
|
+
|
43
|
+
sig do
|
44
|
+
override.params(
|
45
|
+
uri: URI::Generic,
|
46
|
+
document: Document,
|
47
|
+
).returns(T.nilable(T::Array[Interface::Diagnostic]))
|
48
|
+
end
|
49
|
+
def run_diagnostic(uri, document)
|
50
|
+
nil
|
51
|
+
end
|
42
52
|
end
|
43
53
|
end
|
44
54
|
end
|
data/lib/ruby_lsp/requests.rb
CHANGED
@@ -56,7 +56,7 @@ module RubyLsp
|
|
56
56
|
autoload :Sorbet, "ruby_lsp/requests/support/sorbet"
|
57
57
|
autoload :RailsDocumentClient, "ruby_lsp/requests/support/rails_document_client"
|
58
58
|
autoload :Common, "ruby_lsp/requests/support/common"
|
59
|
-
autoload :
|
59
|
+
autoload :Formatter, "ruby_lsp/requests/support/formatter"
|
60
60
|
end
|
61
61
|
end
|
62
62
|
end
|
data/lib/ruby_lsp/server.rb
CHANGED
@@ -88,6 +88,26 @@ module RubyLsp
|
|
88
88
|
$stderr.puts("Error processing #{message[:method]}: #{e.full_message}")
|
89
89
|
end
|
90
90
|
|
91
|
+
sig { void }
|
92
|
+
def load_addons
|
93
|
+
Addon.load_addons(@global_state, @outgoing_queue)
|
94
|
+
errored_addons = Addon.addons.select(&:error?)
|
95
|
+
|
96
|
+
if errored_addons.any?
|
97
|
+
send_message(
|
98
|
+
Notification.new(
|
99
|
+
method: "window/showMessage",
|
100
|
+
params: Interface::ShowMessageParams.new(
|
101
|
+
type: Constant::MessageType::WARNING,
|
102
|
+
message: "Error loading addons:\n\n#{errored_addons.map(&:formatted_errors).join("\n\n")}",
|
103
|
+
),
|
104
|
+
),
|
105
|
+
)
|
106
|
+
|
107
|
+
$stderr.puts(errored_addons.map(&:backtraces).join("\n\n"))
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
91
111
|
private
|
92
112
|
|
93
113
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
@@ -213,23 +233,7 @@ module RubyLsp
|
|
213
233
|
|
214
234
|
sig { void }
|
215
235
|
def run_initialized
|
216
|
-
|
217
|
-
errored_addons = Addon.addons.select(&:error?)
|
218
|
-
|
219
|
-
if errored_addons.any?
|
220
|
-
send_message(
|
221
|
-
Notification.new(
|
222
|
-
method: "window/showMessage",
|
223
|
-
params: Interface::ShowMessageParams.new(
|
224
|
-
type: Constant::MessageType::WARNING,
|
225
|
-
message: "Error loading addons:\n\n#{errored_addons.map(&:formatted_errors).join("\n\n")}",
|
226
|
-
),
|
227
|
-
),
|
228
|
-
)
|
229
|
-
|
230
|
-
$stderr.puts(errored_addons.map(&:backtraces).join("\n\n"))
|
231
|
-
end
|
232
|
-
|
236
|
+
load_addons
|
233
237
|
RubyVM::YJIT.enable if defined?(RubyVM::YJIT.enable)
|
234
238
|
|
235
239
|
indexing_config = {}
|
@@ -254,6 +258,13 @@ module RubyLsp
|
|
254
258
|
end
|
255
259
|
end
|
256
260
|
|
261
|
+
if defined?(Requests::Support::RuboCopFormatter)
|
262
|
+
@global_state.register_formatter("rubocop", Requests::Support::RuboCopFormatter.instance)
|
263
|
+
end
|
264
|
+
if defined?(Requests::Support::SyntaxTreeFormatter)
|
265
|
+
@global_state.register_formatter("syntax_tree", Requests::Support::SyntaxTreeFormatter.instance)
|
266
|
+
end
|
267
|
+
|
257
268
|
perform_initial_indexing(indexing_config)
|
258
269
|
check_formatter_is_available
|
259
270
|
end
|
@@ -387,9 +398,9 @@ module RubyLsp
|
|
387
398
|
return
|
388
399
|
end
|
389
400
|
|
390
|
-
response = Requests::Formatting.new(@store.get(uri)
|
401
|
+
response = Requests::Formatting.new(@global_state, @store.get(uri)).perform
|
391
402
|
send_message(Result.new(id: message[:id], response: response))
|
392
|
-
rescue Requests::
|
403
|
+
rescue Requests::Request::InvalidFormatter => error
|
393
404
|
send_message(Notification.window_show_error("Configuration error: #{error.message}"))
|
394
405
|
send_empty_response(message[:id])
|
395
406
|
rescue StandardError, LoadError => error
|
@@ -512,7 +523,7 @@ module RubyLsp
|
|
512
523
|
end
|
513
524
|
|
514
525
|
response = @store.cache_fetch(uri, "textDocument/diagnostic") do |document|
|
515
|
-
Requests::Diagnostics.new(document).perform
|
526
|
+
Requests::Diagnostics.new(@global_state, document).perform
|
516
527
|
end
|
517
528
|
|
518
529
|
send_message(
|
@@ -521,6 +532,9 @@ module RubyLsp
|
|
521
532
|
response: response && Interface::FullDocumentDiagnosticReport.new(kind: "full", items: response),
|
522
533
|
),
|
523
534
|
)
|
535
|
+
rescue Requests::Request::InvalidFormatter => error
|
536
|
+
send_message(Notification.window_show_error("Configuration error: #{error.message}"))
|
537
|
+
send_empty_response(message[:id])
|
524
538
|
rescue StandardError, LoadError => error
|
525
539
|
send_message(Notification.window_show_error("Error running diagnostics: #{error.message}"))
|
526
540
|
send_empty_response(message[:id])
|
data/lib/ruby_lsp/test_helper.rb
CHANGED
@@ -13,10 +13,12 @@ module RubyLsp
|
|
13
13
|
source: T.nilable(String),
|
14
14
|
uri: URI::Generic,
|
15
15
|
stub_no_typechecker: T::Boolean,
|
16
|
+
load_addons: T::Boolean,
|
16
17
|
block: T.proc.params(server: RubyLsp::Server, uri: URI::Generic).returns(T.type_parameter(:T)),
|
17
18
|
).returns(T.type_parameter(:T))
|
18
19
|
end
|
19
|
-
def with_server(source = nil, uri = Kernel.URI("file:///fake.rb"), stub_no_typechecker: false,
|
20
|
+
def with_server(source = nil, uri = Kernel.URI("file:///fake.rb"), stub_no_typechecker: false, load_addons: true,
|
21
|
+
&block)
|
20
22
|
server = RubyLsp::Server.new(test_mode: true)
|
21
23
|
server.global_state.stubs(:typechecker).returns(false) if stub_no_typechecker
|
22
24
|
|
@@ -37,8 +39,13 @@ module RubyLsp
|
|
37
39
|
RubyIndexer::IndexablePath.new(nil, T.must(uri.to_standardized_path)),
|
38
40
|
source,
|
39
41
|
)
|
42
|
+
server.load_addons if load_addons
|
40
43
|
block.call(server, uri)
|
41
44
|
ensure
|
45
|
+
if load_addons
|
46
|
+
RubyLsp::Addon.addons.each(&:deactivate)
|
47
|
+
RubyLsp::Addon.addons.clear
|
48
|
+
end
|
42
49
|
T.must(server).run_shutdown
|
43
50
|
end
|
44
51
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-lsp
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.16.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|
@@ -134,15 +134,14 @@ files:
|
|
134
134
|
- lib/ruby_lsp/requests/signature_help.rb
|
135
135
|
- lib/ruby_lsp/requests/support/annotation.rb
|
136
136
|
- lib/ruby_lsp/requests/support/common.rb
|
137
|
-
- lib/ruby_lsp/requests/support/
|
137
|
+
- lib/ruby_lsp/requests/support/formatter.rb
|
138
138
|
- lib/ruby_lsp/requests/support/rubocop_diagnostic.rb
|
139
|
-
- lib/ruby_lsp/requests/support/
|
140
|
-
- lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb
|
139
|
+
- lib/ruby_lsp/requests/support/rubocop_formatter.rb
|
141
140
|
- lib/ruby_lsp/requests/support/rubocop_runner.rb
|
142
141
|
- lib/ruby_lsp/requests/support/selection_range.rb
|
143
142
|
- lib/ruby_lsp/requests/support/sorbet.rb
|
144
143
|
- lib/ruby_lsp/requests/support/source_uri.rb
|
145
|
-
- lib/ruby_lsp/requests/support/
|
144
|
+
- lib/ruby_lsp/requests/support/syntax_tree_formatter.rb
|
146
145
|
- lib/ruby_lsp/requests/workspace_symbol.rb
|
147
146
|
- lib/ruby_lsp/response_builders.rb
|
148
147
|
- lib/ruby_lsp/response_builders/collection_response_builder.rb
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
module RubyLsp
|
5
|
-
module Requests
|
6
|
-
module Support
|
7
|
-
module FormatterRunner
|
8
|
-
extend T::Sig
|
9
|
-
extend T::Helpers
|
10
|
-
|
11
|
-
interface!
|
12
|
-
|
13
|
-
sig { abstract.params(uri: URI::Generic, document: Document).returns(T.nilable(String)) }
|
14
|
-
def run(uri, document); end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
return unless defined?(RubyLsp::Requests::Support::RuboCopRunner)
|
5
|
-
|
6
|
-
require "singleton"
|
7
|
-
|
8
|
-
module RubyLsp
|
9
|
-
module Requests
|
10
|
-
module Support
|
11
|
-
# :nodoc:
|
12
|
-
class RuboCopDiagnosticsRunner
|
13
|
-
extend T::Sig
|
14
|
-
include Singleton
|
15
|
-
|
16
|
-
sig { void }
|
17
|
-
def initialize
|
18
|
-
@runner = T.let(RuboCopRunner.new, RuboCopRunner)
|
19
|
-
end
|
20
|
-
|
21
|
-
sig { params(uri: URI::Generic, document: Document).returns(T::Array[Support::RuboCopDiagnostic]) }
|
22
|
-
def run(uri, document)
|
23
|
-
filename = T.must(uri.to_standardized_path || uri.opaque)
|
24
|
-
# Invoke RuboCop with just this file in `paths`
|
25
|
-
@runner.run(filename, document.source)
|
26
|
-
|
27
|
-
@runner.offenses.map do |offense|
|
28
|
-
Support::RuboCopDiagnostic.new(document, offense, uri)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,35 +0,0 @@
|
|
1
|
-
# typed: strict
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
return unless defined?(RubyLsp::Requests::Support::RuboCopRunner)
|
5
|
-
|
6
|
-
require "singleton"
|
7
|
-
|
8
|
-
module RubyLsp
|
9
|
-
module Requests
|
10
|
-
module Support
|
11
|
-
# :nodoc:
|
12
|
-
class RuboCopFormattingRunner
|
13
|
-
extend T::Sig
|
14
|
-
include Singleton
|
15
|
-
include Support::FormatterRunner
|
16
|
-
|
17
|
-
sig { void }
|
18
|
-
def initialize
|
19
|
-
# -a is for "--auto-correct" (or "--autocorrect" on newer versions of RuboCop)
|
20
|
-
@runner = T.let(RuboCopRunner.new("-a"), RuboCopRunner)
|
21
|
-
end
|
22
|
-
|
23
|
-
sig { override.params(uri: URI::Generic, document: Document).returns(String) }
|
24
|
-
def run(uri, document)
|
25
|
-
filename = T.must(uri.to_standardized_path || uri.opaque)
|
26
|
-
|
27
|
-
# Invoke RuboCop with just this file in `paths`
|
28
|
-
@runner.run(filename, document.source)
|
29
|
-
|
30
|
-
@runner.formatted_source
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|