ruby-lsp 0.0.4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -1
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +13 -13
- data/README.md +1 -1
- data/VERSION +1 -1
- data/exe/ruby-lsp +1 -1
- data/lib/ruby-lsp.rb +2 -2
- data/lib/ruby_lsp/document.rb +7 -1
- data/lib/ruby_lsp/handler.rb +30 -32
- data/lib/{internal.rb → ruby_lsp/internal.rb} +1 -1
- data/lib/ruby_lsp/requests/base_request.rb +9 -7
- data/lib/ruby_lsp/requests/code_actions.rb +18 -9
- data/lib/ruby_lsp/requests/diagnostics.rb +13 -1
- data/lib/ruby_lsp/requests/document_highlight.rb +21 -6
- data/lib/ruby_lsp/requests/document_symbol.rb +57 -10
- data/lib/ruby_lsp/requests/folding_ranges.rb +52 -18
- data/lib/ruby_lsp/requests/formatting.rb +8 -3
- data/lib/ruby_lsp/requests/rubocop_request.rb +19 -9
- data/lib/ruby_lsp/requests/selection_ranges.rb +16 -5
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +104 -29
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +16 -4
- data/lib/ruby_lsp/requests/support/selection_range.rb +4 -1
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +13 -3
- data/lib/ruby_lsp/requests/support/syntax_error_diagnostic.rb +6 -1
- data/lib/ruby_lsp/requests.rb +1 -1
- data/lib/ruby_lsp/store.rb +6 -5
- data/rakelib/check_docs.rake +1 -0
- data/ruby-lsp.gemspec +1 -1
- data/sorbet/tapioca/require.rb +1 -1
- metadata +6 -7
- data/shipit.production.yml +0 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b072ffa3ea73a83aba6d6c32b931c4de30b0de06fd70655d620c3ed95bd8aa4
|
4
|
+
data.tar.gz: 24568688b20ffed38defcbc0b00708eb22a7dad20a9b5f397348242a64359bfd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ea1830f0be08cb291e67d80bbe21dbe17f3e4b4d285b1d9112e004ca2feff32eaca85af755bc2635e3341ab4e64491710c3ba13c5bed617e34495534e1d7a5f8
|
7
|
+
data.tar.gz: f84b1b27c5c17455d1e8423f1e52f98a754ed123e1722bd536ee7bfdc754952e5d6619c0f4402664a33dc278bdc2422a3e7a37c8de5f172e4456e7a6c08b7a67
|
data/.rubocop.yml
CHANGED
@@ -25,6 +25,15 @@ Sorbet/FalseSigil:
|
|
25
25
|
Sorbet/TrueSigil:
|
26
26
|
Enabled: true
|
27
27
|
Include:
|
28
|
-
- "
|
28
|
+
- "test/**/*.rb"
|
29
29
|
Exclude:
|
30
30
|
- "**/*.rake"
|
31
|
+
- "lib/**/*.rb"
|
32
|
+
|
33
|
+
Sorbet/StrictSigil:
|
34
|
+
Enabled: true
|
35
|
+
Include:
|
36
|
+
- "lib/**/*.rb"
|
37
|
+
Exclude:
|
38
|
+
- "**/*.rake"
|
39
|
+
- "test/**/*.rb"
|
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,16 @@ Check [Keep a Changelog](http://keepachangelog.com/) for recommendations on how
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.1.0]
|
10
|
+
|
11
|
+
- Implement token modifiers in SemanticTokenEncoder ([#112](https://github.com/Shopify/ruby-lsp/pull/112))
|
12
|
+
- Add semantic token for name in a method definition ([#133](https://github.com/Shopify/ruby-lsp/pull/133))
|
13
|
+
- Add semantic highighting for def endless and singleton method names ([#134](https://github.com/Shopify/ruby-lsp/pull/134))
|
14
|
+
- Add semantic token for keyword self ([#137](https://github.com/Shopify/ruby-lsp/pull/137))
|
15
|
+
- Add semantic token for constants ([#138](https://github.com/Shopify/ruby-lsp/pull/138))
|
16
|
+
- Improve error handling + fix formatting hanging issue ([#149](https://github.com/Shopify/ruby-lsp/pull/149))
|
17
|
+
- Set the minimum syntax_tree version to 2.4 ([#151](https://github.com/Shopify/ruby-lsp/pull/151))
|
18
|
+
|
9
19
|
## [0.0.4]
|
10
20
|
|
11
21
|
- Add basic document highlight (https://github.com/Shopify/ruby-lsp/pull/91)
|
data/Gemfile
CHANGED
@@ -9,7 +9,7 @@ gem "minitest", "~> 5.15"
|
|
9
9
|
gem "minitest-reporters", "~> 1.5"
|
10
10
|
gem "rake", "~> 13.0"
|
11
11
|
gem "rubocop-shopify", "~> 2.7", require: false
|
12
|
-
gem "rubocop-minitest", "~> 0.20.
|
12
|
+
gem "rubocop-minitest", "~> 0.20.1", require: false
|
13
13
|
gem "rubocop-rake", "~> 0.6.0", require: false
|
14
14
|
gem "rubocop-sorbet", "~> 0.6", require: false
|
15
15
|
gem "sorbet-static-and-runtime"
|
data/Gemfile.lock
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ruby-lsp (0.0
|
4
|
+
ruby-lsp (0.1.0)
|
5
5
|
language_server-protocol
|
6
6
|
rubocop (>= 1.0)
|
7
7
|
sorbet-runtime
|
8
|
-
syntax_tree (>= 2.
|
8
|
+
syntax_tree (>= 2.4)
|
9
9
|
|
10
10
|
GEM
|
11
11
|
remote: https://rubygems.org/
|
@@ -47,7 +47,7 @@ GEM
|
|
47
47
|
reline (0.3.1)
|
48
48
|
io-console (~> 0.5)
|
49
49
|
rexml (3.2.5)
|
50
|
-
rubocop (1.30.
|
50
|
+
rubocop (1.30.1)
|
51
51
|
parallel (~> 1.10)
|
52
52
|
parser (>= 3.1.0.0)
|
53
53
|
rainbow (>= 2.2.2, < 4.0)
|
@@ -58,7 +58,7 @@ GEM
|
|
58
58
|
unicode-display_width (>= 1.4.0, < 3.0)
|
59
59
|
rubocop-ast (1.18.0)
|
60
60
|
parser (>= 3.1.1.0)
|
61
|
-
rubocop-minitest (0.20.
|
61
|
+
rubocop-minitest (0.20.1)
|
62
62
|
rubocop (>= 0.90, < 2.0)
|
63
63
|
rubocop-rake (0.6.0)
|
64
64
|
rubocop (~> 1.0)
|
@@ -67,14 +67,14 @@ GEM
|
|
67
67
|
rubocop-sorbet (0.6.8)
|
68
68
|
rubocop (>= 0.90.0)
|
69
69
|
ruby-progressbar (1.11.0)
|
70
|
-
sorbet (0.5.
|
71
|
-
sorbet-static (= 0.5.
|
72
|
-
sorbet-runtime (0.5.
|
73
|
-
sorbet-static (0.5.
|
74
|
-
sorbet-static (0.5.
|
75
|
-
sorbet-static-and-runtime (0.5.
|
76
|
-
sorbet (= 0.5.
|
77
|
-
sorbet-runtime (= 0.5.
|
70
|
+
sorbet (0.5.10092)
|
71
|
+
sorbet-static (= 0.5.10092)
|
72
|
+
sorbet-runtime (0.5.10092)
|
73
|
+
sorbet-static (0.5.10092-universal-darwin-21)
|
74
|
+
sorbet-static (0.5.10092-x86_64-linux)
|
75
|
+
sorbet-static-and-runtime (0.5.10092)
|
76
|
+
sorbet (= 0.5.10092)
|
77
|
+
sorbet-runtime (= 0.5.10092)
|
78
78
|
spoom (1.1.11)
|
79
79
|
sorbet (>= 0.5.9204)
|
80
80
|
sorbet-runtime (>= 0.5.9204)
|
@@ -111,7 +111,7 @@ DEPENDENCIES
|
|
111
111
|
minitest (~> 5.15)
|
112
112
|
minitest-reporters (~> 1.5)
|
113
113
|
rake (~> 13.0)
|
114
|
-
rubocop-minitest (~> 0.20.
|
114
|
+
rubocop-minitest (~> 0.20.1)
|
115
115
|
rubocop-rake (~> 0.6.0)
|
116
116
|
rubocop-shopify (~> 2.7)
|
117
117
|
rubocop-sorbet (~> 0.6)
|
data/README.md
CHANGED
@@ -50,7 +50,7 @@ To add a new expectations test runner for a new request handler:
|
|
50
50
|
require "expectations/expectations_test_runner"
|
51
51
|
|
52
52
|
class $HANDLERExpectationsTest < ExpectationsTestRunner
|
53
|
-
|
53
|
+
expectations_tests RubyLsp::Requests::$HANDLER, "$EXPECTATIONS_DIR"
|
54
54
|
end
|
55
55
|
```
|
56
56
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/exe/ruby-lsp
CHANGED
data/lib/ruby-lsp.rb
CHANGED
data/lib/ruby_lsp/document.rb
CHANGED
@@ -32,7 +32,13 @@ module RubyLsp
|
|
32
32
|
@source == other.source
|
33
33
|
end
|
34
34
|
|
35
|
-
sig
|
35
|
+
sig do
|
36
|
+
type_parameters(:T)
|
37
|
+
.params(
|
38
|
+
request_name: Symbol,
|
39
|
+
block: T.proc.params(document: Document).returns(T.type_parameter(:T))
|
40
|
+
).returns(T.type_parameter(:T))
|
41
|
+
end
|
36
42
|
def cache_fetch(request_name, &block)
|
37
43
|
cached = @cache[request_name]
|
38
44
|
return cached if cached
|
data/lib/ruby_lsp/handler.rb
CHANGED
@@ -28,9 +28,7 @@ module RubyLsp
|
|
28
28
|
sig { void }
|
29
29
|
def start
|
30
30
|
$stderr.puts "Starting Ruby LSP..."
|
31
|
-
@reader.read
|
32
|
-
with_telemetry(request) { handle(request) }
|
33
|
-
end
|
31
|
+
@reader.read { |request| handle(request) }
|
34
32
|
end
|
35
33
|
|
36
34
|
sig { params(blk: T.proc.bind(Handler).params(arg0: T.untyped).void).void }
|
@@ -52,11 +50,23 @@ module RubyLsp
|
|
52
50
|
|
53
51
|
sig { params(request: T::Hash[Symbol, T.untyped]).void }
|
54
52
|
def handle(request)
|
53
|
+
result = T.let(nil, T.untyped)
|
54
|
+
error = T.let(nil, T.nilable(StandardError))
|
55
55
|
handler = @handlers[request[:method]]
|
56
|
-
return unless handler
|
57
56
|
|
58
|
-
|
59
|
-
|
57
|
+
request_time = Benchmark.realtime do
|
58
|
+
if handler
|
59
|
+
begin
|
60
|
+
result = handler.call(request)
|
61
|
+
rescue StandardError => e
|
62
|
+
error = e
|
63
|
+
end
|
64
|
+
|
65
|
+
@writer.write(id: request[:id], result: result) unless result == VOID
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
@writer.write(method: "telemetry/event", params: telemetry_params(request, request_time, error))
|
60
70
|
end
|
61
71
|
|
62
72
|
sig { void }
|
@@ -114,14 +124,14 @@ module RubyLsp
|
|
114
124
|
sig { params(uri: String).returns(T::Array[LanguageServer::Protocol::Interface::DocumentSymbol]) }
|
115
125
|
def respond_with_document_symbol(uri)
|
116
126
|
store.cache_fetch(uri, :document_symbol) do |document|
|
117
|
-
RubyLsp::Requests::DocumentSymbol.
|
127
|
+
RubyLsp::Requests::DocumentSymbol.new(document).run
|
118
128
|
end
|
119
129
|
end
|
120
130
|
|
121
131
|
sig { params(uri: String).returns(T::Array[LanguageServer::Protocol::Interface::FoldingRange]) }
|
122
132
|
def respond_with_folding_ranges(uri)
|
123
133
|
store.cache_fetch(uri, :folding_ranges) do |document|
|
124
|
-
Requests::FoldingRanges.
|
134
|
+
Requests::FoldingRanges.new(document).run
|
125
135
|
end
|
126
136
|
end
|
127
137
|
|
@@ -129,11 +139,11 @@ module RubyLsp
|
|
129
139
|
params(
|
130
140
|
uri: String,
|
131
141
|
positions: T::Array[Document::PositionShape]
|
132
|
-
).returns(T::Array[RubyLsp::Requests::Support::SelectionRange])
|
142
|
+
).returns(T::Array[T.nilable(RubyLsp::Requests::Support::SelectionRange)])
|
133
143
|
end
|
134
144
|
def respond_with_selection_ranges(uri, positions)
|
135
145
|
ranges = store.cache_fetch(uri, :selection_ranges) do |document|
|
136
|
-
Requests::SelectionRanges.
|
146
|
+
Requests::SelectionRanges.new(document).run
|
137
147
|
end
|
138
148
|
|
139
149
|
# Per the selection range request spec (https://microsoft.github.io/language-server-protocol/specification#textDocument_selectionRange),
|
@@ -150,19 +160,22 @@ module RubyLsp
|
|
150
160
|
sig { params(uri: String).returns(LanguageServer::Protocol::Interface::SemanticTokens) }
|
151
161
|
def respond_with_semantic_highlighting(uri)
|
152
162
|
store.cache_fetch(uri, :semantic_highlighting) do |document|
|
153
|
-
|
163
|
+
T.cast(
|
164
|
+
Requests::SemanticHighlighting.new(document, encoder: Requests::Support::SemanticTokenEncoder.new).run,
|
165
|
+
LanguageServer::Protocol::Interface::SemanticTokens
|
166
|
+
)
|
154
167
|
end
|
155
168
|
end
|
156
169
|
|
157
|
-
sig { params(uri: String).returns(T::Array[LanguageServer::Protocol::Interface::TextEdit]) }
|
170
|
+
sig { params(uri: String).returns(T.nilable(T::Array[LanguageServer::Protocol::Interface::TextEdit])) }
|
158
171
|
def respond_with_formatting(uri)
|
159
|
-
Requests::Formatting.
|
172
|
+
Requests::Formatting.new(uri, store.get(uri)).run
|
160
173
|
end
|
161
174
|
|
162
175
|
sig { params(uri: String).void }
|
163
176
|
def send_diagnostics(uri)
|
164
177
|
response = store.cache_fetch(uri, :diagnostics) do |document|
|
165
|
-
Requests::Diagnostics.
|
178
|
+
Requests::Diagnostics.new(uri, document).run
|
166
179
|
end
|
167
180
|
|
168
181
|
@writer.write(
|
@@ -175,11 +188,11 @@ module RubyLsp
|
|
175
188
|
end
|
176
189
|
|
177
190
|
sig do
|
178
|
-
params(uri: String, range: T::Range[Integer]).returns(T::Array[LanguageServer::Protocol::Interface::
|
191
|
+
params(uri: String, range: T::Range[Integer]).returns(T::Array[LanguageServer::Protocol::Interface::CodeAction])
|
179
192
|
end
|
180
193
|
def respond_with_code_actions(uri, range)
|
181
194
|
store.cache_fetch(uri, :code_actions) do |document|
|
182
|
-
Requests::CodeActions.
|
195
|
+
Requests::CodeActions.new(uri, document, range).run
|
183
196
|
end
|
184
197
|
end
|
185
198
|
|
@@ -190,22 +203,7 @@ module RubyLsp
|
|
190
203
|
).returns(T::Array[LanguageServer::Protocol::Interface::DocumentHighlight])
|
191
204
|
end
|
192
205
|
def respond_with_document_highlight(uri, position)
|
193
|
-
Requests::DocumentHighlight.
|
194
|
-
end
|
195
|
-
|
196
|
-
sig { params(request: T::Hash[Symbol, T.untyped], block: T.proc.void).returns(T.untyped) }
|
197
|
-
def with_telemetry(request, &block)
|
198
|
-
result = T.let(nil, T.untyped)
|
199
|
-
error = T.let(nil, T.nilable(StandardError))
|
200
|
-
|
201
|
-
request_time = Benchmark.realtime do
|
202
|
-
result = block.call
|
203
|
-
rescue StandardError => e
|
204
|
-
error = e
|
205
|
-
end
|
206
|
-
|
207
|
-
@writer.write(method: "telemetry/event", params: telemetry_params(request, request_time, error))
|
208
|
-
result
|
206
|
+
Requests::DocumentHighlight.new(store.get(uri), position).run
|
209
207
|
end
|
210
208
|
|
211
209
|
sig do
|
@@ -1,24 +1,26 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Requests
|
6
6
|
# :nodoc:
|
7
7
|
class BaseRequest < SyntaxTree::Visitor
|
8
|
-
|
9
|
-
|
10
|
-
|
8
|
+
extend T::Sig
|
9
|
+
extend T::Helpers
|
10
|
+
|
11
|
+
abstract!
|
11
12
|
|
13
|
+
sig { params(document: Document).void }
|
12
14
|
def initialize(document)
|
13
15
|
@document = document
|
14
16
|
|
15
17
|
super()
|
16
18
|
end
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
end
|
20
|
+
sig { abstract.returns(Object) }
|
21
|
+
def run; end
|
21
22
|
|
23
|
+
sig { params(node: SyntaxTree::Node).returns(LanguageServer::Protocol::Interface::Range) }
|
22
24
|
def range_from_syntax_tree_node(node)
|
23
25
|
loc = node.location
|
24
26
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
@@ -14,23 +14,32 @@ module RubyLsp
|
|
14
14
|
# puts "Hello" # --> code action: quick fix indentation
|
15
15
|
# end
|
16
16
|
# ```
|
17
|
-
class CodeActions
|
18
|
-
|
19
|
-
new(uri, document, range).run
|
20
|
-
end
|
17
|
+
class CodeActions < BaseRequest
|
18
|
+
extend T::Sig
|
21
19
|
|
20
|
+
sig do
|
21
|
+
params(
|
22
|
+
uri: String,
|
23
|
+
document: Document,
|
24
|
+
range: T::Range[Integer]
|
25
|
+
).void
|
26
|
+
end
|
22
27
|
def initialize(uri, document, range)
|
23
|
-
|
28
|
+
super(document)
|
29
|
+
|
24
30
|
@uri = uri
|
25
31
|
@range = range
|
26
32
|
end
|
27
33
|
|
34
|
+
sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::CodeAction], Object)) }
|
28
35
|
def run
|
29
|
-
diagnostics = Diagnostics.
|
30
|
-
corrections = diagnostics.select
|
36
|
+
diagnostics = Diagnostics.new(@uri, @document).run
|
37
|
+
corrections = diagnostics.select do |diagnostic|
|
38
|
+
diagnostic.correctable? && T.cast(diagnostic, Support::RuboCopDiagnostic).in_range?(@range)
|
39
|
+
end
|
31
40
|
return [] if corrections.empty?
|
32
41
|
|
33
|
-
corrections.map!(&:to_lsp_code_action)
|
42
|
+
T.cast(corrections, T::Array[Support::RuboCopDiagnostic]).map!(&:to_lsp_code_action)
|
34
43
|
end
|
35
44
|
end
|
36
45
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
@@ -15,6 +15,16 @@ module RubyLsp
|
|
15
15
|
# end
|
16
16
|
# ```
|
17
17
|
class Diagnostics < RuboCopRequest
|
18
|
+
extend T::Sig
|
19
|
+
|
20
|
+
sig do
|
21
|
+
override.returns(
|
22
|
+
T.any(
|
23
|
+
T.all(T::Array[Support::RuboCopDiagnostic], Object),
|
24
|
+
T.all(T::Array[Support::SyntaxErrorDiagnostic], Object),
|
25
|
+
)
|
26
|
+
)
|
27
|
+
end
|
18
28
|
def run
|
19
29
|
return syntax_error_diagnostics if @document.syntax_errors?
|
20
30
|
|
@@ -23,12 +33,14 @@ module RubyLsp
|
|
23
33
|
@diagnostics
|
24
34
|
end
|
25
35
|
|
36
|
+
sig { params(_file: String, offenses: T::Array[RuboCop::Cop::Offense]).void }
|
26
37
|
def file_finished(_file, offenses)
|
27
38
|
@diagnostics = offenses.map { |offense| Support::RuboCopDiagnostic.new(offense, @uri) }
|
28
39
|
end
|
29
40
|
|
30
41
|
private
|
31
42
|
|
43
|
+
sig { returns(T::Array[Support::SyntaxErrorDiagnostic]) }
|
32
44
|
def syntax_error_diagnostics
|
33
45
|
@document.syntax_error_edits.map { |e| Support::SyntaxErrorDiagnostic.new(e) }
|
34
46
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
@@ -21,18 +21,28 @@ module RubyLsp
|
|
21
21
|
# end
|
22
22
|
# ```
|
23
23
|
class DocumentHighlight < BaseRequest
|
24
|
-
|
25
|
-
|
24
|
+
extend T::Sig
|
25
|
+
|
26
|
+
VarNodes = T.type_alias do
|
27
|
+
T.any(
|
28
|
+
SyntaxTree::GVar,
|
29
|
+
SyntaxTree::Ident,
|
30
|
+
SyntaxTree::IVar,
|
31
|
+
SyntaxTree::Const,
|
32
|
+
SyntaxTree::CVar
|
33
|
+
)
|
26
34
|
end
|
27
35
|
|
36
|
+
sig { params(document: Document, position: Document::PositionShape).void }
|
28
37
|
def initialize(document, position)
|
29
|
-
@highlights = []
|
38
|
+
@highlights = T.let([], T::Array[LanguageServer::Protocol::Interface::DocumentHighlight])
|
30
39
|
position = Document::Scanner.new(document.source).find_position(position)
|
31
|
-
@target = find(document.tree, position)
|
40
|
+
@target = T.let(find(document.tree, position), T.nilable(VarNodes))
|
32
41
|
|
33
42
|
super(document)
|
34
43
|
end
|
35
44
|
|
45
|
+
sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::DocumentHighlight], Object)) }
|
36
46
|
def run
|
37
47
|
# no @target means the target is not highlightable
|
38
48
|
return [] unless @target
|
@@ -41,6 +51,7 @@ module RubyLsp
|
|
41
51
|
@highlights
|
42
52
|
end
|
43
53
|
|
54
|
+
sig { params(node: SyntaxTree::VarField).void }
|
44
55
|
def visit_var_field(node)
|
45
56
|
if matches_target?(node.value)
|
46
57
|
add_highlight(
|
@@ -52,6 +63,7 @@ module RubyLsp
|
|
52
63
|
super
|
53
64
|
end
|
54
65
|
|
66
|
+
sig { params(node: SyntaxTree::VarRef).void }
|
55
67
|
def visit_var_ref(node)
|
56
68
|
if matches_target?(node.value)
|
57
69
|
add_highlight(
|
@@ -65,6 +77,7 @@ module RubyLsp
|
|
65
77
|
|
66
78
|
private
|
67
79
|
|
80
|
+
sig { params(node: SyntaxTree::Node, position: Integer).returns(T.nilable(VarNodes)) }
|
68
81
|
def find(node, position)
|
69
82
|
matched =
|
70
83
|
node.child_nodes.compact.bsearch do |child|
|
@@ -83,10 +96,12 @@ module RubyLsp
|
|
83
96
|
end
|
84
97
|
end
|
85
98
|
|
99
|
+
sig { params(node: SyntaxTree::Node).returns(T::Boolean) }
|
86
100
|
def matches_target?(node)
|
87
|
-
node.is_a?(@target.class) && node.value == @target.value
|
101
|
+
node.is_a?(@target.class) && T.cast(node, VarNodes).value == T.must(@target).value
|
88
102
|
end
|
89
103
|
|
104
|
+
sig { params(node: SyntaxTree::Node, kind: Integer).void }
|
90
105
|
def add_highlight(node, kind)
|
91
106
|
range = range_from_syntax_tree_node(node)
|
92
107
|
@highlights << LanguageServer::Protocol::Interface::DocumentHighlight.new(range: range, kind: kind)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
@@ -25,7 +25,9 @@ module RubyLsp
|
|
25
25
|
# end
|
26
26
|
# ```
|
27
27
|
class DocumentSymbol < BaseRequest
|
28
|
-
|
28
|
+
extend T::Sig
|
29
|
+
|
30
|
+
SYMBOL_KIND = T.let({
|
29
31
|
file: 1,
|
30
32
|
module: 2,
|
31
33
|
namespace: 3,
|
@@ -52,33 +54,43 @@ module RubyLsp
|
|
52
54
|
event: 24,
|
53
55
|
operator: 25,
|
54
56
|
typeparameter: 26,
|
55
|
-
}.freeze
|
57
|
+
}.freeze, T::Hash[Symbol, Integer])
|
56
58
|
|
57
|
-
ATTR_ACCESSORS = ["attr_reader", "attr_writer", "attr_accessor"].freeze
|
59
|
+
ATTR_ACCESSORS = T.let(["attr_reader", "attr_writer", "attr_accessor"].freeze, T::Array[String])
|
58
60
|
|
59
61
|
class SymbolHierarchyRoot
|
62
|
+
extend T::Sig
|
63
|
+
|
64
|
+
sig { returns(T::Array[LanguageServer::Protocol::Interface::DocumentSymbol]) }
|
60
65
|
attr_reader :children
|
61
66
|
|
67
|
+
sig { void }
|
62
68
|
def initialize
|
63
|
-
@children = []
|
69
|
+
@children = T.let([], T::Array[LanguageServer::Protocol::Interface::DocumentSymbol])
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
73
|
+
sig { params(document: Document).void }
|
67
74
|
def initialize(document)
|
68
75
|
super
|
69
76
|
|
70
|
-
@root = SymbolHierarchyRoot.new
|
71
|
-
@stack =
|
77
|
+
@root = T.let(SymbolHierarchyRoot.new, SymbolHierarchyRoot)
|
78
|
+
@stack = T.let(
|
79
|
+
[@root],
|
80
|
+
T::Array[T.any(SymbolHierarchyRoot, LanguageServer::Protocol::Interface::DocumentSymbol)]
|
81
|
+
)
|
72
82
|
end
|
73
83
|
|
84
|
+
sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::DocumentSymbol], Object)) }
|
74
85
|
def run
|
75
86
|
visit(@document.tree)
|
76
87
|
@root.children
|
77
88
|
end
|
78
89
|
|
90
|
+
sig { params(node: SyntaxTree::ClassDeclaration).void }
|
79
91
|
def visit_class(node)
|
80
92
|
symbol = create_document_symbol(
|
81
|
-
name: node
|
93
|
+
name: fully_qualified_name(node),
|
82
94
|
kind: :class,
|
83
95
|
range_node: node,
|
84
96
|
selection_range_node: node.constant
|
@@ -89,6 +101,7 @@ module RubyLsp
|
|
89
101
|
@stack.pop
|
90
102
|
end
|
91
103
|
|
104
|
+
sig { params(node: SyntaxTree::Command).void }
|
92
105
|
def visit_command(node)
|
93
106
|
return unless ATTR_ACCESSORS.include?(node.message.value)
|
94
107
|
|
@@ -104,6 +117,7 @@ module RubyLsp
|
|
104
117
|
end
|
105
118
|
end
|
106
119
|
|
120
|
+
sig { params(node: SyntaxTree::ConstPathField).void }
|
107
121
|
def visit_const_path_field(node)
|
108
122
|
create_document_symbol(
|
109
123
|
name: node.constant.value,
|
@@ -113,6 +127,7 @@ module RubyLsp
|
|
113
127
|
)
|
114
128
|
end
|
115
129
|
|
130
|
+
sig { params(node: SyntaxTree::Def).void }
|
116
131
|
def visit_def(node)
|
117
132
|
name = node.name.value
|
118
133
|
|
@@ -128,6 +143,7 @@ module RubyLsp
|
|
128
143
|
@stack.pop
|
129
144
|
end
|
130
145
|
|
146
|
+
sig { params(node: SyntaxTree::DefEndless).void }
|
131
147
|
def visit_def_endless(node)
|
132
148
|
name = node.name.value
|
133
149
|
|
@@ -143,6 +159,7 @@ module RubyLsp
|
|
143
159
|
@stack.pop
|
144
160
|
end
|
145
161
|
|
162
|
+
sig { params(node: SyntaxTree::Defs).void }
|
146
163
|
def visit_defs(node)
|
147
164
|
symbol = create_document_symbol(
|
148
165
|
name: "self.#{node.name.value}",
|
@@ -156,9 +173,10 @@ module RubyLsp
|
|
156
173
|
@stack.pop
|
157
174
|
end
|
158
175
|
|
176
|
+
sig { params(node: SyntaxTree::ModuleDeclaration).void }
|
159
177
|
def visit_module(node)
|
160
178
|
symbol = create_document_symbol(
|
161
|
-
name: node
|
179
|
+
name: fully_qualified_name(node),
|
162
180
|
kind: :module,
|
163
181
|
range_node: node,
|
164
182
|
selection_range_node: node.constant
|
@@ -169,6 +187,7 @@ module RubyLsp
|
|
169
187
|
@stack.pop
|
170
188
|
end
|
171
189
|
|
190
|
+
sig { params(node: SyntaxTree::TopConstField).void }
|
172
191
|
def visit_top_const_field(node)
|
173
192
|
create_document_symbol(
|
174
193
|
name: node.constant.value,
|
@@ -178,6 +197,7 @@ module RubyLsp
|
|
178
197
|
)
|
179
198
|
end
|
180
199
|
|
200
|
+
sig { params(node: SyntaxTree::VarField).void }
|
181
201
|
def visit_var_field(node)
|
182
202
|
kind = case node.value
|
183
203
|
when SyntaxTree::Const
|
@@ -198,6 +218,14 @@ module RubyLsp
|
|
198
218
|
|
199
219
|
private
|
200
220
|
|
221
|
+
sig do
|
222
|
+
params(
|
223
|
+
name: String,
|
224
|
+
kind: Symbol,
|
225
|
+
range_node: SyntaxTree::Node,
|
226
|
+
selection_range_node: SyntaxTree::Node
|
227
|
+
).returns(LanguageServer::Protocol::Interface::DocumentSymbol)
|
228
|
+
end
|
201
229
|
def create_document_symbol(name:, kind:, range_node:, selection_range_node:)
|
202
230
|
symbol = LanguageServer::Protocol::Interface::DocumentSymbol.new(
|
203
231
|
name: name,
|
@@ -207,10 +235,29 @@ module RubyLsp
|
|
207
235
|
children: [],
|
208
236
|
)
|
209
237
|
|
210
|
-
@stack.last.children << symbol
|
238
|
+
T.must(@stack.last).children << symbol
|
211
239
|
|
212
240
|
symbol
|
213
241
|
end
|
242
|
+
|
243
|
+
sig { params(node: T.any(SyntaxTree::ClassDeclaration, SyntaxTree::ModuleDeclaration)).returns(String) }
|
244
|
+
def fully_qualified_name(node)
|
245
|
+
constant = T.let(node.constant, SyntaxTree::Node)
|
246
|
+
name = +node.constant.constant.value
|
247
|
+
|
248
|
+
while constant.is_a?(SyntaxTree::ConstPathRef)
|
249
|
+
constant = constant.parent
|
250
|
+
|
251
|
+
case constant
|
252
|
+
when SyntaxTree::ConstPathRef
|
253
|
+
name.prepend("#{constant.constant.value}::")
|
254
|
+
when SyntaxTree::VarRef
|
255
|
+
name.prepend("#{constant.value.value}::")
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
name
|
260
|
+
end
|
214
261
|
end
|
215
262
|
end
|
216
263
|
end
|