ruby-lsp 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +6 -0
  3. data/.rubocop.yml +16 -0
  4. data/CHANGELOG.md +13 -0
  5. data/Gemfile +8 -5
  6. data/Gemfile.lock +55 -10
  7. data/README.md +40 -0
  8. data/VERSION +1 -1
  9. data/bin/tapioca +29 -0
  10. data/dev.yml +3 -0
  11. data/exe/ruby-lsp +19 -4
  12. data/lib/internal.rb +7 -0
  13. data/lib/ruby-lsp.rb +1 -0
  14. data/lib/ruby_lsp/cli.rb +12 -5
  15. data/lib/ruby_lsp/document.rb +37 -14
  16. data/lib/ruby_lsp/handler.rb +78 -23
  17. data/lib/ruby_lsp/requests/base_request.rb +11 -0
  18. data/lib/ruby_lsp/requests/code_actions.rb +1 -0
  19. data/lib/ruby_lsp/requests/diagnostics.rb +1 -0
  20. data/lib/ruby_lsp/requests/document_highlight.rb +96 -0
  21. data/lib/ruby_lsp/requests/document_symbol.rb +1 -10
  22. data/lib/ruby_lsp/requests/folding_ranges.rb +3 -2
  23. data/lib/ruby_lsp/requests/formatting.rb +2 -1
  24. data/lib/ruby_lsp/requests/rubocop_request.rb +1 -0
  25. data/lib/ruby_lsp/requests/selection_ranges.rb +1 -0
  26. data/lib/ruby_lsp/requests/semantic_highlighting.rb +17 -3
  27. data/lib/ruby_lsp/requests/support/rubocop_diagnostic.rb +1 -0
  28. data/lib/ruby_lsp/requests/support/selection_range.rb +1 -0
  29. data/lib/ruby_lsp/requests/support/semantic_token_encoder.rb +12 -1
  30. data/lib/ruby_lsp/requests/support/syntax_error_diagnostic.rb +1 -0
  31. data/lib/ruby_lsp/requests.rb +2 -0
  32. data/lib/ruby_lsp/store.rb +19 -3
  33. data/rakelib/check_docs.rake +4 -1
  34. data/ruby-lsp.gemspec +1 -0
  35. data/sorbet/config +4 -0
  36. data/sorbet/rbi/.rubocop.yml +8 -0
  37. data/sorbet/rbi/gems/ansi@1.5.0.rbi +338 -0
  38. data/sorbet/rbi/gems/ast@2.4.2.rbi +522 -0
  39. data/sorbet/rbi/gems/builder@3.2.4.rbi +418 -0
  40. data/sorbet/rbi/gems/coderay@1.1.3.rbi +8 -0
  41. data/sorbet/rbi/gems/debug@1.5.0.rbi +1273 -0
  42. data/sorbet/rbi/gems/diff-lcs@1.5.0.rbi +867 -0
  43. data/sorbet/rbi/gems/io-console@0.5.11.rbi +8 -0
  44. data/sorbet/rbi/gems/irb@1.4.1.rbi +376 -0
  45. data/sorbet/rbi/gems/language_server-protocol@3.16.0.3.rbi +7325 -0
  46. data/sorbet/rbi/gems/method_source@1.0.0.rbi +8 -0
  47. data/sorbet/rbi/gems/minitest-reporters@1.5.0.rbi +612 -0
  48. data/sorbet/rbi/gems/minitest@5.15.0.rbi +994 -0
  49. data/sorbet/rbi/gems/parallel@1.22.1.rbi +163 -0
  50. data/sorbet/rbi/gems/parser@3.1.2.0.rbi +3968 -0
  51. data/sorbet/rbi/gems/prettier_print@0.1.0.rbi +734 -0
  52. data/sorbet/rbi/gems/pry@0.14.1.rbi +8 -0
  53. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +227 -0
  54. data/sorbet/rbi/gems/rake@13.0.6.rbi +1853 -0
  55. data/sorbet/rbi/gems/rbi@0.0.14.rbi +2337 -0
  56. data/sorbet/rbi/gems/regexp_parser@2.5.0.rbi +1854 -0
  57. data/sorbet/rbi/gems/reline@0.3.1.rbi +1274 -0
  58. data/sorbet/rbi/gems/rexml@3.2.5.rbi +3852 -0
  59. data/sorbet/rbi/gems/rubocop-ast@1.18.0.rbi +4180 -0
  60. data/sorbet/rbi/gems/rubocop-minitest@0.20.0.rbi +1369 -0
  61. data/sorbet/rbi/gems/rubocop-rake@0.6.0.rbi +246 -0
  62. data/sorbet/rbi/gems/rubocop-shopify@2.6.0.rbi +8 -0
  63. data/sorbet/rbi/gems/rubocop-sorbet@0.6.8.rbi +652 -0
  64. data/sorbet/rbi/gems/rubocop@1.30.0.rbi +36729 -0
  65. data/sorbet/rbi/gems/ruby-progressbar@1.11.0.rbi +732 -0
  66. data/sorbet/rbi/gems/spoom@1.1.11.rbi +1600 -0
  67. data/sorbet/rbi/gems/syntax_tree@2.7.1.rbi +6777 -0
  68. data/sorbet/rbi/gems/tapioca@0.8.1.rbi +1972 -0
  69. data/sorbet/rbi/gems/thor@1.2.1.rbi +2921 -0
  70. data/sorbet/rbi/gems/unicode-display_width@2.1.0.rbi +27 -0
  71. data/sorbet/rbi/gems/unparser@0.6.5.rbi +2789 -0
  72. data/sorbet/rbi/gems/webrick@1.7.0.rbi +1779 -0
  73. data/sorbet/rbi/gems/yard-sorbet@0.6.1.rbi +289 -0
  74. data/sorbet/rbi/gems/yard@0.9.27.rbi +13048 -0
  75. data/sorbet/rbi/shims/fiddle.rbi +4 -0
  76. data/sorbet/rbi/shims/hash.rbi +6 -0
  77. data/sorbet/rbi/shims/rdoc.rbi +4 -0
  78. data/sorbet/tapioca/config.yml +13 -0
  79. data/sorbet/tapioca/require.rb +7 -0
  80. metadata +64 -2
