ruby-lsp 0.0.3 → 0.2.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/.github/workflows/ci.yml +6 -0
- data/.rubocop.yml +25 -0
- data/CHANGELOG.md +35 -0
- data/Gemfile +10 -6
- data/Gemfile.lock +63 -16
- data/README.md +41 -0
- data/Rakefile +8 -1
- data/VERSION +1 -1
- data/bin/console +19 -0
- data/bin/tapioca +29 -0
- data/dev.yml +3 -0
- data/exe/ruby-lsp +19 -4
- data/lib/ruby-lsp.rb +2 -1
- data/lib/ruby_lsp/cli.rb +13 -5
- data/lib/ruby_lsp/document.rb +43 -14
- data/lib/ruby_lsp/handler.rb +107 -37
- data/lib/ruby_lsp/internal.rb +7 -0
- data/lib/ruby_lsp/requests/base_request.rb +18 -5
- data/lib/ruby_lsp/requests/code_actions.rb +20 -8
- data/lib/ruby_lsp/requests/diagnostics.rb +25 -7
- data/lib/ruby_lsp/requests/document_highlight.rb +113 -0
- data/lib/ruby_lsp/requests/document_symbol.rb +56 -16
- data/lib/ruby_lsp/requests/folding_ranges.rb +70 -34
- data/lib/ruby_lsp/requests/formatting.rb +24 -14
- data/lib/ruby_lsp/requests/selection_ranges.rb +18 -4
- data/lib/ruby_lsp/requests/semantic_highlighting.rb +187 -34
- data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +16 -3
- data/lib/ruby_lsp/requests/support/rubocop_diagnostics_runner.rb +61 -0
- data/lib/ruby_lsp/requests/support/rubocop_formatting_runner.rb +50 -0
- data/lib/ruby_lsp/requests/support/selection_range.rb +4 -0
- data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +24 -3
- data/lib/ruby_lsp/requests/support/syntax_error_diagnostic.rb +6 -0
- data/lib/ruby_lsp/requests.rb +13 -1
- data/lib/ruby_lsp/store.rb +20 -3
- data/rakelib/check_docs.rake +34 -6
- data/ruby-lsp.gemspec +7 -5
- data/sorbet/config +4 -0
- data/sorbet/rbi/.rubocop.yml +8 -0
- data/sorbet/rbi/gems/ansi@1.5.0.rbi +338 -0
- data/sorbet/rbi/gems/ast@2.4.2.rbi +522 -0
- data/sorbet/rbi/gems/builder@3.2.4.rbi +418 -0
- data/sorbet/rbi/gems/coderay@1.1.3.rbi +8 -0
- data/sorbet/rbi/gems/debug@1.5.0.rbi +1273 -0
- data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +867 -0
- data/sorbet/rbi/gems/io-console@0.5.11.rbi +8 -0
- data/sorbet/rbi/gems/irb@1.4.1.rbi +376 -0
- data/sorbet/rbi/gems/language_server-protocol@3.16.0.3.rbi +7325 -0
- data/sorbet/rbi/gems/method_source@1.0.0.rbi +8 -0
- data/sorbet/rbi/gems/minitest-reporters@1.5.0.rbi +612 -0
- data/sorbet/rbi/gems/minitest@5.15.0.rbi +994 -0
- data/sorbet/rbi/gems/parallel@1.22.1.rbi +163 -0
- data/sorbet/rbi/gems/parser@3.1.2.0.rbi +3968 -0
- data/sorbet/rbi/gems/prettier_print@0.1.0.rbi +734 -0
- data/sorbet/rbi/gems/pry@0.14.1.rbi +8 -0
- data/sorbet/rbi/gems/rainbow@3.1.1.rbi +227 -0
- data/sorbet/rbi/gems/rake@13.0.6.rbi +1853 -0
- data/sorbet/rbi/gems/rbi@0.0.14.rbi +2337 -0
- data/sorbet/rbi/gems/regexp_parser@2.5.0.rbi +1854 -0
- data/sorbet/rbi/gems/reline@0.3.1.rbi +1274 -0
- data/sorbet/rbi/gems/rexml@3.2.5.rbi +3852 -0
- data/sorbet/rbi/gems/rubocop-ast@1.18.0.rbi +4180 -0
- data/sorbet/rbi/gems/rubocop-minitest@0.20.0.rbi +1369 -0
- data/sorbet/rbi/gems/rubocop-rake@0.6.0.rbi +246 -0
- data/sorbet/rbi/gems/rubocop-shopify@2.6.0.rbi +8 -0
- data/sorbet/rbi/gems/rubocop-sorbet@0.6.8.rbi +652 -0
- data/sorbet/rbi/gems/rubocop@1.30.0.rbi +36729 -0
- data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +732 -0
- data/sorbet/rbi/gems/spoom@1.1.11.rbi +1600 -0
- data/sorbet/rbi/gems/syntax_tree@2.7.1.rbi +6777 -0
- data/sorbet/rbi/gems/tapioca@0.8.1.rbi +1972 -0
- data/sorbet/rbi/gems/thor@1.2.1.rbi +2921 -0
- data/sorbet/rbi/gems/unicode-display_width@2.1.0.rbi +27 -0
- data/sorbet/rbi/gems/unparser@0.6.5.rbi +2789 -0
- data/sorbet/rbi/gems/webrick@1.7.0.rbi +1779 -0
- data/sorbet/rbi/gems/yard-sorbet@0.6.1.rbi +289 -0
- data/sorbet/rbi/gems/yard@0.9.27.rbi +13048 -0
- data/sorbet/rbi/shims/fiddle.rbi +4 -0
- data/sorbet/rbi/shims/hash.rbi +6 -0
- data/sorbet/rbi/shims/rdoc.rbi +4 -0
- data/sorbet/tapioca/config.yml +13 -0
- data/sorbet/tapioca/require.rb +7 -0
- metadata +62 -13
- data/lib/ruby_lsp/requests/rubocop_request.rb +0 -49
- data/shipit.production.yml +0 -1
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
# typed: strict
|
|
1
2
|
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module RubyLsp
|
|
4
5
|
module Requests
|
|
6
|
+
# 
|
|
7
|
+
#
|
|
5
8
|
# The [document
|
|
6
9
|
# symbol](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentSymbol) request
|
|
7
10
|
# informs the editor of all the important symbols, such as classes, variables, and methods, defined in a file. With
|
|
@@ -24,7 +27,9 @@ module RubyLsp
|
|
|
24
27
|
# end
|
|
25
28
|
# ```
|
|
26
29
|
class DocumentSymbol < BaseRequest
|
|
27
|
-
|
|
30
|
+
extend T::Sig
|
|
31
|
+
|
|
32
|
+
SYMBOL_KIND = T.let({
|
|
28
33
|
file: 1,
|
|
29
34
|
module: 2,
|
|
30
35
|
namespace: 3,
|
|
@@ -51,33 +56,43 @@ module RubyLsp
|
|
|
51
56
|
event: 24,
|
|
52
57
|
operator: 25,
|
|
53
58
|
typeparameter: 26,
|
|
54
|
-
}.freeze
|
|
59
|
+
}.freeze, T::Hash[Symbol, Integer])
|
|
55
60
|
|
|
56
|
-
ATTR_ACCESSORS = ["attr_reader", "attr_writer", "attr_accessor"].freeze
|
|
61
|
+
ATTR_ACCESSORS = T.let(["attr_reader", "attr_writer", "attr_accessor"].freeze, T::Array[String])
|
|
57
62
|
|
|
58
63
|
class SymbolHierarchyRoot
|
|
64
|
+
extend T::Sig
|
|
65
|
+
|
|
66
|
+
sig { returns(T::Array[LanguageServer::Protocol::Interface::DocumentSymbol]) }
|
|
59
67
|
attr_reader :children
|
|
60
68
|
|
|
69
|
+
sig { void }
|
|
61
70
|
def initialize
|
|
62
|
-
@children = []
|
|
71
|
+
@children = T.let([], T::Array[LanguageServer::Protocol::Interface::DocumentSymbol])
|
|
63
72
|
end
|
|
64
73
|
end
|
|
65
74
|
|
|
75
|
+
sig { params(document: Document).void }
|
|
66
76
|
def initialize(document)
|
|
67
77
|
super
|
|
68
78
|
|
|
69
|
-
@root = SymbolHierarchyRoot.new
|
|
70
|
-
@stack =
|
|
79
|
+
@root = T.let(SymbolHierarchyRoot.new, SymbolHierarchyRoot)
|
|
80
|
+
@stack = T.let(
|
|
81
|
+
[@root],
|
|
82
|
+
T::Array[T.any(SymbolHierarchyRoot, LanguageServer::Protocol::Interface::DocumentSymbol)]
|
|
83
|
+
)
|
|
71
84
|
end
|
|
72
85
|
|
|
86
|
+
sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::DocumentSymbol], Object)) }
|
|
73
87
|
def run
|
|
74
88
|
visit(@document.tree)
|
|
75
89
|
@root.children
|
|
76
90
|
end
|
|
77
91
|
|
|
92
|
+
sig { params(node: SyntaxTree::ClassDeclaration).void }
|
|
78
93
|
def visit_class(node)
|
|
79
94
|
symbol = create_document_symbol(
|
|
80
|
-
name: node
|
|
95
|
+
name: fully_qualified_name(node),
|
|
81
96
|
kind: :class,
|
|
82
97
|
range_node: node,
|
|
83
98
|
selection_range_node: node.constant
|
|
@@ -88,6 +103,7 @@ module RubyLsp
|
|
|
88
103
|
@stack.pop
|
|
89
104
|
end
|
|
90
105
|
|
|
106
|
+
sig { params(node: SyntaxTree::Command).void }
|
|
91
107
|
def visit_command(node)
|
|
92
108
|
return unless ATTR_ACCESSORS.include?(node.message.value)
|
|
93
109
|
|
|
@@ -103,6 +119,7 @@ module RubyLsp
|
|
|
103
119
|
end
|
|
104
120
|
end
|
|
105
121
|
|
|
122
|
+
sig { params(node: SyntaxTree::ConstPathField).void }
|
|
106
123
|
def visit_const_path_field(node)
|
|
107
124
|
create_document_symbol(
|
|
108
125
|
name: node.constant.value,
|
|
@@ -112,6 +129,7 @@ module RubyLsp
|
|
|
112
129
|
)
|
|
113
130
|
end
|
|
114
131
|
|
|
132
|
+
sig { params(node: SyntaxTree::Def).void }
|
|
115
133
|
def visit_def(node)
|
|
116
134
|
name = node.name.value
|
|
117
135
|
|
|
@@ -127,6 +145,7 @@ module RubyLsp
|
|
|
127
145
|
@stack.pop
|
|
128
146
|
end
|
|
129
147
|
|
|
148
|
+
sig { params(node: SyntaxTree::DefEndless).void }
|
|
130
149
|
def visit_def_endless(node)
|
|
131
150
|
name = node.name.value
|
|
132
151
|
|
|
@@ -142,6 +161,7 @@ module RubyLsp
|
|
|
142
161
|
@stack.pop
|
|
143
162
|
end
|
|
144
163
|
|
|
164
|
+
sig { params(node: SyntaxTree::Defs).void }
|
|
145
165
|
def visit_defs(node)
|
|
146
166
|
symbol = create_document_symbol(
|
|
147
167
|
name: "self.#{node.name.value}",
|
|
@@ -155,9 +175,10 @@ module RubyLsp
|
|
|
155
175
|
@stack.pop
|
|
156
176
|
end
|
|
157
177
|
|
|
178
|
+
sig { params(node: SyntaxTree::ModuleDeclaration).void }
|
|
158
179
|
def visit_module(node)
|
|
159
180
|
symbol = create_document_symbol(
|
|
160
|
-
name: node
|
|
181
|
+
name: fully_qualified_name(node),
|
|
161
182
|
kind: :module,
|
|
162
183
|
range_node: node,
|
|
163
184
|
selection_range_node: node.constant
|
|
@@ -168,6 +189,7 @@ module RubyLsp
|
|
|
168
189
|
@stack.pop
|
|
169
190
|
end
|
|
170
191
|
|
|
192
|
+
sig { params(node: SyntaxTree::TopConstField).void }
|
|
171
193
|
def visit_top_const_field(node)
|
|
172
194
|
create_document_symbol(
|
|
173
195
|
name: node.constant.value,
|
|
@@ -177,6 +199,7 @@ module RubyLsp
|
|
|
177
199
|
)
|
|
178
200
|
end
|
|
179
201
|
|
|
202
|
+
sig { params(node: SyntaxTree::VarField).void }
|
|
180
203
|
def visit_var_field(node)
|
|
181
204
|
kind = case node.value
|
|
182
205
|
when SyntaxTree::Const
|
|
@@ -197,6 +220,14 @@ module RubyLsp
|
|
|
197
220
|
|
|
198
221
|
private
|
|
199
222
|
|
|
223
|
+
sig do
|
|
224
|
+
params(
|
|
225
|
+
name: String,
|
|
226
|
+
kind: Symbol,
|
|
227
|
+
range_node: SyntaxTree::Node,
|
|
228
|
+
selection_range_node: SyntaxTree::Node
|
|
229
|
+
).returns(LanguageServer::Protocol::Interface::DocumentSymbol)
|
|
230
|
+
end
|
|
200
231
|
def create_document_symbol(name:, kind:, range_node:, selection_range_node:)
|
|
201
232
|
symbol = LanguageServer::Protocol::Interface::DocumentSymbol.new(
|
|
202
233
|
name: name,
|
|
@@ -206,19 +237,28 @@ module RubyLsp
|
|
|
206
237
|
children: [],
|
|
207
238
|
)
|
|
208
239
|
|
|
209
|
-
@stack.last.children << symbol
|
|
240
|
+
T.must(@stack.last).children << symbol
|
|
210
241
|
|
|
211
242
|
symbol
|
|
212
243
|
end
|
|
213
244
|
|
|
214
|
-
|
|
215
|
-
|
|
245
|
+
sig { params(node: T.any(SyntaxTree::ClassDeclaration, SyntaxTree::ModuleDeclaration)).returns(String) }
|
|
246
|
+
def fully_qualified_name(node)
|
|
247
|
+
constant = T.let(node.constant, SyntaxTree::Node)
|
|
248
|
+
name = +node.constant.constant.value
|
|
216
249
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
250
|
+
while constant.is_a?(SyntaxTree::ConstPathRef)
|
|
251
|
+
constant = constant.parent
|
|
252
|
+
|
|
253
|
+
case constant
|
|
254
|
+
when SyntaxTree::ConstPathRef
|
|
255
|
+
name.prepend("#{constant.constant.value}::")
|
|
256
|
+
when SyntaxTree::VarRef
|
|
257
|
+
name.prepend("#{constant.value.value}::")
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
name
|
|
222
262
|
end
|
|
223
263
|
end
|
|
224
264
|
end
|
|
@@ -1,18 +1,24 @@
|
|
|
1
|
+
# typed: strict
|
|
1
2
|
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module RubyLsp
|
|
4
5
|
module Requests
|
|
6
|
+
# 
|
|
7
|
+
#
|
|
5
8
|
# The [folding ranges](https://microsoft.github.io/language-server-protocol/specification#textDocument_foldingRange)
|
|
6
|
-
# request informs the editor of the ranges where code can be folded.
|
|
9
|
+
# request informs the editor of the ranges where and how code can be folded.
|
|
7
10
|
#
|
|
8
11
|
# # Example
|
|
12
|
+
#
|
|
9
13
|
# ```ruby
|
|
10
14
|
# def say_hello # <-- folding range start
|
|
11
15
|
# puts "Hello"
|
|
12
16
|
# end # <-- folding range end
|
|
13
17
|
# ```
|
|
14
18
|
class FoldingRanges < BaseRequest
|
|
15
|
-
|
|
19
|
+
extend T::Sig
|
|
20
|
+
|
|
21
|
+
SIMPLE_FOLDABLES = T.let([
|
|
16
22
|
SyntaxTree::ArrayLiteral,
|
|
17
23
|
SyntaxTree::BraceBlock,
|
|
18
24
|
SyntaxTree::Case,
|
|
@@ -29,24 +35,36 @@ module RubyLsp
|
|
|
29
35
|
SyntaxTree::Unless,
|
|
30
36
|
SyntaxTree::Until,
|
|
31
37
|
SyntaxTree::While,
|
|
32
|
-
].freeze
|
|
33
|
-
|
|
34
|
-
NODES_WITH_STATEMENTS = [
|
|
35
38
|
SyntaxTree::Else,
|
|
36
|
-
SyntaxTree::Elsif,
|
|
37
39
|
SyntaxTree::Ensure,
|
|
40
|
+
SyntaxTree::Begin,
|
|
41
|
+
].freeze, T::Array[T.class_of(SyntaxTree::Node)])
|
|
42
|
+
|
|
43
|
+
NODES_WITH_STATEMENTS = T.let([
|
|
44
|
+
SyntaxTree::Elsif,
|
|
38
45
|
SyntaxTree::In,
|
|
39
46
|
SyntaxTree::Rescue,
|
|
40
47
|
SyntaxTree::When,
|
|
41
|
-
].freeze
|
|
48
|
+
].freeze, T::Array[T.class_of(SyntaxTree::Node)])
|
|
49
|
+
|
|
50
|
+
StatementNode = T.type_alias do
|
|
51
|
+
T.any(
|
|
52
|
+
SyntaxTree::Elsif,
|
|
53
|
+
SyntaxTree::In,
|
|
54
|
+
SyntaxTree::Rescue,
|
|
55
|
+
SyntaxTree::When,
|
|
56
|
+
)
|
|
57
|
+
end
|
|
42
58
|
|
|
59
|
+
sig { params(document: Document).void }
|
|
43
60
|
def initialize(document)
|
|
44
61
|
super
|
|
45
62
|
|
|
46
|
-
@ranges = []
|
|
47
|
-
@partial_range = nil
|
|
63
|
+
@ranges = T.let([], T::Array[LanguageServer::Protocol::Interface::FoldingRange])
|
|
64
|
+
@partial_range = T.let(nil, T.nilable(PartialRange))
|
|
48
65
|
end
|
|
49
66
|
|
|
67
|
+
sig { override.returns(T.all(T::Array[LanguageServer::Protocol::Interface::FoldingRange], Object)) }
|
|
50
68
|
def run
|
|
51
69
|
visit(@document.tree)
|
|
52
70
|
emit_partial_range
|
|
@@ -55,16 +73,16 @@ module RubyLsp
|
|
|
55
73
|
|
|
56
74
|
private
|
|
57
75
|
|
|
76
|
+
sig { params(node: T.nilable(SyntaxTree::Node)).void }
|
|
58
77
|
def visit(node)
|
|
59
78
|
return unless handle_partial_range(node)
|
|
60
79
|
|
|
61
80
|
case node
|
|
62
81
|
when *SIMPLE_FOLDABLES
|
|
63
|
-
|
|
82
|
+
location = T.must(node).location
|
|
83
|
+
add_lines_range(location.start_line, location.end_line - 1)
|
|
64
84
|
when *NODES_WITH_STATEMENTS
|
|
65
|
-
add_statements_range(node, node.statements)
|
|
66
|
-
when SyntaxTree::Begin
|
|
67
|
-
add_statements_range(node, node.bodystmt.statements)
|
|
85
|
+
add_statements_range(T.must(node), T.cast(node, StatementNode).statements)
|
|
68
86
|
when SyntaxTree::Call, SyntaxTree::CommandCall
|
|
69
87
|
add_call_range(node)
|
|
70
88
|
return
|
|
@@ -79,27 +97,38 @@ module RubyLsp
|
|
|
79
97
|
end
|
|
80
98
|
|
|
81
99
|
class PartialRange
|
|
82
|
-
|
|
100
|
+
extend T::Sig
|
|
101
|
+
|
|
102
|
+
sig { returns(String) }
|
|
103
|
+
attr_reader :kind
|
|
104
|
+
|
|
105
|
+
sig { returns(Integer) }
|
|
106
|
+
attr_reader :end_line
|
|
83
107
|
|
|
108
|
+
sig { params(node: SyntaxTree::Node, kind: String).returns(PartialRange) }
|
|
84
109
|
def self.from(node, kind)
|
|
85
110
|
new(node.location.start_line - 1, node.location.end_line - 1, kind)
|
|
86
111
|
end
|
|
87
112
|
|
|
113
|
+
sig { params(start_line: Integer, end_line: Integer, kind: String).void }
|
|
88
114
|
def initialize(start_line, end_line, kind)
|
|
89
115
|
@start_line = start_line
|
|
90
116
|
@end_line = end_line
|
|
91
117
|
@kind = kind
|
|
92
118
|
end
|
|
93
119
|
|
|
120
|
+
sig { params(node: SyntaxTree::Node).returns(PartialRange) }
|
|
94
121
|
def extend_to(node)
|
|
95
122
|
@end_line = node.location.end_line - 1
|
|
96
123
|
self
|
|
97
124
|
end
|
|
98
125
|
|
|
126
|
+
sig { params(node: SyntaxTree::Node).returns(T::Boolean) }
|
|
99
127
|
def new_section?(node)
|
|
100
128
|
node.is_a?(SyntaxTree::Comment) && @end_line + 1 != node.location.start_line - 1
|
|
101
129
|
end
|
|
102
130
|
|
|
131
|
+
sig { returns(LanguageServer::Protocol::Interface::FoldingRange) }
|
|
103
132
|
def to_range
|
|
104
133
|
LanguageServer::Protocol::Interface::FoldingRange.new(
|
|
105
134
|
start_line: @start_line,
|
|
@@ -107,8 +136,14 @@ module RubyLsp
|
|
|
107
136
|
kind: @kind
|
|
108
137
|
)
|
|
109
138
|
end
|
|
139
|
+
|
|
140
|
+
sig { returns(T::Boolean) }
|
|
141
|
+
def multiline?
|
|
142
|
+
@end_line > @start_line
|
|
143
|
+
end
|
|
110
144
|
end
|
|
111
145
|
|
|
146
|
+
sig { params(node: T.nilable(SyntaxTree::Node)).returns(T::Boolean) }
|
|
112
147
|
def handle_partial_range(node)
|
|
113
148
|
kind = partial_range_kind(node)
|
|
114
149
|
|
|
@@ -117,18 +152,20 @@ module RubyLsp
|
|
|
117
152
|
return true
|
|
118
153
|
end
|
|
119
154
|
|
|
155
|
+
target_node = T.must(node)
|
|
120
156
|
@partial_range = if @partial_range.nil?
|
|
121
|
-
PartialRange.from(
|
|
122
|
-
elsif @partial_range.kind != kind || @partial_range.new_section?(
|
|
157
|
+
PartialRange.from(target_node, kind)
|
|
158
|
+
elsif @partial_range.kind != kind || @partial_range.new_section?(target_node)
|
|
123
159
|
emit_partial_range
|
|
124
|
-
PartialRange.from(
|
|
160
|
+
PartialRange.from(target_node, kind)
|
|
125
161
|
else
|
|
126
|
-
@partial_range.extend_to(
|
|
162
|
+
@partial_range.extend_to(target_node)
|
|
127
163
|
end
|
|
128
164
|
|
|
129
165
|
false
|
|
130
166
|
end
|
|
131
167
|
|
|
168
|
+
sig { params(node: T.nilable(SyntaxTree::Node)).returns(T.nilable(String)) }
|
|
132
169
|
def partial_range_kind(node)
|
|
133
170
|
case node
|
|
134
171
|
when SyntaxTree::Comment
|
|
@@ -140,15 +177,17 @@ module RubyLsp
|
|
|
140
177
|
end
|
|
141
178
|
end
|
|
142
179
|
|
|
180
|
+
sig { void }
|
|
143
181
|
def emit_partial_range
|
|
144
182
|
return if @partial_range.nil?
|
|
145
183
|
|
|
146
|
-
@ranges << @partial_range.to_range
|
|
184
|
+
@ranges << @partial_range.to_range if @partial_range.multiline?
|
|
147
185
|
@partial_range = nil
|
|
148
186
|
end
|
|
149
187
|
|
|
188
|
+
sig { params(node: T.any(SyntaxTree::Call, SyntaxTree::CommandCall)).void }
|
|
150
189
|
def add_call_range(node)
|
|
151
|
-
receiver = node.receiver
|
|
190
|
+
receiver = T.let(node.receiver, SyntaxTree::Node)
|
|
152
191
|
loop do
|
|
153
192
|
case receiver
|
|
154
193
|
when SyntaxTree::Call
|
|
@@ -162,42 +201,39 @@ module RubyLsp
|
|
|
162
201
|
end
|
|
163
202
|
end
|
|
164
203
|
|
|
165
|
-
add_lines_range(receiver.location.start_line, node.location.end_line)
|
|
204
|
+
add_lines_range(receiver.location.start_line, node.location.end_line - 1)
|
|
166
205
|
|
|
167
206
|
visit(node.arguments)
|
|
168
207
|
end
|
|
169
208
|
|
|
209
|
+
sig { params(node: T.any(SyntaxTree::Def, SyntaxTree::Defs)).void }
|
|
170
210
|
def add_def_range(node)
|
|
171
211
|
params_location = node.params.location
|
|
172
212
|
|
|
173
213
|
if params_location.start_line < params_location.end_line
|
|
174
|
-
add_lines_range(params_location.end_line, node.location.end_line)
|
|
214
|
+
add_lines_range(params_location.end_line, node.location.end_line - 1)
|
|
175
215
|
else
|
|
176
|
-
|
|
216
|
+
location = node.location
|
|
217
|
+
add_lines_range(location.start_line, location.end_line - 1)
|
|
177
218
|
end
|
|
178
219
|
|
|
179
220
|
visit(node.bodystmt.statements)
|
|
180
221
|
end
|
|
181
222
|
|
|
223
|
+
sig { params(node: SyntaxTree::Node, statements: SyntaxTree::Statements).void }
|
|
182
224
|
def add_statements_range(node, statements)
|
|
183
|
-
add_lines_range(node.location.start_line, statements.location.end_line) unless statements.empty?
|
|
225
|
+
add_lines_range(node.location.start_line, statements.body.last.location.end_line) unless statements.empty?
|
|
184
226
|
end
|
|
185
227
|
|
|
228
|
+
sig { params(node: SyntaxTree::StringConcat).void }
|
|
186
229
|
def add_string_concat(node)
|
|
187
|
-
left = node.left
|
|
230
|
+
left = T.let(node.left, SyntaxTree::Node)
|
|
188
231
|
left = left.left while left.is_a?(SyntaxTree::StringConcat)
|
|
189
232
|
|
|
190
|
-
add_lines_range(left.location.start_line, node.right.location.end_line)
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
def add_node_range(node)
|
|
194
|
-
add_location_range(node.location)
|
|
195
|
-
end
|
|
196
|
-
|
|
197
|
-
def add_location_range(location)
|
|
198
|
-
add_lines_range(location.start_line, location.end_line)
|
|
233
|
+
add_lines_range(left.location.start_line, node.right.location.end_line - 1)
|
|
199
234
|
end
|
|
200
235
|
|
|
236
|
+
sig { params(start_line: Integer, end_line: Integer).void }
|
|
201
237
|
def add_lines_range(start_line, end_line)
|
|
202
238
|
return if start_line >= end_line
|
|
203
239
|
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
# typed: strict
|
|
1
2
|
# frozen_string_literal: true
|
|
2
3
|
|
|
4
|
+
require "ruby_lsp/requests/support/rubocop_formatting_runner"
|
|
5
|
+
|
|
3
6
|
module RubyLsp
|
|
4
7
|
module Requests
|
|
8
|
+
# 
|
|
9
|
+
#
|
|
5
10
|
# The [formatting](https://microsoft.github.io/language-server-protocol/specification#textDocument_formatting)
|
|
6
11
|
# request uses RuboCop to fix auto-correctable offenses in the document. This requires enabling format on save and
|
|
7
12
|
# registering the ruby-lsp as the Ruby formatter.
|
|
@@ -13,38 +18,43 @@ module RubyLsp
|
|
|
13
18
|
# puts "Hello" # --> formatting: fixes the indentation on save
|
|
14
19
|
# end
|
|
15
20
|
# ```
|
|
16
|
-
class Formatting <
|
|
17
|
-
|
|
21
|
+
class Formatting < BaseRequest
|
|
22
|
+
extend T::Sig
|
|
18
23
|
|
|
24
|
+
sig { params(uri: String, document: Document).void }
|
|
19
25
|
def initialize(uri, document)
|
|
20
|
-
super
|
|
21
|
-
|
|
26
|
+
super(document)
|
|
27
|
+
|
|
28
|
+
@uri = uri
|
|
22
29
|
end
|
|
23
30
|
|
|
31
|
+
sig { override.returns(T.nilable(T.all(T::Array[LanguageServer::Protocol::Interface::TextEdit], Object))) }
|
|
24
32
|
def run
|
|
25
|
-
|
|
33
|
+
formatted_text = formatted_file
|
|
34
|
+
return unless formatted_text
|
|
26
35
|
|
|
27
|
-
|
|
28
|
-
return unless @formatted_text
|
|
36
|
+
size = @document.source.size
|
|
29
37
|
|
|
30
38
|
[
|
|
31
39
|
LanguageServer::Protocol::Interface::TextEdit.new(
|
|
32
40
|
range: LanguageServer::Protocol::Interface::Range.new(
|
|
33
41
|
start: LanguageServer::Protocol::Interface::Position.new(line: 0, character: 0),
|
|
34
|
-
end: LanguageServer::Protocol::Interface::Position.new(
|
|
35
|
-
line: text.size,
|
|
36
|
-
character: text.size
|
|
37
|
-
)
|
|
42
|
+
end: LanguageServer::Protocol::Interface::Position.new(line: size, character: size)
|
|
38
43
|
),
|
|
39
|
-
new_text:
|
|
44
|
+
new_text: formatted_text
|
|
40
45
|
),
|
|
41
46
|
]
|
|
42
47
|
end
|
|
43
48
|
|
|
44
49
|
private
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
sig { returns(T.nilable(String)) }
|
|
52
|
+
def formatted_file
|
|
53
|
+
if defined?(Support::RuboCopFormattingRunner)
|
|
54
|
+
Support::RuboCopFormattingRunner.instance.run(@uri, @document)
|
|
55
|
+
else
|
|
56
|
+
SyntaxTree.format(@document.source)
|
|
57
|
+
end
|
|
48
58
|
end
|
|
49
59
|
end
|
|
50
60
|
end
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
# typed: strict
|
|
1
2
|
# frozen_string_literal: true
|
|
2
3
|
|
|
3
4
|
module RubyLsp
|
|
4
5
|
module Requests
|
|
6
|
+
# 
|
|
7
|
+
#
|
|
5
8
|
# The [selection ranges](https://microsoft.github.io/language-server-protocol/specification#textDocument_selectionRange)
|
|
6
9
|
# request informs the editor of ranges that the user may want to select based on the location(s)
|
|
7
10
|
# of their cursor(s).
|
|
@@ -16,7 +19,9 @@ module RubyLsp
|
|
|
16
19
|
# end
|
|
17
20
|
# ```
|
|
18
21
|
class SelectionRanges < BaseRequest
|
|
19
|
-
|
|
22
|
+
extend T::Sig
|
|
23
|
+
|
|
24
|
+
NODES_THAT_CAN_BE_PARENTS = T.let([
|
|
20
25
|
SyntaxTree::Assign,
|
|
21
26
|
SyntaxTree::ArrayLiteral,
|
|
22
27
|
SyntaxTree::Begin,
|
|
@@ -53,15 +58,17 @@ module RubyLsp
|
|
|
53
58
|
SyntaxTree::VCall,
|
|
54
59
|
SyntaxTree::When,
|
|
55
60
|
SyntaxTree::While,
|
|
56
|
-
].freeze
|
|
61
|
+
].freeze, T::Array[T.class_of(SyntaxTree::Node)])
|
|
57
62
|
|
|
63
|
+
sig { params(document: Document).void }
|
|
58
64
|
def initialize(document)
|
|
59
65
|
super(document)
|
|
60
66
|
|
|
61
|
-
@ranges = []
|
|
62
|
-
@stack = []
|
|
67
|
+
@ranges = T.let([], T::Array[Support::SelectionRange])
|
|
68
|
+
@stack = T.let([], T::Array[Support::SelectionRange])
|
|
63
69
|
end
|
|
64
70
|
|
|
71
|
+
sig { override.returns(T.all(T::Array[Support::SelectionRange], Object)) }
|
|
65
72
|
def run
|
|
66
73
|
visit(@document.tree)
|
|
67
74
|
@ranges.reverse!
|
|
@@ -69,6 +76,7 @@ module RubyLsp
|
|
|
69
76
|
|
|
70
77
|
private
|
|
71
78
|
|
|
79
|
+
sig { params(node: T.nilable(SyntaxTree::Node)).void }
|
|
72
80
|
def visit(node)
|
|
73
81
|
return if node.nil?
|
|
74
82
|
|
|
@@ -82,6 +90,12 @@ module RubyLsp
|
|
|
82
90
|
@stack.pop if NODES_THAT_CAN_BE_PARENTS.include?(node.class)
|
|
83
91
|
end
|
|
84
92
|
|
|
93
|
+
sig do
|
|
94
|
+
params(
|
|
95
|
+
location: SyntaxTree::Location,
|
|
96
|
+
parent: T.nilable(Support::SelectionRange)
|
|
97
|
+
).returns(Support::SelectionRange)
|
|
98
|
+
end
|
|
85
99
|
def create_selection_range(location, parent = nil)
|
|
86
100
|
RubyLsp::Requests::Support::SelectionRange.new(
|
|
87
101
|
range: LanguageServer::Protocol::Interface::Range.new(
|