ruby-lsp 0.13.1 → 0.13.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|