@@ -1,3 +1,4 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "ruby_lsp/requests"
@@ -6,24 +7,25 @@ require "benchmark"
6
7
 
7
8
  module RubyLsp
8
9
  class Handler
9
- IGNORED_FOR_TELEMETRY = [
10
- "initialized",
11
- "$/cancelRequest",
12
- ].freeze
10
+ extend T::Sig
11
+ VOID = T.let(Object.new.freeze, Object)
13
12
 
13
+ sig { returns(Store) }
14
14
  attr_reader :store
15
15
 
16
16
  Interface = LanguageServer::Protocol::Interface
17
17
  Constant = LanguageServer::Protocol::Constant
18
18
  Transport = LanguageServer::Protocol::Transport
19
19
 
20
+ sig { void }
20
21
  def initialize
21
- @writer = Transport::Stdio::Writer.new
22
- @reader = Transport::Stdio::Reader.new
23
- @handlers = {}
24
- @store = Store.new
22
+ @writer = T.let(Transport::Stdio::Writer.new, Transport::Stdio::Writer)
23
+ @reader = T.let(Transport::Stdio::Reader.new, Transport::Stdio::Reader)
24
+ @handlers = T.let({}, T::Hash[String, T.proc.params(request: T::Hash[Symbol, T.untyped]).returns(T.untyped)])
25
+ @store = T.let(Store.new, Store)
25
26
  end
26
27
 
28
+ sig { void }
27
29
  def start
28
30
  $stderr.puts "Starting Ruby LSP..."
29
31
  @reader.read do |request|
@@ -31,26 +33,39 @@ module RubyLsp
31
33
  end
32
34
  end
33
35
 
