ruby-lsp 0.23.23 → 0.24.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-launcher +7 -2
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +7 -1
- data/lib/ruby_indexer/lib/ruby_indexer/enhancement.rb +1 -4
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +6 -18
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +16 -5
- data/lib/ruby_indexer/lib/ruby_indexer/reference_finder.rb +12 -8
- data/lib/ruby_indexer/test/index_test.rb +24 -0
- data/lib/ruby_indexer/test/instance_variables_test.rb +24 -0
- data/lib/ruby_indexer/test/method_test.rb +17 -0
- data/lib/ruby_indexer/test/reference_finder_test.rb +79 -14
- data/lib/ruby_lsp/addon.rb +9 -9
- data/lib/ruby_lsp/base_server.rb +5 -7
- data/lib/ruby_lsp/document.rb +36 -25
- data/lib/ruby_lsp/erb_document.rb +8 -3
- data/lib/ruby_lsp/listeners/completion.rb +9 -1
- data/lib/ruby_lsp/listeners/spec_style.rb +7 -8
- data/lib/ruby_lsp/listeners/test_discovery.rb +18 -15
- data/lib/ruby_lsp/listeners/test_style.rb +7 -8
- data/lib/ruby_lsp/requests/code_action_resolve.rb +2 -2
- data/lib/ruby_lsp/requests/completion.rb +1 -1
- data/lib/ruby_lsp/requests/definition.rb +1 -1
- data/lib/ruby_lsp/requests/discover_tests.rb +2 -2
- data/lib/ruby_lsp/requests/document_highlight.rb +1 -1
- data/lib/ruby_lsp/requests/hover.rb +1 -1
- data/lib/ruby_lsp/requests/prepare_rename.rb +1 -1
- data/lib/ruby_lsp/requests/references.rb +6 -2
- data/lib/ruby_lsp/requests/rename.rb +8 -6
- data/lib/ruby_lsp/requests/request.rb +3 -6
- data/lib/ruby_lsp/requests/selection_ranges.rb +1 -1
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +1 -1
- data/lib/ruby_lsp/requests/signature_help.rb +1 -1
- data/lib/ruby_lsp/requests/support/common.rb +1 -3
- data/lib/ruby_lsp/requests/support/formatter.rb +8 -13
- data/lib/ruby_lsp/response_builders/response_builder.rb +3 -5
- data/lib/ruby_lsp/ruby_document.rb +9 -4
- data/lib/ruby_lsp/server.rb +9 -30
- data/lib/ruby_lsp/setup_bundler.rb +3 -3
- data/lib/ruby_lsp/test_helper.rb +1 -4
- data/lib/ruby_lsp/utils.rb +3 -6
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 575c7b2510306819184c495560cc9bf9dee6dd9151cbeabe0ba3a8085996f58d
|
4
|
+
data.tar.gz: 0f714d35b90754c5c37672fef82a75ab5e0a2358ba821c397a3191a28518c9d3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f909d33820859b7e6a6be0e75345b00397a0717fdc5f63cfddf84b7277e7420469439f2a8d48561b96ae20f91bcbfd9ee9444522ec11e9da4611ac6371aeb52a
|
7
|
+
data.tar.gz: 866291dfe01240d91b1e8adfc74cc16482a5ddf9c68fc763f6869145e78ca4ea35f47f0e3727b1c1d930cc140e60e3e23c979bf68fc97a26eb6b2cd45c9403b4
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.24.0
|
data/exe/ruby-lsp-launcher
CHANGED
@@ -83,8 +83,13 @@ begin
|
|
83
83
|
# This Marshal load can only happen after requiring Bundler because it will load a custom error class from Bundler
|
84
84
|
# itself. If we try to load before requiring, the class will not be defined and loading will fail
|
85
85
|
error_path = File.join(".ruby-lsp", "install_error")
|
86
|
-
install_error =
|
87
|
-
Marshal.load(File.read(error_path))
|
86
|
+
install_error = begin
|
87
|
+
Marshal.load(File.read(error_path)) if File.exist?(error_path)
|
88
|
+
rescue ArgumentError
|
89
|
+
# The class we tried to load is not defined. This might happen when the user upgrades Bundler and new error
|
90
|
+
# classes are introduced or removed
|
91
|
+
File.delete(error_path)
|
92
|
+
nil
|
88
93
|
end
|
89
94
|
|
90
95
|
Bundler.setup
|
@@ -9,7 +9,7 @@ module RubyIndexer
|
|
9
9
|
#: Array[String]
|
10
10
|
attr_reader :indexing_errors
|
11
11
|
|
12
|
-
#: (Index index, Prism::Dispatcher dispatcher, Prism::ParseResult parse_result, URI::Generic uri, ?collect_comments: bool) -> void
|
12
|
+
#: (Index index, Prism::Dispatcher dispatcher, Prism::ParseLexResult | Prism::ParseResult parse_result, URI::Generic uri, ?collect_comments: bool) -> void
|
13
13
|
def initialize(index, dispatcher, parse_result, uri, collect_comments: false)
|
14
14
|
@index = index
|
15
15
|
@uri = uri
|
@@ -260,6 +260,9 @@ module RubyIndexer
|
|
260
260
|
handle_attribute(node, reader: false, writer: true)
|
261
261
|
when :attr_accessor
|
262
262
|
handle_attribute(node, reader: true, writer: true)
|
263
|
+
when :attr
|
264
|
+
has_writer = node.arguments&.arguments&.last&.is_a?(Prism::TrueNode) || false
|
265
|
+
handle_attribute(node, reader: true, writer: has_writer)
|
263
266
|
when :alias_method
|
264
267
|
handle_alias_method(node)
|
265
268
|
when :include, :prepend, :extend
|
@@ -726,6 +729,9 @@ module RubyIndexer
|
|
726
729
|
comment = @comments_by_line[line]
|
727
730
|
break unless comment
|
728
731
|
|
732
|
+
# a trailing comment from a previous line is not a comment for this node
|
733
|
+
break if comment.trailing?
|
734
|
+
|
729
735
|
comment_content = comment.location.slice
|
730
736
|
|
731
737
|
# invalid encodings would raise an "invalid byte sequence" exception
|
@@ -98,11 +98,8 @@ module RubyIndexer
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
+
# @abstract
|
101
102
|
class ModuleOperation
|
102
|
-
extend T::Helpers
|
103
|
-
|
104
|
-
abstract!
|
105
|
-
|
106
103
|
#: String
|
107
104
|
attr_reader :module_name
|
108
105
|
|
@@ -115,11 +112,8 @@ module RubyIndexer
|
|
115
112
|
class Include < ModuleOperation; end
|
116
113
|
class Prepend < ModuleOperation; end
|
117
114
|
|
115
|
+
# @abstract
|
118
116
|
class Namespace < Entry
|
119
|
-
extend T::Helpers
|
120
|
-
|
121
|
-
abstract!
|
122
|
-
|
123
117
|
#: Array[String]
|
124
118
|
attr_reader :nesting
|
125
119
|
|
@@ -191,11 +185,8 @@ module RubyIndexer
|
|
191
185
|
class Constant < Entry
|
192
186
|
end
|
193
187
|
|
188
|
+
# @abstract
|
194
189
|
class Parameter
|
195
|
-
extend T::Helpers
|
196
|
-
|
197
|
-
abstract!
|
198
|
-
|
199
190
|
# Name includes just the name of the parameter, excluding symbols like splats
|
200
191
|
#: Symbol
|
201
192
|
attr_reader :name
|
@@ -289,12 +280,8 @@ module RubyIndexer
|
|
289
280
|
end
|
290
281
|
end
|
291
282
|
|
283
|
+
# @abstract
|
292
284
|
class Member < Entry
|
293
|
-
extend T::Sig
|
294
|
-
extend T::Helpers
|
295
|
-
|
296
|
-
abstract!
|
297
|
-
|
298
285
|
#: Entry::Namespace?
|
299
286
|
attr_reader :owner
|
300
287
|
|
@@ -305,7 +292,8 @@ module RubyIndexer
|
|
305
292
|
@owner = owner
|
306
293
|
end
|
307
294
|
|
308
|
-
|
295
|
+
# @abstract
|
296
|
+
#: -> Array[Signature]
|
309
297
|
def signatures; end
|
310
298
|
|
311
299
|
#: -> String
|
@@ -818,11 +818,22 @@ module RubyIndexer
|
|
818
818
|
)
|
819
819
|
# Find the first class entry that has a parent class. Notice that if the developer makes a mistake and inherits
|
820
820
|
# from two different classes in different files, we simply ignore it
|
821
|
-
|
822
|
-
|
823
|
-
|
824
|
-
|
825
|
-
|
821
|
+
possible_parents = singleton_levels > 0 ? self[attached_class_name] : namespace_entries
|
822
|
+
superclass = nil #: Entry::Class?
|
823
|
+
|
824
|
+
possible_parents&.each do |n|
|
825
|
+
# Ignore non class entries
|
826
|
+
next unless n.is_a?(Entry::Class)
|
827
|
+
|
828
|
+
parent_class = n.parent_class
|
829
|
+
next unless parent_class
|
830
|
+
|
831
|
+
# Always set the superclass, but break early if we found one that isn't `::Object` (meaning we found an explicit
|
832
|
+
# parent class and not the implicit default). Note that when setting different parents to the same class, which
|
833
|
+
# is invalid, we pick whatever is the first one we find
|
834
|
+
superclass = n
|
835
|
+
break if parent_class != "::Object"
|
836
|
+
end
|
826
837
|
|
827
838
|
if superclass
|
828
839
|
# If the user makes a mistake and creates a class that inherits from itself, this method would throw a stack
|
@@ -3,11 +3,8 @@
|
|
3
3
|
|
4
4
|
module RubyIndexer
|
5
5
|
class ReferenceFinder
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
abstract!
|
10
|
-
end
|
6
|
+
# @abstract
|
7
|
+
class Target; end
|
11
8
|
|
12
9
|
class ConstTarget < Target
|
13
10
|
#: String
|
@@ -35,10 +32,14 @@ module RubyIndexer
|
|
35
32
|
#: String
|
36
33
|
attr_reader :name
|
37
34
|
|
38
|
-
#:
|
39
|
-
|
35
|
+
#: Array[String]
|
36
|
+
attr_reader :owner_ancestors
|
37
|
+
|
38
|
+
#: (String name, Array[String] owner_ancestors) -> void
|
39
|
+
def initialize(name, owner_ancestors)
|
40
40
|
super()
|
41
41
|
@name = name
|
42
|
+
@owner_ancestors = owner_ancestors
|
42
43
|
end
|
43
44
|
end
|
44
45
|
|
@@ -325,7 +326,10 @@ module RubyIndexer
|
|
325
326
|
def collect_instance_variable_references(name, location, declaration)
|
326
327
|
return unless @target.is_a?(InstanceVariableTarget) && name == @target.name
|
327
328
|
|
328
|
-
|
329
|
+
receiver_type = Index.actual_nesting(@stack, nil).join("::")
|
330
|
+
if @target.owner_ancestors.include?(receiver_type)
|
331
|
+
@references << Reference.new(name, location, declaration: declaration)
|
332
|
+
end
|
329
333
|
end
|
330
334
|
end
|
331
335
|
end
|
@@ -728,6 +728,30 @@ module RubyIndexer
|
|
728
728
|
assert_equal(["A", "ALIAS"], @index.linearized_ancestors_of("A"))
|
729
729
|
end
|
730
730
|
|
731
|
+
def test_linearizing_ancestors_for_classes_with_overridden_parents
|
732
|
+
index(<<~RUBY)
|
733
|
+
# Find the re-open of a class first, without specifying a parent
|
734
|
+
class Child
|
735
|
+
end
|
736
|
+
|
737
|
+
# Now, find the actual definition of the class, which includes a parent
|
738
|
+
class Parent; end
|
739
|
+
class Child < Parent
|
740
|
+
end
|
741
|
+
RUBY
|
742
|
+
|
743
|
+
assert_equal(
|
744
|
+
[
|
745
|
+
"Child",
|
746
|
+
"Parent",
|
747
|
+
"Object",
|
748
|
+
"Kernel",
|
749
|
+
"BasicObject",
|
750
|
+
],
|
751
|
+
@index.linearized_ancestors_of("Child"),
|
752
|
+
)
|
753
|
+
end
|
754
|
+
|
731
755
|
def test_resolving_an_inherited_method
|
732
756
|
index(<<~RUBY)
|
733
757
|
module Foo
|
@@ -236,5 +236,29 @@ module RubyIndexer
|
|
236
236
|
assert_instance_of(Entry::SingletonClass, owner)
|
237
237
|
assert_equal("Foo::<Class:Foo>", owner&.name)
|
238
238
|
end
|
239
|
+
|
240
|
+
def test_class_instance_variable_comments
|
241
|
+
index(<<~RUBY)
|
242
|
+
class Foo
|
243
|
+
# Documentation for @a
|
244
|
+
@a = "Hello" #: String
|
245
|
+
@b = "World" # trailing comment
|
246
|
+
@c = "!"
|
247
|
+
end
|
248
|
+
end
|
249
|
+
RUBY
|
250
|
+
|
251
|
+
assert_entry("@a", Entry::InstanceVariable, "/fake/path/foo.rb:2-4:2-6")
|
252
|
+
entry = @index["@a"]&.first #: as Entry::InstanceVariable
|
253
|
+
assert_equal("Documentation for @a", entry.comments)
|
254
|
+
|
255
|
+
assert_entry("@b", Entry::InstanceVariable, "/fake/path/foo.rb:3-4:3-6")
|
256
|
+
entry = @index["@b"]&.first #: as Entry::InstanceVariable
|
257
|
+
assert_empty(entry.comments)
|
258
|
+
|
259
|
+
assert_entry("@c", Entry::InstanceVariable, "/fake/path/foo.rb:4-4:4-6")
|
260
|
+
entry = @index["@c"]&.first #: as Entry::InstanceVariable
|
261
|
+
assert_empty(entry.comments)
|
262
|
+
end
|
239
263
|
end
|
240
264
|
end
|
@@ -950,6 +950,23 @@ module RubyIndexer
|
|
950
950
|
assert_predicate(entry, :public?)
|
951
951
|
end
|
952
952
|
|
953
|
+
def test_handling_attr
|
954
|
+
index(<<~RUBY)
|
955
|
+
class Foo
|
956
|
+
attr :bar
|
957
|
+
attr :baz, true
|
958
|
+
attr :qux, false
|
959
|
+
end
|
960
|
+
RUBY
|
961
|
+
|
962
|
+
assert_entry("bar", Entry::Accessor, "/fake/path/foo.rb:1-8:1-11")
|
963
|
+
assert_no_entry("bar=")
|
964
|
+
assert_entry("baz", Entry::Accessor, "/fake/path/foo.rb:2-8:2-11")
|
965
|
+
assert_entry("baz=", Entry::Accessor, "/fake/path/foo.rb:2-8:2-11")
|
966
|
+
assert_entry("qux", Entry::Accessor, "/fake/path/foo.rb:3-8:3-11")
|
967
|
+
assert_no_entry("qux=")
|
968
|
+
end
|
969
|
+
|
953
970
|
private
|
954
971
|
|
955
972
|
#: (Entry::Method entry, String call_string) -> void
|
@@ -216,22 +216,43 @@ module RubyIndexer
|
|
216
216
|
assert_equal(11, refs[2].location.start_line)
|
217
217
|
end
|
218
218
|
|
219
|
-
def
|
220
|
-
refs = find_instance_variable_references("@
|
219
|
+
def test_finds_instance_variable_references
|
220
|
+
refs = find_instance_variable_references("@name", ["Foo"], <<~RUBY)
|
221
221
|
class Foo
|
222
|
-
def
|
223
|
-
@foo
|
222
|
+
def initialize
|
223
|
+
@name = "foo"
|
224
|
+
end
|
225
|
+
def name
|
226
|
+
@name
|
227
|
+
end
|
228
|
+
def name_capital
|
229
|
+
@name[0]
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
class Bar
|
234
|
+
def initialize
|
235
|
+
@name = "foo"
|
236
|
+
end
|
237
|
+
def name
|
238
|
+
@name
|
224
239
|
end
|
225
240
|
end
|
226
241
|
RUBY
|
227
|
-
assert_equal(
|
242
|
+
assert_equal(3, refs.size)
|
228
243
|
|
229
|
-
assert_equal("@
|
244
|
+
assert_equal("@name", refs[0].name)
|
230
245
|
assert_equal(3, refs[0].location.start_line)
|
246
|
+
|
247
|
+
assert_equal("@name", refs[1].name)
|
248
|
+
assert_equal(6, refs[1].location.start_line)
|
249
|
+
|
250
|
+
assert_equal("@name", refs[2].name)
|
251
|
+
assert_equal(9, refs[2].location.start_line)
|
231
252
|
end
|
232
253
|
|
233
254
|
def test_finds_instance_variable_write_references
|
234
|
-
refs = find_instance_variable_references("@foo", <<~RUBY)
|
255
|
+
refs = find_instance_variable_references("@foo", ["Foo"], <<~RUBY)
|
235
256
|
class Foo
|
236
257
|
def write
|
237
258
|
@foo = 1
|
@@ -252,26 +273,70 @@ module RubyIndexer
|
|
252
273
|
assert_equal(7, refs[4].location.start_line)
|
253
274
|
end
|
254
275
|
|
255
|
-
def
|
256
|
-
refs = find_instance_variable_references("@name", <<~RUBY)
|
257
|
-
|
276
|
+
def test_finds_instance_variable_references_in_owner_ancestors
|
277
|
+
refs = find_instance_variable_references("@name", ["Foo", "Base", "Top", "Parent"], <<~RUBY)
|
278
|
+
module Base
|
279
|
+
def change_name(name)
|
280
|
+
@name = name
|
281
|
+
end
|
258
282
|
def name
|
283
|
+
@name
|
284
|
+
end
|
285
|
+
|
286
|
+
module ::Top
|
287
|
+
def name
|
288
|
+
@name
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
class Parent
|
294
|
+
def initialize
|
295
|
+
@name = "parent"
|
296
|
+
end
|
297
|
+
def name_capital
|
298
|
+
@name[0]
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
class Foo < Parent
|
303
|
+
include Base
|
304
|
+
def initialize
|
259
305
|
@name = "foo"
|
260
306
|
end
|
307
|
+
def name
|
308
|
+
@name
|
309
|
+
end
|
261
310
|
end
|
311
|
+
|
262
312
|
class Bar
|
263
313
|
def name
|
264
314
|
@name = "bar"
|
265
315
|
end
|
266
316
|
end
|
267
317
|
RUBY
|
268
|
-
assert_equal(
|
318
|
+
assert_equal(7, refs.size)
|
269
319
|
|
270
320
|
assert_equal("@name", refs[0].name)
|
271
321
|
assert_equal(3, refs[0].location.start_line)
|
272
322
|
|
273
323
|
assert_equal("@name", refs[1].name)
|
274
|
-
assert_equal(
|
324
|
+
assert_equal(6, refs[1].location.start_line)
|
325
|
+
|
326
|
+
assert_equal("@name", refs[2].name)
|
327
|
+
assert_equal(11, refs[2].location.start_line)
|
328
|
+
|
329
|
+
assert_equal("@name", refs[3].name)
|
330
|
+
assert_equal(18, refs[3].location.start_line)
|
331
|
+
|
332
|
+
assert_equal("@name", refs[4].name)
|
333
|
+
assert_equal(21, refs[4].location.start_line)
|
334
|
+
|
335
|
+
assert_equal("@name", refs[5].name)
|
336
|
+
assert_equal(28, refs[5].location.start_line)
|
337
|
+
|
338
|
+
assert_equal("@name", refs[6].name)
|
339
|
+
assert_equal(31, refs[6].location.start_line)
|
275
340
|
end
|
276
341
|
|
277
342
|
def test_accounts_for_reopened_classes
|
@@ -310,8 +375,8 @@ module RubyIndexer
|
|
310
375
|
find_references(target, source)
|
311
376
|
end
|
312
377
|
|
313
|
-
def find_instance_variable_references(instance_variable_name, source)
|
314
|
-
target = ReferenceFinder::InstanceVariableTarget.new(instance_variable_name)
|
378
|
+
def find_instance_variable_references(instance_variable_name, owner_ancestors, source)
|
379
|
+
target = ReferenceFinder::InstanceVariableTarget.new(instance_variable_name, owner_ancestors)
|
315
380
|
find_references(target, source)
|
316
381
|
end
|
317
382
|
|
data/lib/ruby_lsp/addon.rb
CHANGED
@@ -19,12 +19,8 @@ module RubyLsp
|
|
19
19
|
# end
|
20
20
|
# end
|
21
21
|
# ```
|
22
|
+
# @abstract
|
22
23
|
class Addon
|
23
|
-
extend T::Sig
|
24
|
-
extend T::Helpers
|
25
|
-
|
26
|
-
abstract!
|
27
|
-
|
28
24
|
@addons = [] #: Array[Addon]
|
29
25
|
@addon_classes = [] #: Array[singleton(Addon)]
|
30
26
|
# Add-on instances that have declared a handler to accept file watcher events
|
@@ -178,21 +174,25 @@ module RubyLsp
|
|
178
174
|
|
179
175
|
# Each add-on should implement `MyAddon#activate` and use to perform any sort of initialization, such as
|
180
176
|
# reading information into memory or even spawning a separate process
|
181
|
-
|
177
|
+
# @abstract
|
178
|
+
#: (GlobalState, Thread::Queue) -> void
|
182
179
|
def activate(global_state, outgoing_queue); end
|
183
180
|
|
184
181
|
# Each add-on should implement `MyAddon#deactivate` and use to perform any clean up, like shutting down a
|
185
182
|
# child process
|
186
|
-
|
183
|
+
# @abstract
|
184
|
+
#: -> void
|
187
185
|
def deactivate; end
|
188
186
|
|
189
187
|
# Add-ons should override the `name` method to return the add-on name
|
190
|
-
|
188
|
+
# @abstract
|
189
|
+
#: -> String
|
191
190
|
def name; end
|
192
191
|
|
193
192
|
# Add-ons should override the `version` method to return a semantic version string representing the add-on's
|
194
193
|
# version. This is used for compatibility checks
|
195
|
-
|
194
|
+
# @abstract
|
195
|
+
#: -> String
|
196
196
|
def version; end
|
197
197
|
|
198
198
|
# Handle a response from a window/showMessageRequest request. Add-ons must include the addon_name as part of the
|
data/lib/ruby_lsp/base_server.rb
CHANGED
@@ -2,12 +2,8 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
+
# @abstract
|
5
6
|
class BaseServer
|
6
|
-
extend T::Sig
|
7
|
-
extend T::Helpers
|
8
|
-
|
9
|
-
abstract!
|
10
|
-
|
11
7
|
#: (**untyped options) -> void
|
12
8
|
def initialize(**options)
|
13
9
|
@test_mode = options[:test_mode] #: bool?
|
@@ -130,10 +126,12 @@ module RubyLsp
|
|
130
126
|
@incoming_queue << message
|
131
127
|
end
|
132
128
|
|
133
|
-
|
129
|
+
# @abstract
|
130
|
+
#: (Hash[Symbol, untyped] message) -> void
|
134
131
|
def process_message(message); end
|
135
132
|
|
136
|
-
|
133
|
+
# @abstract
|
134
|
+
#: -> void
|
137
135
|
def shutdown; end
|
138
136
|
|
139
137
|
#: (Integer id, String message, ?type: Integer) -> void
|
data/lib/ruby_lsp/document.rb
CHANGED
@@ -2,21 +2,16 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
+
# @abstract
|
5
6
|
#: [ParseResultType]
|
6
7
|
class Document
|
7
|
-
extend T::Sig
|
8
|
-
extend T::Helpers
|
9
8
|
extend T::Generic
|
10
9
|
|
11
|
-
class LocationNotFoundError < StandardError; end
|
12
|
-
|
13
10
|
# This maximum number of characters for providing expensive features, like semantic highlighting and diagnostics.
|
14
11
|
# This is the same number used by the TypeScript extension in VS Code
|
15
12
|
MAXIMUM_CHARACTERS_FOR_EXPENSIVE_FEATURES = 100_000
|
16
13
|
EMPTY_CACHE = Object.new.freeze #: Object
|
17
14
|
|
18
|
-
abstract!
|
19
|
-
|
20
15
|
#: ParseResultType
|
21
16
|
attr_reader :parse_result
|
22
17
|
|
@@ -63,7 +58,8 @@ module RubyLsp
|
|
63
58
|
self.class == other.class && uri == other.uri && @source == other.source
|
64
59
|
end
|
65
60
|
|
66
|
-
|
61
|
+
# @abstract
|
62
|
+
#: -> Symbol
|
67
63
|
def language_id; end
|
68
64
|
|
69
65
|
#: [T] (String request_name) { (Document[ParseResultType] document) -> T } -> T
|
@@ -122,10 +118,12 @@ module RubyLsp
|
|
122
118
|
end
|
123
119
|
|
124
120
|
# Returns `true` if the document was parsed and `false` if nothing needed parsing
|
125
|
-
|
121
|
+
# @abstract
|
122
|
+
#: -> bool
|
126
123
|
def parse!; end
|
127
124
|
|
128
|
-
|
125
|
+
# @abstract
|
126
|
+
#: -> bool
|
129
127
|
def syntax_error?; end
|
130
128
|
|
131
129
|
#: -> bool
|
@@ -150,12 +148,8 @@ module RubyLsp
|
|
150
148
|
Scanner.new(@source, @encoding)
|
151
149
|
end
|
152
150
|
|
151
|
+
# @abstract
|
153
152
|
class Edit
|
154
|
-
extend T::Sig
|
155
|
-
extend T::Helpers
|
156
|
-
|
157
|
-
abstract!
|
158
|
-
|
159
153
|
#: Hash[Symbol, untyped]
|
160
154
|
attr_reader :range
|
161
155
|
|
@@ -180,7 +174,7 @@ module RubyLsp
|
|
180
174
|
def initialize(source, encoding)
|
181
175
|
@current_line = 0 #: Integer
|
182
176
|
@pos = 0 #: Integer
|
183
|
-
@
|
177
|
+
@bytes_or_codepoints = encoding == Encoding::UTF_8 ? source.bytes : source.codepoints #: Array[Integer]
|
184
178
|
@encoding = encoding
|
185
179
|
end
|
186
180
|
|
@@ -189,23 +183,40 @@ module RubyLsp
|
|
189
183
|
def find_char_position(position)
|
190
184
|
# Find the character index for the beginning of the requested line
|
191
185
|
until @current_line == position[:line]
|
192
|
-
until LINE_BREAK == @
|
193
|
-
|
186
|
+
@pos += 1 until LINE_BREAK == @bytes_or_codepoints[@pos]
|
187
|
+
@pos += 1
|
188
|
+
@current_line += 1
|
189
|
+
end
|
194
190
|
|
195
|
-
|
196
|
-
|
197
|
-
|
191
|
+
# For UTF-8, the code unit length is the same as bytes, but we want to return the character index
|
192
|
+
requested_position = if @encoding == Encoding::UTF_8
|
193
|
+
character_offset = 0
|
194
|
+
i = @pos
|
195
|
+
|
196
|
+
# Each group of bytes is a character. We advance based on the number of bytes to count how many full
|
197
|
+
# characters we have in the requested offset
|
198
|
+
while i < @pos + position[:character] && i < @bytes_or_codepoints.length
|
199
|
+
byte = @bytes_or_codepoints[i] #: as !nil
|
200
|
+
i += if byte < 0x80 # 1-byte character
|
201
|
+
1
|
202
|
+
elsif byte < 0xE0 # 2-byte character
|
203
|
+
2
|
204
|
+
elsif byte < 0xF0 # 3-byte character
|
205
|
+
3
|
206
|
+
else # 4-byte character
|
207
|
+
4
|
198
208
|
end
|
209
|
+
|
210
|
+
character_offset += 1
|
199
211
|
end
|
200
212
|
|
201
|
-
@pos
|
202
|
-
|
213
|
+
@pos + character_offset
|
214
|
+
else
|
215
|
+
@pos + position[:character]
|
203
216
|
end
|
204
217
|
|
205
218
|
# The final position is the beginning of the line plus the requested column. If the encoding is UTF-16, we also
|
206
219
|
# need to adjust for surrogate pairs
|
207
|
-
requested_position = @pos + position[:character]
|
208
|
-
|
209
220
|
if @encoding == Encoding::UTF_16LE
|
210
221
|
requested_position -= utf_16_character_position_correction(@pos, requested_position)
|
211
222
|
end
|
@@ -220,7 +231,7 @@ module RubyLsp
|
|
220
231
|
utf16_unicode_correction = 0
|
221
232
|
|
222
233
|
until current_position == requested_position
|
223
|
-
codepoint = @
|
234
|
+
codepoint = @bytes_or_codepoints[current_position]
|
224
235
|
utf16_unicode_correction += 1 if codepoint && codepoint > SURROGATE_PAIR_START
|
225
236
|
|
226
237
|
current_position += 1
|
@@ -2,7 +2,7 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
|
-
#: [ParseResultType = Prism::
|
5
|
+
#: [ParseResultType = Prism::ParseLexResult]
|
6
6
|
class ERBDocument < Document
|
7
7
|
#: String
|
8
8
|
attr_reader :host_language_source
|
@@ -31,11 +31,16 @@ module RubyLsp
|
|
31
31
|
@host_language_source = scanner.host_language
|
32
32
|
# Use partial script to avoid syntax errors in ERB files where keywords may be used without the full context in
|
33
33
|
# which they will be evaluated
|
34
|
-
@parse_result = Prism.
|
34
|
+
@parse_result = Prism.parse_lex(scanner.ruby, partial_script: true)
|
35
35
|
@code_units_cache = @parse_result.code_units_cache(@encoding)
|
36
36
|
true
|
37
37
|
end
|
38
38
|
|
39
|
+
#: -> Prism::ProgramNode
|
40
|
+
def ast
|
41
|
+
@parse_result.value.first
|
42
|
+
end
|
43
|
+
|
39
44
|
# @override
|
40
45
|
#: -> bool
|
41
46
|
def syntax_error?
|
@@ -53,7 +58,7 @@ module RubyLsp
|
|
53
58
|
char_position, _ = find_index_by_position(position)
|
54
59
|
|
55
60
|
RubyDocument.locate(
|
56
|
-
|
61
|
+
ast,
|
57
62
|
char_position,
|
58
63
|
code_units_cache: @code_units_cache,
|
59
64
|
node_types: node_types,
|