ruby-lsp 0.0.4 → 0.1.0
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/.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
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
@@ -13,7 +13,9 @@ module RubyLsp
|
|
13
13
|
# end # <-- folding range end
|
14
14
|
# ```
|
15
15
|
class FoldingRanges < BaseRequest
|
16
|
-
|
16
|
+
extend T::Sig
|
17
|
+
|
18
|
+
SIMPLE_FOLDABLES = T.let([
|
17
19
|
SyntaxTree::ArrayLiteral,
|
18
20
|
SyntaxTree::BraceBlock,
|
19
21
|
SyntaxTree::Case,
|
@@ -30,24 +32,37 @@ module RubyLsp
|
|
30
32
|
SyntaxTree::Unless,
|
31
33
|
SyntaxTree::Until,
|
32
34
|
SyntaxTree::While,
|
33
|
-
].freeze
|
35
|
+
].freeze, T::Array[T.class_of(SyntaxTree::Node)])
|
34
36
|
|
35
|
-
NODES_WITH_STATEMENTS = [
|
37
|
+
NODES_WITH_STATEMENTS = T.let([
|
36
38
|
SyntaxTree::Else,
|
37
39
|
SyntaxTree::Elsif,
|
38
40
|
SyntaxTree::Ensure,
|
39
41
|
SyntaxTree::In,
|
40
42
|
SyntaxTree::Rescue,
|
41
43
|
SyntaxTree::When,
|
42
|
-
].freeze
|
44
|
+
].freeze, T::Array[T.class_of(SyntaxTree::Node)])
|
45
|
+
|
46
|
+
StatementNode = T.type_alias do
|
47
|
+
T.any(
|
48
|
+
SyntaxTree::Else,
|
49
|
+
SyntaxTree::Elsif,
|
50
|
+
SyntaxTree::Ensure,
|
51
|
+
SyntaxTree::In,
|
52
|
+
SyntaxTree::Rescue,
|
53
|
+
SyntaxTree::When,
|
54
|
+
)
|
55
|
+
end
|
43
56
|
|
57
|
+
sig { params(document: Document).void }
|
44
58
|
def initialize(document)
|
45
59
|
super
|
46
60
|
|
47
|
-
@ranges = []
|
48
|
-
@partial_range = nil
|
61
|
+
@ranges = T.let([], T::Array[LanguageServer::Protocol::Interface::FoldingRange])
|
62
|
+
@partial_range = T.let(nil, T.nilable(PartialRange))
|
49
63
|
end
|
50
64
|
|
65
|
+
sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::FoldingRange], Object)) }
|
51
66
|
def run
|
52
67
|
visit(@document.tree)
|
53
68
|
emit_partial_range
|
@@ -56,14 +71,15 @@ module RubyLsp
|
|
56
71
|
|
57
72
|
private
|
58
73
|
|
74
|
+
sig { params(node: T.nilable(SyntaxTree::Node)).void }
|
59
75
|
def visit(node)
|
60
76
|
return unless handle_partial_range(node)
|
61
77
|
|
62
78
|
case node
|
63
79
|
when *SIMPLE_FOLDABLES
|
64
|
-
add_node_range(node)
|
80
|
+
add_node_range(T.must(node))
|
65
81
|
when *NODES_WITH_STATEMENTS
|
66
|
-
add_statements_range(node, node.statements)
|
82
|
+
add_statements_range(T.must(node), T.cast(node, StatementNode).statements)
|
67
83
|
when SyntaxTree::Begin
|
68
84
|
add_statements_range(node, node.bodystmt.statements)
|
69
85
|
when SyntaxTree::Call, SyntaxTree::CommandCall
|
@@ -80,27 +96,38 @@ module RubyLsp
|
|
80
96
|
end
|
81
97
|
|
82
98
|
class PartialRange
|
83
|
-
|
99
|
+
extend T::Sig
|
84
100
|
|
101
|
+
sig { returns(String) }
|
102
|
+
attr_reader :kind
|
103
|
+
|
104
|
+
sig { returns(Integer) }
|
105
|
+
attr_reader :end_line
|
106
|
+
|
107
|
+
sig { params(node: SyntaxTree::Node, kind: String).returns(PartialRange) }
|
85
108
|
def self.from(node, kind)
|
86
109
|
new(node.location.start_line - 1, node.location.end_line - 1, kind)
|
87
110
|
end
|
88
111
|
|
112
|
+
sig { params(start_line: Integer, end_line: Integer, kind: String).void }
|
89
113
|
def initialize(start_line, end_line, kind)
|
90
114
|
@start_line = start_line
|
91
115
|
@end_line = end_line
|
92
116
|
@kind = kind
|
93
117
|
end
|
94
118
|
|
119
|
+
sig { params(node: SyntaxTree::Node).returns(PartialRange) }
|
95
120
|
def extend_to(node)
|
96
121
|
@end_line = node.location.end_line - 1
|
97
122
|
self
|
98
123
|
end
|
99
124
|
|
125
|
+
sig { params(node: SyntaxTree::Node).returns(T::Boolean) }
|
100
126
|
def new_section?(node)
|
101
127
|
node.is_a?(SyntaxTree::Comment) && @end_line + 1 != node.location.start_line - 1
|
102
128
|
end
|
103
129
|
|
130
|
+
sig { returns(LanguageServer::Protocol::Interface::FoldingRange) }
|
104
131
|
def to_range
|
105
132
|
LanguageServer::Protocol::Interface::FoldingRange.new(
|
106
133
|
start_line: @start_line,
|
@@ -110,6 +137,7 @@ module RubyLsp
|
|
110
137
|
end
|
111
138
|
end
|
112
139
|
|
140
|
+
sig { params(node: T.nilable(SyntaxTree::Node)).returns(T::Boolean) }
|
113
141
|
def handle_partial_range(node)
|
114
142
|
kind = partial_range_kind(node)
|
115
143
|
|
@@ -118,18 +146,20 @@ module RubyLsp
|
|
118
146
|
return true
|
119
147
|
end
|
120
148
|
|
149
|
+
target_node = T.must(node)
|
121
150
|
@partial_range = if @partial_range.nil?
|
122
|
-
PartialRange.from(
|
123
|
-
elsif @partial_range.kind != kind || @partial_range.new_section?(
|
151
|
+
PartialRange.from(target_node, kind)
|
152
|
+
elsif @partial_range.kind != kind || @partial_range.new_section?(target_node)
|
124
153
|
emit_partial_range
|
125
|
-
PartialRange.from(
|
154
|
+
PartialRange.from(target_node, kind)
|
126
155
|
else
|
127
|
-
@partial_range.extend_to(
|
156
|
+
@partial_range.extend_to(target_node)
|
128
157
|
end
|
129
158
|
|
130
159
|
false
|
131
160
|
end
|
132
161
|
|
162
|
+
sig { params(node: T.nilable(SyntaxTree::Node)).returns(T.nilable(String)) }
|
133
163
|
def partial_range_kind(node)
|
134
164
|
case node
|
135
165
|
when SyntaxTree::Comment
|
@@ -141,6 +171,7 @@ module RubyLsp
|
|
141
171
|
end
|
142
172
|
end
|
143
173
|
|
174
|
+
sig { void }
|
144
175
|
def emit_partial_range
|
145
176
|
return if @partial_range.nil?
|
146
177
|
|
@@ -148,6 +179,7 @@ module RubyLsp
|
|
148
179
|
@partial_range = nil
|
149
180
|
end
|
150
181
|
|
182
|
+
sig { params(node: T.any(SyntaxTree::Call, SyntaxTree::CommandCall)).void }
|
151
183
|
def add_call_range(node)
|
152
184
|
receiver = T.let(node.receiver, SyntaxTree::Node)
|
153
185
|
loop do
|
@@ -168,6 +200,7 @@ module RubyLsp
|
|
168
200
|
visit(node.arguments)
|
169
201
|
end
|
170
202
|
|
203
|
+
sig { params(node: T.any(SyntaxTree::Def, SyntaxTree::Defs)).void }
|
171
204
|
def add_def_range(node)
|
172
205
|
params_location = node.params.location
|
173
206
|
|
@@ -180,10 +213,12 @@ module RubyLsp
|
|
180
213
|
visit(node.bodystmt.statements)
|
181
214
|
end
|
182
215
|
|
216
|
+
sig { params(node: SyntaxTree::Node, statements: SyntaxTree::Statements).void }
|
183
217
|
def add_statements_range(node, statements)
|
184
218
|
add_lines_range(node.location.start_line, statements.location.end_line) unless statements.empty?
|
185
219
|
end
|
186
220
|
|
221
|
+
sig { params(node: SyntaxTree::StringConcat).void }
|
187
222
|
def add_string_concat(node)
|
188
223
|
left = T.let(node.left, SyntaxTree::Node)
|
189
224
|
left = left.left while left.is_a?(SyntaxTree::StringConcat)
|
@@ -191,14 +226,13 @@ module RubyLsp
|
|
191
226
|
add_lines_range(left.location.start_line, node.right.location.end_line)
|
192
227
|
end
|
193
228
|
|
229
|
+
sig { params(node: SyntaxTree::Node).void }
|
194
230
|
def add_node_range(node)
|
195
|
-
|
196
|
-
end
|
197
|
-
|
198
|
-
def add_location_range(location)
|
231
|
+
location = node.location
|
199
232
|
add_lines_range(location.start_line, location.end_line)
|
200
233
|
end
|
201
234
|
|
235
|
+
sig { params(start_line: Integer, end_line: Integer).void }
|
202
236
|
def add_lines_range(start_line, end_line)
|
203
237
|
return if start_line >= end_line
|
204
238
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
@@ -15,13 +15,17 @@ module RubyLsp
|
|
15
15
|
# end
|
16
16
|
# ```
|
17
17
|
class Formatting < RuboCopRequest
|
18
|
-
|
18
|
+
extend T::Sig
|
19
19
|
|
20
|
+
RUBOCOP_FLAGS = T.let((COMMON_RUBOCOP_FLAGS + ["--auto-correct"]).freeze, T::Array[String])
|
21
|
+
|
22
|
+
sig { params(uri: String, document: Document).void }
|
20
23
|
def initialize(uri, document)
|
21
24
|
super
|
22
|
-
@formatted_text = nil
|
25
|
+
@formatted_text = T.let(nil, T.nilable(String))
|
23
26
|
end
|
24
27
|
|
28
|
+
sig { override.returns(T.nilable(T.all(T::Array[LanguageServer::Protocol::Interface::TextEdit], Object))) }
|
25
29
|
def run
|
26
30
|
super
|
27
31
|
|
@@ -44,6 +48,7 @@ module RubyLsp
|
|
44
48
|
|
45
49
|
private
|
46
50
|
|
51
|
+
sig { returns(T::Array[String]) }
|
47
52
|
def rubocop_flags
|
48
53
|
RUBOCOP_FLAGS
|
49
54
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
require "rubocop"
|
@@ -8,23 +8,31 @@ module RubyLsp
|
|
8
8
|
module Requests
|
9
9
|
# :nodoc:
|
10
10
|
class RuboCopRequest < RuboCop::Runner
|
11
|
-
|
11
|
+
extend T::Sig
|
12
|
+
extend T::Helpers
|
13
|
+
|
14
|
+
abstract!
|
15
|
+
|
16
|
+
COMMON_RUBOCOP_FLAGS = T.let([
|
12
17
|
"--stderr", # Print any output to stderr so that our stdout does not get polluted
|
13
18
|
"--format",
|
14
19
|
"RuboCop::Formatter::BaseFormatter", # Suppress any output by using the base formatter
|
15
|
-
].freeze
|
20
|
+
].freeze, T::Array[String])
|
16
21
|
|
17
|
-
|
22
|
+
sig { returns(String) }
|
23
|
+
attr_reader :file
|
18
24
|
|
19
|
-
|
20
|
-
|
21
|
-
end
|
25
|
+
sig { returns(String) }
|
26
|
+
attr_reader :text
|
22
27
|
|
28
|
+
sig { params(uri: String, document: Document).void }
|
23
29
|
def initialize(uri, document)
|
24
|
-
@file = CGI.unescape(URI.parse(uri).path)
|
30
|
+
@file = T.let(CGI.unescape(URI.parse(uri).path), String)
|
25
31
|
@document = document
|
26
|
-
@text = document.source
|
32
|
+
@text = T.let(document.source, String)
|
27
33
|
@uri = uri
|
34
|
+
@options = T.let({}, T::Hash[Symbol, T.untyped])
|
35
|
+
@diagnostics = T.let([], T::Array[Support::RuboCopDiagnostic])
|
28
36
|
|
29
37
|
super(
|
30
38
|
::RuboCop::Options.new.parse(rubocop_flags).first,
|
@@ -32,6 +40,7 @@ module RubyLsp
|
|
32
40
|
)
|
33
41
|
end
|
34
42
|
|
43
|
+
sig { overridable.returns(Object) }
|
35
44
|
def run
|
36
45
|
# We communicate with Rubocop via stdin
|
37
46
|
@options[:stdin] = text
|
@@ -42,6 +51,7 @@ module RubyLsp
|
|
42
51
|
|
43
52
|
private
|
44
53
|
|
54
|
+
sig { returns(T::Array[String]) }
|
45
55
|
def rubocop_flags
|
46
56
|
COMMON_RUBOCOP_FLAGS
|
47
57
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
@@ -17,7 +17,9 @@ module RubyLsp
|
|
17
17
|
# end
|
18
18
|
# ```
|
19
19
|
class SelectionRanges < BaseRequest
|
20
|
-
|
20
|
+
extend T::Sig
|
21
|
+
|
22
|
+
NODES_THAT_CAN_BE_PARENTS = T.let([
|
21
23
|
SyntaxTree::Assign,
|
22
24
|
SyntaxTree::ArrayLiteral,
|
23
25
|
SyntaxTree::Begin,
|
@@ -54,15 +56,17 @@ module RubyLsp
|
|
54
56
|
SyntaxTree::VCall,
|
55
57
|
SyntaxTree::When,
|
56
58
|
SyntaxTree::While,
|
57
|
-
].freeze
|
59
|
+
].freeze, T::Array[T.class_of(SyntaxTree::Node)])
|
58
60
|
|
61
|
+
sig { params(document: Document).void }
|
59
62
|
def initialize(document)
|
60
63
|
super(document)
|
61
64
|
|
62
|
-
@ranges = []
|
63
|
-
@stack = []
|
65
|
+
@ranges = T.let([], T::Array[Support::SelectionRange])
|
66
|
+
@stack = T.let([], T::Array[Support::SelectionRange])
|
64
67
|
end
|
65
68
|
|
69
|
+
sig { override.returns(T.all(T::Array[Support::SelectionRange], Object)) }
|
66
70
|
def run
|
67
71
|
visit(@document.tree)
|
68
72
|
@ranges.reverse!
|
@@ -70,6 +74,7 @@ module RubyLsp
|
|
70
74
|
|
71
75
|
private
|
72
76
|
|
77
|
+
sig { params(node: T.nilable(SyntaxTree::Node)).void }
|
73
78
|
def visit(node)
|
74
79
|
return if node.nil?
|
75
80
|
|
@@ -83,6 +88,12 @@ module RubyLsp
|
|
83
88
|
@stack.pop if NODES_THAT_CAN_BE_PARENTS.include?(node.class)
|
84
89
|
end
|
85
90
|
|
91
|
+
sig do
|
92
|
+
params(
|
93
|
+
location: SyntaxTree::Location,
|
94
|
+
parent: T.nilable(Support::SelectionRange)
|
95
|
+
).returns(Support::SelectionRange)
|
96
|
+
end
|
86
97
|
def create_selection_range(location, parent = nil)
|
87
98
|
RubyLsp::Requests::Support::SelectionRange.new(
|
88
99
|
range: LanguageServer::Protocol::Interface::Range.new(
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
@@ -17,12 +17,15 @@ module RubyLsp
|
|
17
17
|
# end
|
18
18
|
# ```
|
19
19
|
class SemanticHighlighting < BaseRequest
|
20
|
-
|
20
|
+
extend T::Sig
|
21
|
+
|
22
|
+
TOKEN_TYPES = T.let([
|
21
23
|
:variable,
|
22
24
|
:method,
|
23
|
-
|
25
|
+
:namespace,
|
26
|
+
].freeze, T::Array[Symbol])
|
24
27
|
|
25
|
-
TOKEN_MODIFIERS = {
|
28
|
+
TOKEN_MODIFIERS = T.let({
|
26
29
|
declaration: 0,
|
27
30
|
definition: 1,
|
28
31
|
readonly: 2,
|
@@ -33,18 +36,32 @@ module RubyLsp
|
|
33
36
|
modification: 7,
|
34
37
|
documentation: 8,
|
35
38
|
default_library: 9,
|
36
|
-
}.freeze
|
39
|
+
}.freeze, T::Hash[Symbol, Integer])
|
37
40
|
|
38
|
-
SemanticToken
|
41
|
+
class SemanticToken < T::Struct
|
42
|
+
const :location, SyntaxTree::Location
|
43
|
+
const :length, Integer
|
44
|
+
const :type, Integer
|
45
|
+
const :modifier, T::Array[Integer]
|
46
|
+
end
|
39
47
|
|
48
|
+
sig { params(document: Document, encoder: T.nilable(Support::SemanticTokenEncoder)).void }
|
40
49
|
def initialize(document, encoder: nil)
|
41
50
|
super(document)
|
42
51
|
|
43
52
|
@encoder = encoder
|
44
|
-
@tokens = []
|
45
|
-
@tree = document.tree
|
53
|
+
@tokens = T.let([], T::Array[SemanticToken])
|
54
|
+
@tree = T.let(document.tree, SyntaxTree::Node)
|
46
55
|
end
|
47
56
|
|
57
|
+
sig do
|
58
|
+
override.returns(
|
59
|
+
T.any(
|
60
|
+
LanguageServer::Protocol::Interface::SemanticTokens,
|
61
|
+
T.all(T::Array[SemanticToken], Object),
|
62
|
+
)
|
63
|
+
)
|
64
|
+
end
|
48
65
|
def run
|
49
66
|
visit(@tree)
|
50
67
|
return @tokens unless @encoder
|
@@ -52,60 +69,118 @@ module RubyLsp
|
|
52
69
|
@encoder.encode(@tokens)
|
53
70
|
end
|
54
71
|
|
55
|
-
|
56
|
-
node.target.parts.each do |var_ref|
|
57
|
-
add_token(var_ref.value.location, :variable)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def visit_var_field(node)
|
62
|
-
case node.value
|
63
|
-
when SyntaxTree::Ident
|
64
|
-
add_token(node.value.location, :variable)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def visit_var_ref(node)
|
69
|
-
case node.value
|
70
|
-
when SyntaxTree::Ident
|
71
|
-
add_token(node.value.location, :variable)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
72
|
+
sig { params(node: SyntaxTree::ARefField).void }
|
75
73
|
def visit_a_ref_field(node)
|
76
74
|
add_token(node.collection.value.location, :variable)
|
77
75
|
end
|
78
76
|
|
77
|
+
sig { params(node: SyntaxTree::Call).void }
|
79
78
|
def visit_call(node)
|
80
79
|
visit(node.receiver)
|
81
80
|
add_token(node.message.location, :method)
|
82
81
|
visit(node.arguments)
|
83
82
|
end
|
84
83
|
|
84
|
+
sig { params(node: SyntaxTree::Command).void }
|
85
85
|
def visit_command(node)
|
86
86
|
add_token(node.message.location, :method)
|
87
87
|
visit(node.arguments)
|
88
88
|
end
|
89
89
|
|
90
|
+
sig { params(node: SyntaxTree::CommandCall).void }
|
90
91
|
def visit_command_call(node)
|
91
92
|
visit(node.receiver)
|
92
93
|
add_token(node.message.location, :method)
|
93
94
|
visit(node.arguments)
|
94
95
|
end
|
95
96
|
|
97
|
+
sig { params(node: SyntaxTree::Const).void }
|
98
|
+
def visit_const(node)
|
99
|
+
add_token(node.location, :namespace)
|
100
|
+
end
|
101
|
+
|
102
|
+
sig { params(node: SyntaxTree::Def).void }
|
103
|
+
def visit_def(node)
|
104
|
+
add_token(node.name.location, :method, [:declaration])
|
105
|
+
visit(node.params)
|
106
|
+
visit(node.bodystmt)
|
107
|
+
end
|
108
|
+
|
109
|
+
sig { params(node: SyntaxTree::DefEndless).void }
|
110
|
+
def visit_def_endless(node)
|
111
|
+
add_token(node.name.location, :method, [:declaration])
|
112
|
+
visit(node.paren)
|
113
|
+
visit(node.operator)
|
114
|
+
visit(node.statement)
|
115
|
+
end
|
116
|
+
|
117
|
+
sig { params(node: SyntaxTree::Defs).void }
|
118
|
+
def visit_defs(node)
|
119
|
+
visit(node.target)
|
120
|
+
visit(node.operator)
|
121
|
+
add_token(node.name.location, :method, [:declaration])
|
122
|
+
visit(node.params)
|
123
|
+
visit(node.bodystmt)
|
124
|
+
end
|
125
|
+
|
126
|
+
sig { params(node: SyntaxTree::FCall).void }
|
96
127
|
def visit_fcall(node)
|
97
128
|
add_token(node.value.location, :method)
|
98
129
|
visit(node.arguments)
|
99
130
|
end
|
100
131
|
|
132
|
+
sig { params(node: SyntaxTree::Kw).void }
|
133
|
+
def visit_kw(node)
|
134
|
+
case node.value
|
135
|
+
when "self"
|
136
|
+
add_token(node.location, :variable, [:default_library])
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
sig { params(node: SyntaxTree::MAssign).void }
|
141
|
+
def visit_m_assign(node)
|
142
|
+
node.target.parts.each do |var_ref|
|
143
|
+
add_token(var_ref.value.location, :variable)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
sig { params(node: SyntaxTree::VarField).void }
|
148
|
+
def visit_var_field(node)
|
149
|
+
case node.value
|
150
|
+
when SyntaxTree::Ident
|
151
|
+
add_token(node.value.location, :variable)
|
152
|
+
else
|
153
|
+
visit(node.value)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
sig { params(node: SyntaxTree::VarRef).void }
|
158
|
+
def visit_var_ref(node)
|
159
|
+
case node.value
|
160
|
+
when SyntaxTree::Ident
|
161
|
+
add_token(node.value.location, :variable)
|
162
|
+
else
|
163
|
+
visit(node.value)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
sig { params(node: SyntaxTree::VCall).void }
|
101
168
|
def visit_vcall(node)
|
102
169
|
add_token(node.value.location, :method)
|
103
170
|
end
|
104
171
|
|
172
|
+
sig { params(location: SyntaxTree::Location, type: Symbol, modifiers: T::Array[Symbol]).void }
|
105
173
|
def add_token(location, type, modifiers = [])
|
106
174
|
length = location.end_char - location.start_char
|
107
175
|
modifiers_indices = modifiers.filter_map { |modifier| TOKEN_MODIFIERS[modifier] }
|
108
|
-
@tokens.push(
|
176
|
+
@tokens.push(
|
177
|
+
SemanticToken.new(
|
178
|
+
location: location,
|
179
|
+
length: length,
|
180
|
+
type: T.must(TOKEN_TYPES.index(type)),
|
181
|
+
modifier: modifiers_indices
|
182
|
+
)
|
183
|
+
)
|
109
184
|
end
|
110
185
|
end
|
111
186
|
end
|
@@ -1,35 +1,45 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Requests
|
6
6
|
module Support
|
7
7
|
class RuboCopDiagnostic
|
8
|
-
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
RUBOCOP_TO_LSP_SEVERITY = T.let({
|
9
11
|
convention: LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION,
|
10
12
|
info: LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION,
|
11
13
|
refactor: LanguageServer::Protocol::Constant::DiagnosticSeverity::INFORMATION,
|
12
14
|
warning: LanguageServer::Protocol::Constant::DiagnosticSeverity::WARNING,
|
13
15
|
error: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
|
14
16
|
fatal: LanguageServer::Protocol::Constant::DiagnosticSeverity::ERROR,
|
15
|
-
}.freeze
|
17
|
+
}.freeze, T::Hash[Symbol, Integer])
|
16
18
|
|
19
|
+
sig { returns(T::Array[LanguageServer::Protocol::Interface::TextEdit]) }
|
17
20
|
attr_reader :replacements
|
18
21
|
|
22
|
+
sig { params(offense: RuboCop::Cop::Offense, uri: String).void }
|
19
23
|
def initialize(offense, uri)
|
20
24
|
@offense = offense
|
21
25
|
@uri = uri
|
22
|
-
@replacements =
|
26
|
+
@replacements = T.let(
|
27
|
+
offense.correctable? ? offense_replacements : [],
|
28
|
+
T::Array[LanguageServer::Protocol::Interface::TextEdit]
|
29
|
+
)
|
23
30
|
end
|
24
31
|
|
32
|
+
sig { returns(T::Boolean) }
|
25
33
|
def correctable?
|
26
34
|
@offense.correctable?
|
27
35
|
end
|
28
36
|
|
37
|
+
sig { params(range: T::Range[Integer]).returns(T::Boolean) }
|
29
38
|
def in_range?(range)
|
30
39
|
range.cover?(@offense.line - 1)
|
31
40
|
end
|
32
41
|
|
42
|
+
sig { returns(LanguageServer::Protocol::Interface::CodeAction) }
|
33
43
|
def to_lsp_code_action
|
34
44
|
LanguageServer::Protocol::Interface::CodeAction.new(
|
35
45
|
title: "Autocorrect #{@offense.cop_name}",
|
@@ -49,6 +59,7 @@ module RubyLsp
|
|
49
59
|
)
|
50
60
|
end
|
51
61
|
|
62
|
+
sig { returns(LanguageServer::Protocol::Interface::Diagnostic) }
|
52
63
|
def to_lsp_diagnostic
|
53
64
|
LanguageServer::Protocol::Interface::Diagnostic.new(
|
54
65
|
message: @offense.message,
|
@@ -70,6 +81,7 @@ module RubyLsp
|
|
70
81
|
|
71
82
|
private
|
72
83
|
|
84
|
+
sig { returns(T::Array[LanguageServer::Protocol::Interface::TextEdit]) }
|
73
85
|
def offense_replacements
|
74
86
|
@offense.corrector.as_replacements.map do |range, replacement|
|
75
87
|
LanguageServer::Protocol::Interface::TextEdit.new(
|
@@ -1,10 +1,13 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Requests
|
6
6
|
module Support
|
7
7
|
class SelectionRange < LanguageServer::Protocol::Interface::SelectionRange
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { params(position: Document::PositionShape).returns(T::Boolean) }
|
8
11
|
def cover?(position)
|
9
12
|
line_range = (range.start.line..range.end.line)
|
10
13
|
character_range = (range.start.character..range.end.character)
|
@@ -1,15 +1,23 @@
|
|
1
|
-
# typed:
|
1
|
+
# typed: strict
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
module RubyLsp
|
5
5
|
module Requests
|
6
6
|
module Support
|
7
7
|
class SemanticTokenEncoder
|
8
|
+
extend T::Sig
|
9
|
+
|
10
|
+
sig { void }
|
8
11
|
def initialize
|
9
|
-
@current_row = 0
|
10
|
-
@current_column = 0
|
12
|
+
@current_row = T.let(0, Integer)
|
13
|
+
@current_column = T.let(0, Integer)
|
11
14
|
end
|
12
15
|
|
16
|
+
sig do
|
17
|
+
params(
|
18
|
+
tokens: T::Array[SemanticHighlighting::SemanticToken]
|
19
|
+
).returns(LanguageServer::Protocol::Interface::SemanticTokens)
|
20
|
+
end
|
13
21
|
def encode(tokens)
|
14
22
|
delta = tokens
|
15
23
|
.sort_by do |token|
|
@@ -31,6 +39,7 @@ module RubyLsp
|
|
31
39
|
|
32
40
|
# For more information on how each number is calculated, read:
|
33
41
|
# https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens
|
42
|
+
sig { params(token: SemanticHighlighting::SemanticToken).returns(T::Array[Integer]) }
|
34
43
|
def compute_delta(token)
|
35
44
|
row = token.location.start_line - 1
|
36
45
|
column = token.location.start_column
|
@@ -49,6 +58,7 @@ module RubyLsp
|
|
49
58
|
# For example, [:default_library] will be encoded as
|
50
59
|
# 0b1000000000, as :default_library is the 10th bit according
|
51
60
|
# to the token modifiers index map.
|
61
|
+
sig { params(modifiers: T::Array[Integer]).returns(Integer) }
|
52
62
|
def encode_modifiers(modifiers)
|
53
63
|
modifiers.inject(0) do |encoded_modifiers, modifier|
|
54
64
|
encoded_modifiers | (1 << modifier)
|