36
+ sig { params(blk: T.proc.bind(Handler).params(arg0: T.untyped).void).void }
34
37
  def config(&blk)
35
38
  instance_exec(&blk)
36
39
  end
37
40
 
38
41
  private
39
42
 
43
+ sig do
44
+ params(
45
+ msg: String,
46
+ blk: T.proc.bind(Handler).params(request: T::Hash[Symbol, T.untyped]).returns(T.untyped)
47
+ ).void
48
+ end
40
49
  def on(msg, &blk)
41
- @handlers[msg.to_s] = blk
50
+ @handlers[msg] = blk
42
51
  end
43
52
 
53
+ sig { params(request: T::Hash[Symbol, T.untyped]).void }
44
54
  def handle(request)
45
- result = @handlers[request[:method]]&.call(request)
46
- @writer.write(id: request[:id], result: result) if result
55
+ handler = @handlers[request[:method]]
56
+ return unless handler
57
+
58
+ result = handler.call(request)
59
+ @writer.write(id: request[:id], result: result) unless result == VOID
47
60
  end
48
61
 
62
+ sig { void }
49
63
  def shutdown
50
64
  $stderr.puts "Shutting down Ruby LSP..."
51
65
  store.clear
52
66
  end
53
67
 
68
+ sig { params(enabled_features: T::Array[String]).returns(Interface::InitializeResult) }
54
69
  def respond_with_capabilities(enabled_features)
55
70
  document_symbol_provider = if enabled_features.include?("documentSymbols")
56
71
  Interface::DocumentSymbolClientCapabilities.new(
@@ -70,7 +85,7 @@ module RubyLsp
70
85
  document_selector: { scheme: "file", language: "ruby" },
71
86
  legend: Interface::SemanticTokensLegend.new(
72
87
  token_types: Requests::SemanticHighlighting::TOKEN_TYPES,
73
- token_modifiers: Requests::SemanticHighlighting::TOKEN_MODIFIERS
88
+ token_modifiers: Requests::SemanticHighlighting::TOKEN_MODIFIERS.keys
74
89
  ),
75
90
  range: false,
76
91
  full: {
@@ -90,23 +105,32 @@ module RubyLsp
90
105
  folding_range_provider: folding_ranges_provider,
91
106
  semantic_tokens_provider: semantic_tokens_provider,
92
107
  document_formatting_provider: enabled_features.include?("formatting"),
108
+ document_highlight_provider: enabled_features.include?("documentHighlights"),
93
109
  code_action_provider: enabled_features.include?("codeActions")
94
110
  )
95
111
  )
96
112
  end
97
113
 
114
+ sig { params(uri: String).returns(T::Array[LanguageServer::Protocol::Interface::DocumentSymbol]) }
98
115
  def respond_with_document_symbol(uri)
99
116
  store.cache_fetch(uri, :document_symbol) do |document|
100
117
  RubyLsp::Requests::DocumentSymbol.run(document)
101
118
  end
102
119
  end
103
120
 
121
+ sig { params(uri: String).returns(T::Array[LanguageServer::Protocol::Interface::FoldingRange]) }
104
122
  def respond_with_folding_ranges(uri)
105
123
  store.cache_fetch(uri, :folding_ranges) do |document|
106
124
  Requests::FoldingRanges.run(document)
107
125
  end
108
126
  end
109
127
 
128
+ sig do
129
+ params(
130
+ uri: String,
131
+ positions: T::Array[Document::PositionShape]
132
+ ).returns(T::Array[RubyLsp::Requests::Support::SelectionRange])
133
+ end
110
134
  def respond_with_selection_ranges(uri, positions)
111
135
  ranges = store.cache_fetch(uri, :selection_ranges) do |document|
112
136
  Requests::SelectionRanges.run(document)
@@ -123,16 +147,19 @@ module RubyLsp
123
147
  end
124
148
  end
125
149
 
