ruby-lsp 0.13.1 → 0.13.3
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 +30 -0
- data/VERSION +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/configuration.rb +1 -1
- data/lib/ruby_indexer/lib/ruby_indexer/entry.rb +30 -1
- data/lib/ruby_lsp/check_docs.rb +3 -3
- data/lib/ruby_lsp/document.rb +15 -7
- data/lib/ruby_lsp/executor.rb +85 -226
- data/lib/ruby_lsp/listener.rb +1 -50
- data/lib/ruby_lsp/listeners/code_lens.rb +233 -0
- data/lib/ruby_lsp/listeners/completion.rb +275 -0
- data/lib/ruby_lsp/listeners/definition.rb +158 -0
- data/lib/ruby_lsp/listeners/document_highlight.rb +556 -0
- data/lib/ruby_lsp/listeners/document_link.rb +162 -0
- data/lib/ruby_lsp/listeners/document_symbol.rb +223 -0
- data/lib/ruby_lsp/listeners/folding_ranges.rb +271 -0
- data/lib/ruby_lsp/listeners/hover.rb +152 -0
- data/lib/ruby_lsp/listeners/inlay_hints.rb +80 -0
- data/lib/ruby_lsp/listeners/semantic_highlighting.rb +430 -0
- data/lib/ruby_lsp/listeners/signature_help.rb +74 -0
- data/lib/ruby_lsp/requests/code_action_resolve.rb +5 -5
- data/lib/ruby_lsp/requests/code_actions.rb +15 -6
- data/lib/ruby_lsp/requests/code_lens.rb +21 -221
- data/lib/ruby_lsp/requests/completion.rb +64 -246
- data/lib/ruby_lsp/requests/definition.rb +34 -147
- data/lib/ruby_lsp/requests/diagnostics.rb +17 -5
- data/lib/ruby_lsp/requests/document_highlight.rb +12 -536
- data/lib/ruby_lsp/requests/document_link.rb +11 -132
- data/lib/ruby_lsp/requests/document_symbol.rb +23 -210
- data/lib/ruby_lsp/requests/folding_ranges.rb +16 -252
- data/lib/ruby_lsp/requests/formatting.rb +4 -4
- data/lib/ruby_lsp/requests/hover.rb +48 -92
- data/lib/ruby_lsp/requests/inlay_hints.rb +23 -56
- data/lib/ruby_lsp/requests/on_type_formatting.rb +18 -6
- data/lib/ruby_lsp/requests/request.rb +17 -0
- data/lib/ruby_lsp/requests/selection_ranges.rb +4 -3
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +21 -408
- data/lib/ruby_lsp/requests/show_syntax_tree.rb +5 -5
- data/lib/ruby_lsp/requests/signature_help.rb +87 -0
- data/lib/ruby_lsp/requests/support/common.rb +3 -2
- data/lib/ruby_lsp/requests/support/dependency_detector.rb +2 -0
- data/lib/ruby_lsp/requests/support/selection_range.rb +1 -1
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +2 -2
- data/lib/ruby_lsp/requests/workspace_symbol.rb +5 -4
- data/lib/ruby_lsp/requests.rb +3 -1
- data/lib/ruby_lsp/store.rb +1 -1
- data/lib/ruby_lsp/utils.rb +8 -0
- metadata +20 -8
- data/lib/ruby_lsp/requests/base_request.rb +0 -24
@@ -0,0 +1,158 @@
|
|
1
|
+
# typed: strict
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RubyLsp
|
5
|
+
module Listeners
|
6
|
+
class Definition < Listener
|
7
|
+
extend T::Sig
|
8
|
+
extend T::Generic
|
9
|
+
|
10
|
+
ResponseType = type_member { { fixed: T.nilable(T.any(T::Array[Interface::Location], Interface::Location)) } }
|
11
|
+
|
12
|
+
sig { override.returns(ResponseType) }
|
13
|
+
attr_reader :_response
|
14
|
+
|
15
|
+
sig do
|
16
|
+
params(
|
17
|
+
uri: URI::Generic,
|
18
|
+
nesting: T::Array[String],
|
19
|
+
index: RubyIndexer::Index,
|
20
|
+
dispatcher: Prism::Dispatcher,
|
21
|
+
typechecker_enabled: T::Boolean,
|
22
|
+
).void
|
23
|
+
end
|
24
|
+
def initialize(uri, nesting, index, dispatcher, typechecker_enabled)
|
25
|
+
@uri = uri
|
26
|
+
@nesting = nesting
|
27
|
+
@index = index
|
28
|
+
@typechecker_enabled = typechecker_enabled
|
29
|
+
@_response = T.let(nil, ResponseType)
|
30
|
+
|
31
|
+
super(dispatcher)
|
32
|
+
|
33
|
+
dispatcher.register(
|
34
|
+
self,
|
35
|
+
:on_call_node_enter,
|
36
|
+
:on_constant_read_node_enter,
|
37
|
+
:on_constant_path_node_enter,
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
sig { params(node: Prism::CallNode).void }
|
42
|
+
def on_call_node_enter(node)
|
43
|
+
message = node.name
|
44
|
+
|
45
|
+
if message == :require || message == :require_relative
|
46
|
+
handle_require_definition(node)
|
47
|
+
else
|
48
|
+
handle_method_definition(node)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
sig { params(node: Prism::ConstantPathNode).void }
|
53
|
+
def on_constant_path_node_enter(node)
|
54
|
+
find_in_index(node.slice)
|
55
|
+
end
|
56
|
+
|
57
|
+
sig { params(node: Prism::ConstantReadNode).void }
|
58
|
+
def on_constant_read_node_enter(node)
|
59
|
+
find_in_index(node.slice)
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
sig { params(node: Prism::CallNode).void }
|
65
|
+
def handle_method_definition(node)
|
66
|
+
return unless self_receiver?(node)
|
67
|
+
|
68
|
+
message = node.message
|
69
|
+
return unless message
|
70
|
+
|
71
|
+
target_method = @index.resolve_method(message, @nesting.join("::"))
|
72
|
+
return unless target_method
|
73
|
+
|
74
|
+
location = target_method.location
|
75
|
+
file_path = target_method.file_path
|
76
|
+
return if @typechecker_enabled && not_in_dependencies?(file_path)
|
77
|
+
|
78
|
+
@_response = Interface::Location.new(
|
79
|
+
uri: URI::Generic.from_path(path: file_path).to_s,
|
80
|
+
range: Interface::Range.new(
|
81
|
+
start: Interface::Position.new(line: location.start_line - 1, character: location.start_column),
|
82
|
+
end: Interface::Position.new(line: location.end_line - 1, character: location.end_column),
|
83
|
+
),
|
84
|
+
)
|
85
|
+
end
|
86
|
+
|
87
|
+
sig { params(node: Prism::CallNode).void }
|
88
|
+
def handle_require_definition(node)
|
89
|
+
message = node.name
|
90
|
+
arguments = node.arguments
|
91
|
+
return unless arguments
|
92
|
+
|
93
|
+
argument = arguments.arguments.first
|
94
|
+
return unless argument.is_a?(Prism::StringNode)
|
95
|
+
|
96
|
+
case message
|
97
|
+
when :require
|
98
|
+
entry = @index.search_require_paths(argument.content).find do |indexable_path|
|
99
|
+
indexable_path.require_path == argument.content
|
100
|
+
end
|
101
|
+
|
102
|
+
if entry
|
103
|
+
candidate = entry.full_path
|
104
|
+
|
105
|
+
@_response = Interface::Location.new(
|
106
|
+
uri: URI::Generic.from_path(path: candidate).to_s,
|
107
|
+
range: Interface::Range.new(
|
108
|
+
start: Interface::Position.new(line: 0, character: 0),
|
109
|
+
end: Interface::Position.new(line: 0, character: 0),
|
110
|
+
),
|
111
|
+
)
|
112
|
+
end
|
113
|
+
when :require_relative
|
114
|
+
required_file = "#{argument.content}.rb"
|
115
|
+
path = @uri.to_standardized_path
|
116
|
+
current_folder = path ? Pathname.new(CGI.unescape(path)).dirname : Dir.pwd
|
117
|
+
candidate = File.expand_path(File.join(current_folder, required_file))
|
118
|
+
|
119
|
+
@_response = Interface::Location.new(
|
120
|
+
uri: URI::Generic.from_path(path: candidate).to_s,
|
121
|
+
range: Interface::Range.new(
|
122
|
+
start: Interface::Position.new(line: 0, character: 0),
|
123
|
+
end: Interface::Position.new(line: 0, character: 0),
|
124
|
+
),
|
125
|
+
)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
sig { params(value: String).void }
|
130
|
+
def find_in_index(value)
|
131
|
+
entries = @index.resolve(value, @nesting)
|
132
|
+
return unless entries
|
133
|
+
|
134
|
+
# We should only allow jumping to the definition of private constants if the constant is defined in the same
|
135
|
+
# namespace as the reference
|
136
|
+
first_entry = T.must(entries.first)
|
137
|
+
return if first_entry.visibility == :private && first_entry.name != "#{@nesting.join("::")}::#{value}"
|
138
|
+
|
139
|
+
@_response = entries.filter_map do |entry|
|
140
|
+
location = entry.location
|
141
|
+
# If the project has Sorbet, then we only want to handle go to definition for constants defined in gems, as an
|
142
|
+
# additional behavior on top of jumping to RBIs. Sorbet can already handle go to definition for all constants
|
143
|
+
# in the project, even if the files are typed false
|
144
|
+
file_path = entry.file_path
|
145
|
+
next if @typechecker_enabled && not_in_dependencies?(file_path)
|
146
|
+
|
147
|
+
Interface::Location.new(
|
148
|
+
uri: URI::Generic.from_path(path: file_path).to_s,
|
149
|
+
range: Interface::Range.new(
|
150
|
+
start: Interface::Position.new(line: location.start_line - 1, character: location.start_column),
|
151
|
+
end: Interface::Position.new(line: location.end_line - 1, character: location.end_column),
|
152
|
+
),
|
153
|
+
)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|