ruby-lsp 0.17.8 → 0.17.10
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/README.md +1 -1
- data/VERSION +1 -1
- data/exe/ruby-lsp +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +3 -3
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +4 -4
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +49 -20
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +83 -30
- data/lib/ruby_indexer/test/constant_test.rb +17 -17
- data/lib/ruby_indexer/test/index_test.rb +82 -10
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +38 -0
- data/lib/ruby_lsp/document.rb +27 -4
- data/lib/ruby_lsp/global_state.rb +2 -1
- data/lib/ruby_lsp/listeners/completion.rb +53 -33
- data/lib/ruby_lsp/listeners/definition.rb +23 -11
- data/lib/ruby_lsp/listeners/document_highlight.rb +5 -1
- data/lib/ruby_lsp/listeners/hover.rb +21 -9
- data/lib/ruby_lsp/listeners/signature_help.rb +13 -6
- data/lib/ruby_lsp/node_context.rb +2 -2
- data/lib/ruby_lsp/requests/completion.rb +3 -3
- data/lib/ruby_lsp/requests/completion_resolve.rb +10 -3
- data/lib/ruby_lsp/requests/definition.rb +3 -3
- data/lib/ruby_lsp/requests/hover.rb +3 -3
- data/lib/ruby_lsp/requests/on_type_formatting.rb +3 -2
- data/lib/ruby_lsp/requests/signature_help.rb +3 -3
- data/lib/ruby_lsp/requests/support/common.rb +11 -2
- data/lib/ruby_lsp/server.rb +9 -9
- data/lib/ruby_lsp/store.rb +6 -1
- data/lib/ruby_lsp/test_helper.rb +1 -1
- data/lib/ruby_lsp/type_inferrer.rb +48 -10
- data/lib/ruby_lsp/utils.rb +1 -0
- metadata +3 -3
@@ -36,10 +36,10 @@ module RubyLsp
|
|
36
36
|
global_state: GlobalState,
|
37
37
|
position: T::Hash[Symbol, T.untyped],
|
38
38
|
dispatcher: Prism::Dispatcher,
|
39
|
-
|
39
|
+
sorbet_level: Document::SorbetLevel,
|
40
40
|
).void
|
41
41
|
end
|
42
|
-
def initialize(document, global_state, position, dispatcher,
|
42
|
+
def initialize(document, global_state, position, dispatcher, sorbet_level)
|
43
43
|
super()
|
44
44
|
node_context = document.locate_node(position, node_types: Listeners::Hover::ALLOWED_TARGETS)
|
45
45
|
target = node_context.node
|
@@ -65,7 +65,7 @@ module RubyLsp
|
|
65
65
|
@target = T.let(target, T.nilable(Prism::Node))
|
66
66
|
uri = document.uri
|
67
67
|
@response_builder = T.let(ResponseBuilders::Hover.new, ResponseBuilders::Hover)
|
68
|
-
Listeners::Hover.new(@response_builder, global_state, uri, node_context, dispatcher,
|
68
|
+
Listeners::Hover.new(@response_builder, global_state, uri, node_context, dispatcher, sorbet_level)
|
69
69
|
Addon.addons.each do |addon|
|
70
70
|
addon.create_hover_listener(@response_builder, node_context, dispatcher)
|
71
71
|
end
|
@@ -32,8 +32,9 @@ module RubyLsp
|
|
32
32
|
|
33
33
|
END_REGEXES = T.let(
|
34
34
|
[
|
35
|
-
/\b(if|unless|for|while|
|
36
|
-
|
35
|
+
/\b(if|unless|for|while|until)\b($|\s|\()/,
|
36
|
+
/\b(class|module|def|case)\b($|\s)/,
|
37
|
+
/.*\s\bdo\b($|\s)/,
|
37
38
|
],
|
38
39
|
T::Array[Regexp],
|
39
40
|
)
|
@@ -46,10 +46,10 @@ module RubyLsp
|
|
46
46
|
position: T::Hash[Symbol, T.untyped],
|
47
47
|
context: T.nilable(T::Hash[Symbol, T.untyped]),
|
48
48
|
dispatcher: Prism::Dispatcher,
|
49
|
-
|
49
|
+
sorbet_level: Document::SorbetLevel,
|
50
50
|
).void
|
51
51
|
end
|
52
|
-
def initialize(document, global_state, position, context, dispatcher,
|
52
|
+
def initialize(document, global_state, position, context, dispatcher, sorbet_level) # rubocop:disable Metrics/ParameterLists
|
53
53
|
super()
|
54
54
|
node_context = document.locate_node(
|
55
55
|
{ line: position[:line], character: position[:character] },
|
@@ -61,7 +61,7 @@ module RubyLsp
|
|
61
61
|
@target = T.let(target, T.nilable(Prism::Node))
|
62
62
|
@dispatcher = dispatcher
|
63
63
|
@response_builder = T.let(ResponseBuilders::SignatureHelp.new, ResponseBuilders::SignatureHelp)
|
64
|
-
Listeners::SignatureHelp.new(@response_builder, global_state, node_context, dispatcher,
|
64
|
+
Listeners::SignatureHelp.new(@response_builder, global_state, node_context, dispatcher, sorbet_level)
|
65
65
|
end
|
66
66
|
|
67
67
|
sig { override.returns(T.nilable(Interface::SignatureHelp)) }
|
@@ -130,13 +130,17 @@ module RubyLsp
|
|
130
130
|
title: String,
|
131
131
|
entries: T.any(T::Array[RubyIndexer::Entry], RubyIndexer::Entry),
|
132
132
|
max_entries: T.nilable(Integer),
|
133
|
+
extra_links: T.nilable(String),
|
133
134
|
).returns(String)
|
134
135
|
end
|
135
|
-
def markdown_from_index_entries(title, entries, max_entries = nil)
|
136
|
+
def markdown_from_index_entries(title, entries, max_entries = nil, extra_links: nil)
|
136
137
|
categorized_markdown = categorized_markdown_from_index_entries(title, entries, max_entries)
|
137
138
|
|
139
|
+
markdown = +(categorized_markdown[:title] || "")
|
140
|
+
markdown << "\n\n#{extra_links}" if extra_links
|
141
|
+
|
138
142
|
<<~MARKDOWN.chomp
|
139
|
-
#{
|
143
|
+
#{markdown}
|
140
144
|
|
141
145
|
#{categorized_markdown[:links]}
|
142
146
|
|
@@ -204,6 +208,11 @@ module RubyLsp
|
|
204
208
|
Constant::SymbolKind::FIELD
|
205
209
|
end
|
206
210
|
end
|
211
|
+
|
212
|
+
sig { params(sorbet_level: Document::SorbetLevel).returns(T::Boolean) }
|
213
|
+
def sorbet_level_true_or_higher?(sorbet_level)
|
214
|
+
sorbet_level == Document::SorbetLevel::True || sorbet_level == Document::SorbetLevel::Strict
|
215
|
+
end
|
207
216
|
end
|
208
217
|
end
|
209
218
|
end
|
data/lib/ruby_lsp/server.rb
CHANGED
@@ -477,15 +477,17 @@ module RubyLsp
|
|
477
477
|
@global_state,
|
478
478
|
params[:position],
|
479
479
|
dispatcher,
|
480
|
-
|
480
|
+
sorbet_level(document),
|
481
481
|
).perform,
|
482
482
|
),
|
483
483
|
)
|
484
484
|
end
|
485
485
|
|
486
|
-
sig { params(document: Document).returns(
|
487
|
-
def
|
488
|
-
@global_state.has_type_checker
|
486
|
+
sig { params(document: Document).returns(Document::SorbetLevel) }
|
487
|
+
def sorbet_level(document)
|
488
|
+
return Document::SorbetLevel::Ignore unless @global_state.has_type_checker
|
489
|
+
|
490
|
+
document.sorbet_level
|
489
491
|
end
|
490
492
|
|
491
493
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
@@ -594,7 +596,7 @@ module RubyLsp
|
|
594
596
|
document,
|
595
597
|
@global_state,
|
596
598
|
params,
|
597
|
-
|
599
|
+
sorbet_level(document),
|
598
600
|
dispatcher,
|
599
601
|
).perform,
|
600
602
|
),
|
@@ -624,7 +626,7 @@ module RubyLsp
|
|
624
626
|
params[:position],
|
625
627
|
params[:context],
|
626
628
|
dispatcher,
|
627
|
-
|
629
|
+
sorbet_level(document),
|
628
630
|
).perform,
|
629
631
|
),
|
630
632
|
)
|
@@ -644,7 +646,7 @@ module RubyLsp
|
|
644
646
|
@global_state,
|
645
647
|
params[:position],
|
646
648
|
dispatcher,
|
647
|
-
|
649
|
+
sorbet_level(document),
|
648
650
|
).perform,
|
649
651
|
),
|
650
652
|
)
|
@@ -763,8 +765,6 @@ module RubyLsp
|
|
763
765
|
# stuck indexing files
|
764
766
|
Thread.new do
|
765
767
|
begin
|
766
|
-
RubyIndexer::RBSIndexer.new(@global_state.index).index_ruby_core
|
767
|
-
|
768
768
|
@global_state.index.index_all do |percentage|
|
769
769
|
progress("indexing-progress", percentage)
|
770
770
|
true
|
data/lib/ruby_lsp/store.rb
CHANGED
@@ -38,13 +38,18 @@ module RubyLsp
|
|
38
38
|
document = @state[uri.to_s]
|
39
39
|
return document unless document.nil?
|
40
40
|
|
41
|
-
path
|
41
|
+
# For unsaved files (`untitled:Untitled-1` uris), there's no path to read from. If we don't have the untitled file
|
42
|
+
# already present in the store, then we have to raise non existing document error
|
43
|
+
path = uri.to_standardized_path
|
44
|
+
raise NonExistingDocumentError, uri.to_s unless path
|
45
|
+
|
42
46
|
ext = File.extname(path)
|
43
47
|
language_id = if ext == ".erb" || ext == ".rhtml"
|
44
48
|
Document::LanguageId::ERB
|
45
49
|
else
|
46
50
|
Document::LanguageId::Ruby
|
47
51
|
end
|
52
|
+
|
48
53
|
set(uri: uri, source: File.binread(path), version: 0, language_id: language_id)
|
49
54
|
T.must(@state[uri.to_s])
|
50
55
|
rescue Errno::ENOENT
|
data/lib/ruby_lsp/test_helper.rb
CHANGED
@@ -21,7 +21,7 @@ module RubyLsp
|
|
21
21
|
&block)
|
22
22
|
server = RubyLsp::Server.new(test_mode: true)
|
23
23
|
server.global_state.stubs(:has_type_checker).returns(false) if stub_no_typechecker
|
24
|
-
server.global_state.apply_options({})
|
24
|
+
server.global_state.apply_options({ initializationOptions: { experimentalFeaturesEnabled: true } })
|
25
25
|
language_id = uri.to_s.end_with?(".erb") ? "erb" : "ruby"
|
26
26
|
|
27
27
|
if source
|
@@ -7,12 +7,16 @@ module RubyLsp
|
|
7
7
|
class TypeInferrer
|
8
8
|
extend T::Sig
|
9
9
|
|
10
|
-
sig { params(
|
11
|
-
|
10
|
+
sig { params(experimental_features: T::Boolean).returns(T::Boolean) }
|
11
|
+
attr_writer :experimental_features
|
12
|
+
|
13
|
+
sig { params(index: RubyIndexer::Index, experimental_features: T::Boolean).void }
|
14
|
+
def initialize(index, experimental_features = true)
|
12
15
|
@index = index
|
16
|
+
@experimental_features = experimental_features
|
13
17
|
end
|
14
18
|
|
15
|
-
sig { params(node_context: NodeContext).returns(T.nilable(
|
19
|
+
sig { params(node_context: NodeContext).returns(T.nilable(Type)) }
|
16
20
|
def infer_receiver_type(node_context)
|
17
21
|
node = node_context.node
|
18
22
|
|
@@ -28,7 +32,7 @@ module RubyLsp
|
|
28
32
|
|
29
33
|
private
|
30
34
|
|
31
|
-
sig { params(node: Prism::CallNode, node_context: NodeContext).returns(T.nilable(
|
35
|
+
sig { params(node: Prism::CallNode, node_context: NodeContext).returns(T.nilable(Type)) }
|
32
36
|
def infer_receiver_for_call_node(node, node_context)
|
33
37
|
receiver = node.receiver
|
34
38
|
|
@@ -47,23 +51,40 @@ module RubyLsp
|
|
47
51
|
return unless name
|
48
52
|
|
49
53
|
*parts, last = name.split("::")
|
50
|
-
return "#{last}::<Class:#{last}>" if parts.empty?
|
54
|
+
return Type.new("#{last}::<Class:#{last}>") if parts.empty?
|
55
|
+
|
56
|
+
Type.new("#{parts.join("::")}::#{last}::<Class:#{last}>")
|
57
|
+
else
|
58
|
+
return unless @experimental_features
|
59
|
+
|
60
|
+
raw_receiver = node.receiver&.slice
|
51
61
|
|
52
|
-
|
62
|
+
if raw_receiver
|
63
|
+
guessed_name = raw_receiver
|
64
|
+
.delete_prefix("@")
|
65
|
+
.delete_prefix("@@")
|
66
|
+
.split("_")
|
67
|
+
.map(&:capitalize)
|
68
|
+
.join
|
69
|
+
|
70
|
+
entries = @index.resolve(guessed_name, node_context.nesting) || @index.first_unqualified_const(guessed_name)
|
71
|
+
name = entries&.first&.name
|
72
|
+
GuessedType.new(name) if name
|
73
|
+
end
|
53
74
|
end
|
54
75
|
end
|
55
76
|
|
56
|
-
sig { params(node_context: NodeContext).returns(
|
77
|
+
sig { params(node_context: NodeContext).returns(Type) }
|
57
78
|
def self_receiver_handling(node_context)
|
58
79
|
nesting = node_context.nesting
|
59
80
|
# If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
|
60
81
|
# inherits from Object
|
61
|
-
return "Object" if nesting.empty?
|
62
|
-
return node_context.fully_qualified_name if node_context.surrounding_method
|
82
|
+
return Type.new("Object") if nesting.empty?
|
83
|
+
return Type.new(node_context.fully_qualified_name) if node_context.surrounding_method
|
63
84
|
|
64
85
|
# If we're not inside a method, then we're inside the body of a class or module, which is a singleton
|
65
86
|
# context
|
66
|
-
"#{nesting.join("::")}::<Class:#{nesting.last}>"
|
87
|
+
Type.new("#{nesting.join("::")}::<Class:#{nesting.last}>")
|
67
88
|
end
|
68
89
|
|
69
90
|
sig do
|
@@ -80,5 +101,22 @@ module RubyLsp
|
|
80
101
|
Prism::ConstantPathNode::MissingNodesInConstantPathError
|
81
102
|
nil
|
82
103
|
end
|
104
|
+
|
105
|
+
# A known type
|
106
|
+
class Type
|
107
|
+
extend T::Sig
|
108
|
+
|
109
|
+
sig { returns(String) }
|
110
|
+
attr_reader :name
|
111
|
+
|
112
|
+
sig { params(name: String).void }
|
113
|
+
def initialize(name)
|
114
|
+
@name = name
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# A type that was guessed based on the receiver raw name
|
119
|
+
class GuessedType < Type
|
120
|
+
end
|
83
121
|
end
|
84
122
|
end
|
data/lib/ruby_lsp/utils.rb
CHANGED
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.17.
|
4
|
+
version: 0.17.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-07-
|
11
|
+
date: 2024-07-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|
@@ -204,7 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
204
|
- !ruby/object:Gem::Version
|
205
205
|
version: '0'
|
206
206
|
requirements: []
|
207
|
-
rubygems_version: 3.5.
|
207
|
+
rubygems_version: 3.5.16
|
208
208
|
signing_key:
|
209
209
|
specification_version: 4
|
210
210
|
summary: An opinionated language server for Ruby
|