150
+ sig { params(uri: String).returns(LanguageServer::Protocol::Interface::SemanticTokens) }
126
151
  def respond_with_semantic_highlighting(uri)
127
152
  store.cache_fetch(uri, :semantic_highlighting) do |document|
128
153
  Requests::SemanticHighlighting.new(document, encoder: Requests::Support::SemanticTokenEncoder.new).run
129
154
  end
130
155
  end
131
156
 
157
+ sig { params(uri: String).returns(T::Array[LanguageServer::Protocol::Interface::TextEdit]) }
132
158
  def respond_with_formatting(uri)
133
159
  Requests::Formatting.run(uri, store.get(uri))
134
160
  end
135
161
 
162
+ sig { params(uri: String).void }
136
163
  def send_diagnostics(uri)
137
164
  response = store.cache_fetch(uri, :diagnostics) do |document|
138
165
  Requests::Diagnostics.run(uri, document)
@@ -147,35 +174,63 @@ module RubyLsp
147
174
  )
148
175
  end
149
176
 
177
+ sig do
178
+ params(uri: String, range: T::Range[Integer]).returns(T::Array[LanguageServer::Protocol::Interface::Diagnostic])
179
+ end
150
180
  def respond_with_code_actions(uri, range)
151
181
  store.cache_fetch(uri, :code_actions) do |document|
152
182
  Requests::CodeActions.run(uri, document, range)
153
183
  end
154
184
  end
155
185
 
156
- def configure_options(initialization_options)
157
- @telemetry_enabled = initialization_options.fetch(:telemetryEnabled, false)
186
+ sig do
187
+ params(
188
+ uri: String,
189
+ position: Document::PositionShape
190
+ ).returns(T::Array[LanguageServer::Protocol::Interface::DocumentHighlight])
191
+ end
192
+ def respond_with_document_highlight(uri, position)
193
+ Requests::DocumentHighlight.run(store.get(uri), position)
158
194
  end
159
195
 
160
- def with_telemetry(request)
161
- return yield unless @telemetry_enabled && !IGNORED_FOR_TELEMETRY.include?(request[:method])
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))
162
200
 
163
- result = nil
164
201
  request_time = Benchmark.realtime do
165
- result = yield
202
+ result = block.call
203
+ rescue StandardError => e
204
+ error = e
166
205
  end
167
206
 
207
+ @writer.write(method: "telemetry/event", params: telemetry_params(request, request_time, error))
208
+ result
209
+ end
210
+
211
+ sig do
212
+ params(
213
+ request: T::Hash[Symbol, T.untyped],
214
+ request_time: Float,
215
+ error: T.nilable(StandardError)
216
+ ).returns(T::Hash[Symbol, T.any(String, Float)])
217
+ end
218
+ def telemetry_params(request, request_time, error)
219
+ uri = request.dig(:params, :textDocument, :uri)
220
+
168
221
  params = {
169
222
  request: request[:method],
170
- requestTime: request_time,
171
223
  lspVersion: RubyLsp::VERSION,
224
+ requestTime: request_time,
172
225
  }
173
226
 
174
- uri = request.dig(:params, :textDocument, :uri)
175
- params[:uri] = uri if uri
227
+ if error
228
+ params[:errorClass] = error.class.name
229
+ params[:errorMessage] = error.message
230
+ end
176
231
 
177
- @writer.write(method: "telemetry/event", params: params)
178
- result
232
+ params[:uri] = uri if uri
233
+ params
179
234
  end
180
235
  end
181
236
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -17,6 +18,16 @@ module RubyLsp
17
18
  def run
18
19
  raise NotImplementedError, "#{self.class}#run must be implemented"
19
20
  end
21
+
22
+ def range_from_syntax_tree_node(node)
23
+ loc = node.location
24
+
25
+ LanguageServer::Protocol::Interface::Range.new(
26
+ start: LanguageServer::Protocol::Interface::Position.new(line: loc.start_line - 1,
27
+ character: loc.start_column),
28
+ end: LanguageServer::Protocol::Interface::Position.new(line: loc.end_line - 1, character: loc.end_column),
29
+ )
30
+ end
20
31
  end
