ruby-lsp 0.15.0 → 0.16.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- 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 +14 -3
- 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: b52249bb9ff4600edc041d0ac28d961c7670f5dad2475b632fa5ea87c02e1657
|
4
|
+
data.tar.gz: c15ed4c4cd012c64f526ce3c31ca0f70a248467a44034dc6ffeed50cda94d9ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf9936e23669e947cc802e5efe4fc5466528dff0e290d3daf255522cdca7e41d08802737da2f93b0690ca3abf3916a726926b454964f21a67bb661e902494390
|
7
|
+
data.tar.gz: 6d6b39a1dfe90b54e4e20a1a4eda471a71418b85c94ee305c5e9b1a77be8251a304d0da9f4c72fae28773e14bdb1f316da12ce41ef436c2bc72d78903a647fb1
|
data/README.md
CHANGED
@@ -29,7 +29,7 @@ The Ruby LSP features include
|
|
29
29
|
- Debugging support
|
30
30
|
- Running and debugging tests through VS Code's UI
|
31
31
|
- Go to definition for classes, modules, constants and required files
|
32
|
-
- Showing
|
32
|
+
- Showing documentation on hover for classes, modules and constants
|
33
33
|
- Completion for classes, modules, constants and require paths
|
34
34
|
- Fuzzy search classes, modules and constants anywhere in the project and its dependencies (workspace symbol)
|
35
35
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.16.1
|
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 }
|
@@ -52,17 +63,17 @@ module RubyLsp
|
|
52
63
|
|
53
64
|
sig { returns(String) }
|
54
65
|
def detect_test_library
|
66
|
+
if direct_dependency?(/^rspec/)
|
67
|
+
"rspec"
|
55
68
|
# A Rails app may have a dependency on minitest, but we would instead want to use the Rails test runner provided
|
56
69
|
# by ruby-lsp-rails.
|
57
|
-
|
70
|
+
elsif direct_dependency?(/^rails$/)
|
58
71
|
"rails"
|
59
72
|
# NOTE: Intentionally ends with $ to avoid mis-matching minitest-reporters, etc. in a Rails app.
|
60
73
|
elsif direct_dependency?(/^minitest$/)
|
61
74
|
"minitest"
|
62
75
|
elsif direct_dependency?(/^test-unit/)
|
63
76
|
"test-unit"
|
64
|
-
elsif direct_dependency?(/^rspec/)
|
65
|
-
"rspec"
|
66
77
|
else
|
67
78
|
"unknown"
|
68
79
|
end
|
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
|
# ![Diagnostics demo](../../diagnostics.gif)
|
@@ -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
|
# ![Formatting symbol demo](../../formatting.gif)
|
@@ -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.1
|
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-04 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
|