ruby-lsp 0.17.2 → 0.17.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -0
- data/VERSION +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/declaration_listener.rb +280 -74
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +102 -102
- data/lib/ruby_indexer/lib/ruby_indexer/index.rb +234 -56
- data/lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb +147 -0
- data/lib/ruby_indexer/ruby_indexer.rb +1 -0
- data/lib/ruby_indexer/test/classes_and_modules_test.rb +49 -2
- data/lib/ruby_indexer/test/configuration_test.rb +1 -1
- data/lib/ruby_indexer/test/constant_test.rb +1 -1
- data/lib/ruby_indexer/test/index_test.rb +702 -71
- data/lib/ruby_indexer/test/instance_variables_test.rb +84 -7
- data/lib/ruby_indexer/test/method_test.rb +74 -24
- data/lib/ruby_indexer/test/rbs_indexer_test.rb +67 -0
- data/lib/ruby_indexer/test/test_case.rb +7 -0
- data/lib/ruby_lsp/document.rb +37 -8
- data/lib/ruby_lsp/global_state.rb +43 -18
- data/lib/ruby_lsp/internal.rb +2 -0
- data/lib/ruby_lsp/listeners/code_lens.rb +2 -2
- data/lib/ruby_lsp/listeners/completion.rb +53 -14
- data/lib/ruby_lsp/listeners/definition.rb +11 -7
- data/lib/ruby_lsp/listeners/hover.rb +14 -7
- data/lib/ruby_lsp/listeners/signature_help.rb +5 -2
- data/lib/ruby_lsp/node_context.rb +6 -1
- data/lib/ruby_lsp/requests/completion.rb +5 -4
- data/lib/ruby_lsp/requests/completion_resolve.rb +8 -0
- data/lib/ruby_lsp/requests/prepare_type_hierarchy.rb +88 -0
- data/lib/ruby_lsp/requests/support/common.rb +19 -1
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +12 -4
- data/lib/ruby_lsp/requests/type_hierarchy_supertypes.rb +91 -0
- data/lib/ruby_lsp/requests/workspace_symbol.rb +1 -21
- data/lib/ruby_lsp/requests.rb +2 -0
- data/lib/ruby_lsp/server.rb +54 -4
- data/lib/ruby_lsp/test_helper.rb +1 -1
- data/lib/ruby_lsp/type_inferrer.rb +86 -0
- metadata +29 -4
data/lib/ruby_lsp/server.rb
CHANGED
@@ -68,6 +68,12 @@ module RubyLsp
|
|
68
68
|
text_document_signature_help(message)
|
69
69
|
when "textDocument/definition"
|
70
70
|
text_document_definition(message)
|
71
|
+
when "textDocument/prepareTypeHierarchy"
|
72
|
+
text_document_prepare_type_hierarchy(message)
|
73
|
+
when "typeHierarchy/supertypes"
|
74
|
+
type_hierarchy_supertypes(message)
|
75
|
+
when "typeHierarchy/subtypes"
|
76
|
+
type_hierarchy_subtypes(message)
|
71
77
|
when "workspace/didChangeWatchedFiles"
|
72
78
|
workspace_did_change_watched_files(message)
|
73
79
|
when "workspace/symbol"
|
@@ -76,6 +82,16 @@ module RubyLsp
|
|
76
82
|
text_document_show_syntax_tree(message)
|
77
83
|
when "rubyLsp/workspace/dependencies"
|
78
84
|
workspace_dependencies(message)
|
85
|
+
when "rubyLsp/workspace/addons"
|
86
|
+
send_message(
|
87
|
+
Result.new(
|
88
|
+
id: message[:id],
|
89
|
+
response:
|
90
|
+
Addon.addons.map do |addon|
|
91
|
+
{ name: addon.name, errored: addon.error? }
|
92
|
+
end,
|
93
|
+
),
|
94
|
+
)
|
79
95
|
when "$/cancelRequest"
|
80
96
|
@mutex.synchronize { @cancelled_requests << message[:params][:id] }
|
81
97
|
end
|
@@ -104,7 +120,7 @@ module RubyLsp
|
|
104
120
|
),
|
105
121
|
)
|
106
122
|
|
107
|
-
$stderr.puts(errored_addons.map(&:errors_details).join("\n\n"))
|
123
|
+
$stderr.puts(errored_addons.map(&:errors_details).join("\n\n")) unless @test_mode
|
108
124
|
end
|
109
125
|
end
|
110
126
|
|
@@ -152,6 +168,7 @@ module RubyLsp
|
|
152
168
|
inlay_hint_provider = Requests::InlayHints.provider if enabled_features["inlayHint"]
|
153
169
|
completion_provider = Requests::Completion.provider if enabled_features["completion"]
|
154
170
|
signature_help_provider = Requests::SignatureHelp.provider if enabled_features["signatureHelp"]
|
171
|
+
type_hierarchy_provider = Requests::PrepareTypeHierarchy.provider if enabled_features["typeHierarchy"]
|
155
172
|
|
156
173
|
response = {
|
157
174
|
capabilities: Interface::ServerCapabilities.new(
|
@@ -175,8 +192,12 @@ module RubyLsp
|
|
175
192
|
completion_provider: completion_provider,
|
176
193
|
code_lens_provider: code_lens_provider,
|
177
194
|
definition_provider: enabled_features["definition"],
|
178
|
-
workspace_symbol_provider: enabled_features["workspaceSymbol"] && !@global_state.
|
195
|
+
workspace_symbol_provider: enabled_features["workspaceSymbol"] && !@global_state.has_type_checker,
|
179
196
|
signature_help_provider: signature_help_provider,
|
197
|
+
type_hierarchy_provider: type_hierarchy_provider,
|
198
|
+
experimental: {
|
199
|
+
addon_detection: true,
|
200
|
+
},
|
180
201
|
),
|
181
202
|
serverInfo: {
|
182
203
|
name: "Ruby LSP",
|
@@ -449,7 +470,7 @@ module RubyLsp
|
|
449
470
|
|
450
471
|
sig { params(document: Document).returns(T::Boolean) }
|
451
472
|
def typechecker_enabled?(document)
|
452
|
-
@global_state.
|
473
|
+
@global_state.has_type_checker && document.sorbet_sigil_is_true_or_higher
|
453
474
|
end
|
454
475
|
|
455
476
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
@@ -551,7 +572,7 @@ module RubyLsp
|
|
551
572
|
response: Requests::Completion.new(
|
552
573
|
document,
|
553
574
|
@global_state,
|
554
|
-
params
|
575
|
+
params,
|
555
576
|
typechecker_enabled?(document),
|
556
577
|
dispatcher,
|
557
578
|
).perform,
|
@@ -660,6 +681,33 @@ module RubyLsp
|
|
660
681
|
send_message(Result.new(id: message[:id], response: response))
|
661
682
|
end
|
662
683
|
|
684
|
+
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
685
|
+
def text_document_prepare_type_hierarchy(message)
|
686
|
+
params = message[:params]
|
687
|
+
response = Requests::PrepareTypeHierarchy.new(
|
688
|
+
@store.get(params.dig(:textDocument, :uri)),
|
689
|
+
@global_state.index,
|
690
|
+
params[:position],
|
691
|
+
).perform
|
692
|
+
send_message(Result.new(id: message[:id], response: response))
|
693
|
+
end
|
694
|
+
|
695
|
+
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
696
|
+
def type_hierarchy_supertypes(message)
|
697
|
+
response = Requests::TypeHierarchySupertypes.new(
|
698
|
+
@global_state.index,
|
699
|
+
message.dig(:params, :item),
|
700
|
+
).perform
|
701
|
+
send_message(Result.new(id: message[:id], response: response))
|
702
|
+
end
|
703
|
+
|
704
|
+
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
705
|
+
def type_hierarchy_subtypes(message)
|
706
|
+
# TODO: implement subtypes
|
707
|
+
# The current index representation doesn't allow us to find the children of an entry.
|
708
|
+
send_message(Result.new(id: message[:id], response: nil))
|
709
|
+
end
|
710
|
+
|
663
711
|
sig { params(message: T::Hash[Symbol, T.untyped]).void }
|
664
712
|
def workspace_dependencies(message)
|
665
713
|
response = begin
|
@@ -696,6 +744,8 @@ module RubyLsp
|
|
696
744
|
|
697
745
|
Thread.new do
|
698
746
|
begin
|
747
|
+
RubyIndexer::RBSIndexer.new(@global_state.index).index_ruby_core
|
748
|
+
|
699
749
|
@global_state.index.index_all do |percentage|
|
700
750
|
progress("indexing-progress", percentage)
|
701
751
|
true
|
data/lib/ruby_lsp/test_helper.rb
CHANGED
@@ -20,7 +20,7 @@ module RubyLsp
|
|
20
20
|
def with_server(source = nil, uri = Kernel.URI("file:///fake.rb"), stub_no_typechecker: false, load_addons: true,
|
21
21
|
&block)
|
22
22
|
server = RubyLsp::Server.new(test_mode: true)
|
23
|
-
server.global_state.stubs(:
|
23
|
+
server.global_state.stubs(:has_type_checker).returns(false) if stub_no_typechecker
|
24
24
|
server.global_state.apply_options({})
|
25
25
|
|
26
26
|
if source
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
# A minimalistic type checker to try to resolve types that can be inferred without requiring a type system or
|
6
|
+
# annotations
|
7
|
+
class TypeInferrer
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { params(index: RubyIndexer::Index).void }
|
11
|
+
def initialize(index)
|
12
|
+
@index = index
|
13
|
+
end
|
14
|
+
|
15
|
+
sig { params(node_context: NodeContext).returns(T.nilable(String)) }
|
16
|
+
def infer_receiver_type(node_context)
|
17
|
+
node = node_context.node
|
18
|
+
|
19
|
+
case node
|
20
|
+
when Prism::CallNode
|
21
|
+
infer_receiver_for_call_node(node, node_context)
|
22
|
+
when Prism::InstanceVariableReadNode, Prism::InstanceVariableAndWriteNode, Prism::InstanceVariableWriteNode,
|
23
|
+
Prism::InstanceVariableOperatorWriteNode, Prism::InstanceVariableOrWriteNode, Prism::InstanceVariableTargetNode
|
24
|
+
nesting = node_context.nesting
|
25
|
+
# If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
|
26
|
+
# inherits from Object
|
27
|
+
return "Object" if nesting.empty?
|
28
|
+
|
29
|
+
fully_qualified_name = node_context.fully_qualified_name
|
30
|
+
return fully_qualified_name if node_context.surrounding_method
|
31
|
+
|
32
|
+
"#{fully_qualified_name}::<Class:#{nesting.last}>"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
sig { params(node: Prism::CallNode, node_context: NodeContext).returns(T.nilable(String)) }
|
39
|
+
def infer_receiver_for_call_node(node, node_context)
|
40
|
+
receiver = node.receiver
|
41
|
+
|
42
|
+
case receiver
|
43
|
+
when Prism::SelfNode, nil
|
44
|
+
nesting = node_context.nesting
|
45
|
+
# If we're at the top level, then the invocation is happening on `<main>`, which is a special singleton that
|
46
|
+
# inherits from Object
|
47
|
+
return "Object" if nesting.empty?
|
48
|
+
return node_context.fully_qualified_name if node_context.surrounding_method
|
49
|
+
|
50
|
+
# If we're not inside a method, then we're inside the body of a class or module, which is a singleton
|
51
|
+
# context
|
52
|
+
"#{nesting.join("::")}::<Class:#{nesting.last}>"
|
53
|
+
when Prism::ConstantPathNode, Prism::ConstantReadNode
|
54
|
+
# When the receiver is a constant reference, we have to try to resolve it to figure out the right
|
55
|
+
# receiver. But since the invocation is directly on the constant, that's the singleton context of that
|
56
|
+
# class/module
|
57
|
+
receiver_name = constant_name(receiver)
|
58
|
+
return unless receiver_name
|
59
|
+
|
60
|
+
resolved_receiver = @index.resolve(receiver_name, node_context.nesting)
|
61
|
+
name = resolved_receiver&.first&.name
|
62
|
+
return unless name
|
63
|
+
|
64
|
+
*parts, last = name.split("::")
|
65
|
+
return "#{last}::<Class:#{last}>" if parts.empty?
|
66
|
+
|
67
|
+
"#{parts.join("::")}::#{last}::<Class:#{last}>"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
sig do
|
72
|
+
params(
|
73
|
+
node: T.any(
|
74
|
+
Prism::ConstantPathNode,
|
75
|
+
Prism::ConstantReadNode,
|
76
|
+
),
|
77
|
+
).returns(T.nilable(String))
|
78
|
+
end
|
79
|
+
def constant_name(node)
|
80
|
+
node.full_name
|
81
|
+
rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
|
82
|
+
Prism::ConstantPathNode::MissingNodesInConstantPathError
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
end
|
86
|
+
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.17.
|
4
|
+
version: 0.17.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shopify
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-06-
|
11
|
+
date: 2024-06-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: language_server-protocol
|
@@ -33,7 +33,7 @@ dependencies:
|
|
33
33
|
version: 0.29.0
|
34
34
|
- - "<"
|
35
35
|
- !ruby/object:Gem::Version
|
36
|
-
version: '0.
|
36
|
+
version: '0.31'
|
37
37
|
type: :runtime
|
38
38
|
prerelease: false
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -43,7 +43,27 @@ dependencies:
|
|
43
43
|
version: 0.29.0
|
44
44
|
- - "<"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '0.
|
46
|
+
version: '0.31'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rbs
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3'
|
54
|
+
- - "<"
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '4'
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '3'
|
64
|
+
- - "<"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '4'
|
47
67
|
- !ruby/object:Gem::Dependency
|
48
68
|
name: sorbet-runtime
|
49
69
|
requirement: !ruby/object:Gem::Requirement
|
@@ -85,6 +105,7 @@ files:
|
|
85
105
|
- lib/ruby_indexer/lib/ruby_indexer/indexable_path.rb
|
86
106
|
- lib/ruby_indexer/lib/ruby_indexer/location.rb
|
87
107
|
- lib/ruby_indexer/lib/ruby_indexer/prefix_tree.rb
|
108
|
+
- lib/ruby_indexer/lib/ruby_indexer/rbs_indexer.rb
|
88
109
|
- lib/ruby_indexer/ruby_indexer.rb
|
89
110
|
- lib/ruby_indexer/test/classes_and_modules_test.rb
|
90
111
|
- lib/ruby_indexer/test/configuration_test.rb
|
@@ -93,6 +114,7 @@ files:
|
|
93
114
|
- lib/ruby_indexer/test/instance_variables_test.rb
|
94
115
|
- lib/ruby_indexer/test/method_test.rb
|
95
116
|
- lib/ruby_indexer/test/prefix_tree_test.rb
|
117
|
+
- lib/ruby_indexer/test/rbs_indexer_test.rb
|
96
118
|
- lib/ruby_indexer/test/test_case.rb
|
97
119
|
- lib/ruby_lsp/addon.rb
|
98
120
|
- lib/ruby_lsp/base_server.rb
|
@@ -130,6 +152,7 @@ files:
|
|
130
152
|
- lib/ruby_lsp/requests/hover.rb
|
131
153
|
- lib/ruby_lsp/requests/inlay_hints.rb
|
132
154
|
- lib/ruby_lsp/requests/on_type_formatting.rb
|
155
|
+
- lib/ruby_lsp/requests/prepare_type_hierarchy.rb
|
133
156
|
- lib/ruby_lsp/requests/request.rb
|
134
157
|
- lib/ruby_lsp/requests/selection_ranges.rb
|
135
158
|
- lib/ruby_lsp/requests/semantic_highlighting.rb
|
@@ -145,6 +168,7 @@ files:
|
|
145
168
|
- lib/ruby_lsp/requests/support/sorbet.rb
|
146
169
|
- lib/ruby_lsp/requests/support/source_uri.rb
|
147
170
|
- lib/ruby_lsp/requests/support/syntax_tree_formatter.rb
|
171
|
+
- lib/ruby_lsp/requests/type_hierarchy_supertypes.rb
|
148
172
|
- lib/ruby_lsp/requests/workspace_symbol.rb
|
149
173
|
- lib/ruby_lsp/response_builders.rb
|
150
174
|
- lib/ruby_lsp/response_builders/collection_response_builder.rb
|
@@ -158,6 +182,7 @@ files:
|
|
158
182
|
- lib/ruby_lsp/setup_bundler.rb
|
159
183
|
- lib/ruby_lsp/store.rb
|
160
184
|
- lib/ruby_lsp/test_helper.rb
|
185
|
+
- lib/ruby_lsp/type_inferrer.rb
|
161
186
|
- lib/ruby_lsp/utils.rb
|
162
187
|
homepage: https://github.com/Shopify/ruby-lsp
|
163
188
|
licenses:
|