21
32
  end
22
33
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -0,0 +1,96 @@
1
+ # typed: true
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module Requests
6
+ # The [document highlight](https://microsoft.github.io/language-server-protocol/specification#textDocument_documentHighlight)
7
+ # informs the editor all relevant elements of the currently pointed item for highlighting. For example, when
8
+ # the cursor is on the `F` of the constant `FOO`, the editor should identify other occurences of `FOO`
9
+ # and highlight them.
10
+ #
11
+ # For writable elements like constants or variables, their read/write occurrences should be highlighted differently.
12
+ # This is achieved by sending different "kind" attributes to the editor (2 for read and 3 for write).
13
+ #
14
+ # # Example
15
+ #
16
+ # ```ruby
17
+ # FOO = 1 # should be highlighted as "write"
18
+ #
19
+ # def foo
20
+ # FOO # should be highlighted as "read"
21
+ # end
22
+ # ```
23
+ class DocumentHighlight < BaseRequest
24
+ def self.run(document, position)
25
+ new(document, position).run
26
+ end
27
+
28
+ def initialize(document, position)
29
+ @highlights = []
30
+ position = Document::Scanner.new(document.source).find_position(position)
31
+ @target = find(document.tree, position)
32
+
33
+ super(document)
34
+ end
35
+
36
+ def run
37
+ # no @target means the target is not highlightable
38
+ return [] unless @target
39
+
40
+ visit(@document.tree)
41
+ @highlights
42
+ end
43
+
44
+ def visit_var_field(node)
45
+ if matches_target?(node.value)
46
+ add_highlight(
47
+ node.value,
48
+ LanguageServer::Protocol::Constant::DocumentHighlightKind::WRITE
49
+ )
50
+ end
51
+
52
+ super
53
+ end
54
+
55
+ def visit_var_ref(node)
56
+ if matches_target?(node.value)
57
+ add_highlight(
58
+ node.value,
59
+ LanguageServer::Protocol::Constant::DocumentHighlightKind::READ
60
+ )
61
+ end
62
+
63
+ super
64
+ end
65
+
66
+ private
67
+
68
+ def find(node, position)
69
+ matched =
70
+ node.child_nodes.compact.bsearch do |child|
71
+ if (child.location.start_char...child.location.end_char).cover?(position)
72
+ 0
73
+ else
74
+ position <=> child.location.start_char
75
+ end
76
+ end
77
+
78
+ case matched
79
+ when SyntaxTree::GVar, SyntaxTree::Ident, SyntaxTree::IVar, SyntaxTree::Const, SyntaxTree::CVar
80
+ matched
81
+ when SyntaxTree::Node
82
+ find(matched, position)
83
+ end
84
+ end
85
+
86
+ def matches_target?(node)
87
+ node.is_a?(@target.class) && node.value == @target.value
88
+ end
89
+
90
+ def add_highlight(node, kind)
91
+ range = range_from_syntax_tree_node(node)
92
+ @highlights << LanguageServer::Protocol::Interface::DocumentHighlight.new(range: range, kind: kind)
93
+ end
94
+ end
95
+ end
96
+ end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -210,16 +211,6 @@ module RubyLsp
210
211
 
211
212
  symbol
212
213
  end
213
-
214
- def range_from_syntax_tree_node(node)
215
- loc = node.location
216
-
217
- LanguageServer::Protocol::Interface::Range.new(
218
- start: LanguageServer::Protocol::Interface::Position.new(line: loc.start_line - 1,
219
- character: loc.start_column),
220
- end: LanguageServer::Protocol::Interface::Position.new(line: loc.end_line - 1, character: loc.end_column),
221
- )
222
- end
223
214
  end
224
215
  end
225
216
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -148,7 +149,7 @@ module RubyLsp
148
149
  end
149
150
 
150
151
  def add_call_range(node)
151
- receiver = node.receiver
152
+ receiver = T.let(node.receiver, SyntaxTree::Node)
152
153
  loop do
153
154
  case receiver
154
155
  when SyntaxTree::Call
@@ -184,7 +185,7 @@ module RubyLsp
184
185
  end
185
186
 
186
187
  def add_string_concat(node)
187
- left = node.left
188
+ left = T.let(node.left, SyntaxTree::Node)
188
189
  left = left.left while left.is_a?(SyntaxTree::StringConcat)
189
190
 
190
191
  add_lines_range(left.location.start_line, node.right.location.end_line)
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -14,7 +15,7 @@ module RubyLsp
14
15
  # end
15
16
  # ```
16
17
  class Formatting < RuboCopRequest
17
- RUBOCOP_FLAGS = (COMMON_RUBOCOP_FLAGS + ["--auto-correct"]).freeze
18
+ RUBOCOP_FLAGS = (COMMON_RUBOCOP_FLAGS + ["--autocorrect"]).freeze
18
19
 
19
20
  def initialize(uri, document)
20
21
  super
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "rubocop"
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -20,7 +21,19 @@ module RubyLsp
20
21
  :variable,
21
22
  :method,
22
23
  ].freeze
23
- TOKEN_MODIFIERS = [].freeze
24
+
25
+ TOKEN_MODIFIERS = {
26
+ declaration: 0,
27
+ definition: 1,
28
+ readonly: 2,
29
+ static: 3,
30
+ deprecated: 4,
31
+ abstract: 5,
32
+ async: 6,
33
+ modification: 7,
34
+ documentation: 8,
35
+ default_library: 9,
36
+ }.freeze
24
37
 
25
38
  SemanticToken = Struct.new(:location, :length, :type, :modifier)
26
39
 
@@ -89,9 +102,10 @@ module RubyLsp
89
102
  add_token(node.value.location, :method)
90
103
  end
91
104
 
92
- def add_token(location, type)
105
+ def add_token(location, type, modifiers = [])
93
106
  length = location.end_char - location.start_char
94
- @tokens.push(SemanticToken.new(location, length, TOKEN_TYPES.index(type), 0))
107
+ modifiers_indices = modifiers.filter_map { |modifier| TOKEN_MODIFIERS[modifier] }
108
+ @tokens.push(SemanticToken.new(location, length, TOKEN_TYPES.index(type), modifiers_indices))
95
109
  end
96
110
  end
97
111
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -38,11 +39,21 @@ module RubyLsp
38
39
  delta_column = column
39
40
  delta_column -= @current_column if delta_line == 0
40
41
 
41
- [delta_line, delta_column, token.length, token.type, token.modifier]
42
+ [delta_line, delta_column, token.length, token.type, encode_modifiers(token.modifier)]
42
43
  ensure
43
44
  @current_row = row
44
45
  @current_column = column
45
46
  end
47
+
48
+ # Encode an array of modifiers to positions onto a bit flag
49
+ # For example, [:default_library] will be encoded as
50
+ # 0b1000000000, as :default_library is the 10th bit according
51
+ # to the token modifiers index map.
52
+ def encode_modifiers(modifiers)
53
+ modifiers.inject(0) do |encoded_modifiers, modifier|
54
+ encoded_modifiers | (1 << modifier)
55
+ end
56
+ end
46
57
  end
47
58
  end
48
59
  end
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -1,3 +1,4 @@
1
+ # typed: true
1
2
  # frozen_string_literal: true
2
3
 
3
4
  module RubyLsp
@@ -11,6 +12,7 @@ module RubyLsp
11
12
  autoload :Formatting, "ruby_lsp/requests/formatting"
12
13
  autoload :Diagnostics, "ruby_lsp/requests/diagnostics"
13
14
  autoload :CodeActions, "ruby_lsp/requests/code_actions"
15
+ autoload :DocumentHighlight, "ruby_lsp/requests/document_highlight"
14
16
 
15
17
  module Support
16
18
  autoload :RuboCopDiagnostic, "ruby_lsp/requests/support/rubocop_diagnostic"
@@ -1,3 +1,4 @@
1
+ # typed: strict
1
2
  # frozen_string_literal: true
2
3
 
3
4
  require "cgi"
@@ -6,36 +7,51 @@ require "ruby_lsp/document"
6
7
 
7
8
  module RubyLsp
8
9
  class Store
10
+ extend T::Sig
11
+
12
+ sig { void }
9
13
  def initialize
10
- @state = {}
14
+ @state = T.let({}, T::Hash[String, Document])
11
15
  end
12
16
 
17
+ sig { params(uri: String).returns(Document) }
13
18
  def get(uri)
14
19
  document = @state[uri]
15
20
  return document unless document.nil?
16
21
 
17
22
  set(uri, File.binread(CGI.unescape(URI.parse(uri).path)))
18
- @state[uri]
23
+ T.must(@state[uri])
19
24
  end
20
25
 
26
+ sig { params(uri: String, content: String).void }
21
27
  def set(uri, content)
22
28
  @state[uri] = Document.new(content)
23
29
  rescue SyntaxTree::Parser::ParseError
24
30
  # Do not update the store if there are syntax errors
25
31
  end
26
32
 
33
+ sig { params(uri: String, edits: T::Array[Document::EditShape]).void }
27
34
  def push_edits(uri, edits)
28
- @state[uri].push_edits(edits)
35
+ T.must(@state[uri]).push_edits(edits)
29
36
  end
30
37
 
38
+ sig { void }
31
39
  def clear
32
40
  @state.clear
33
41
  end
34
42
 
43
+ sig { params(uri: String).void }
35
44
  def delete(uri)
36
45
  @state.delete(uri)
37
46
  end
38
47
 
48
+ sig do
49
+ params(
50
+ uri: String,
51
+ request_name: Symbol,
52
+ block: T.proc.params(document: Document).returns(T.untyped)
53
+ ).returns(T.untyped)
54
+ end
39
55
  def cache_fetch(uri, request_name, &block)
40
56
  get(uri).cache_fetch(request_name, &block)
41
57
  end
@@ -1,3 +1,4 @@
1
+ # typed: false
1
2
  # frozen_string_literal: true
2
3
 
3
4
  desc "Check if all LSP requests are documented"
@@ -14,7 +15,9 @@ task :check_docs do
14
15
  end
15
16
 
16
17
  spec_matcher = %r{\(https://microsoft.github.io/language-server-protocol/specification#.*\)}
17
- error_messages = RubyLsp::Requests.constants.each_with_object(Hash.new { |h, k| h[k] = [] }) do |request, errors|
18
+ error_messages = RubyLsp::Requests
19
+ .constants # rubocop:disable Sorbet/ConstantsFromStrings
20
+ .each_with_object(Hash.new { |h, k| h[k] = [] }) do |request, errors|
18
21
  full_name = "RubyLsp::Requests::#{request}"
19
22
  docs = YARD::Registry.at(full_name).docstring
20
23
  next if /:nodoc:/.match?(docs)
data/ruby-lsp.gemspec CHANGED
@@ -21,5 +21,6 @@ Gem::Specification.new do |s|
21
21
 
22
22
  s.add_dependency("language_server-protocol")
23
23
  s.add_dependency("rubocop", ">= 1.0")
24
+ s.add_dependency("sorbet-runtime")
24
25
  s.add_dependency("syntax_tree", ">= 2.3")
25
26
  end
data/sorbet/config ADDED
@@ -0,0 +1,4 @@
1
+ --dir
2
+ .
3
+ --ignore=vendor/
4
+ --ignore=test/fixtures/
@@ -0,0 +1,8 @@
1
+ inherit_gem:
2
+ rubocop-sorbet: config/rbi.yml
3
+
4
+ Lint/EmptyFile:
5
+ Enabled: false
6
+
7
+ Sorbet/TypeAliasName:
8
+ Enabled: false