ruby-lsp 0.3.8 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,250 +1,157 @@
1
1
  # typed: strict
2
2
  # frozen_string_literal: true
3
3
 
4
- require "ruby_lsp/internal"
5
-
6
4
  module RubyLsp
7
- Handler.start do
8
- on("initialize") do |request|
9
- store.clear
10
- store.encoding = request.dig(:params, :capabilities, :general, :positionEncodings)
11
-
12
- initialization_options = request.dig(:params, :initializationOptions)
13
- enabled_features = initialization_options.fetch(:enabledFeatures, [])
14
-
15
- document_symbol_provider = if enabled_features.include?("documentSymbols")
16
- Interface::DocumentSymbolClientCapabilities.new(
17
- hierarchical_document_symbol_support: true,
18
- symbol_kind: {
19
- value_set: Requests::DocumentSymbol::SYMBOL_KIND.values,
20
- },
21
- )
22
- end
23
-
24
- document_link_provider = if enabled_features.include?("documentLink")
25
- Interface::DocumentLinkOptions.new(resolve_provider: false)
26
- end
27
-
28
- hover_provider = if enabled_features.include?("hover")
29
- Interface::HoverClientCapabilities.new(dynamic_registration: false)
30
- end
31
-
32
- folding_ranges_provider = if enabled_features.include?("foldingRanges")
33
- Interface::FoldingRangeClientCapabilities.new(line_folding_only: true)
34
- end
35
-
36
- semantic_tokens_provider = if enabled_features.include?("semanticHighlighting")
37
- Interface::SemanticTokensRegistrationOptions.new(
38
- document_selector: { scheme: "file", language: "ruby" },
39
- legend: Interface::SemanticTokensLegend.new(
40
- token_types: Requests::SemanticHighlighting::TOKEN_TYPES.keys,
41
- token_modifiers: Requests::SemanticHighlighting::TOKEN_MODIFIERS.keys,
42
- ),
43
- range: true,
44
- full: { delta: false },
45
- )
46
- end
47
-
48
- diagnostics_provider = if enabled_features.include?("diagnostics")
49
- {
50
- interFileDependencies: false,
51
- workspaceDiagnostics: false,
52
- }
53
- end
54
-
55
- on_type_formatting_provider = if enabled_features.include?("onTypeFormatting")
56
- Interface::DocumentOnTypeFormattingOptions.new(
57
- first_trigger_character: "{",
58
- more_trigger_character: ["\n", "|"],
59
- )
60
- end
61
-
62
- inlay_hint_provider = if enabled_features.include?("inlayHint")
63
- Interface::InlayHintOptions.new(resolve_provider: false)
5
+ Interface = LanguageServer::Protocol::Interface
6
+ Constant = LanguageServer::Protocol::Constant
7
+ Transport = LanguageServer::Protocol::Transport
8
+
9
+ class Server
10
+ extend T::Sig
11
+
12
+ sig { void }
13
+ def initialize
14
+ @writer = T.let(Transport::Stdio::Writer.new, Transport::Stdio::Writer)
15
+ @reader = T.let(Transport::Stdio::Reader.new, Transport::Stdio::Reader)
16
+ @store = T.let(Store.new, Store)
17
+
18
+ # The job queue is the actual list of requests we have to process
19
+ @job_queue = T.let(Thread::Queue.new, Thread::Queue)
20
+ # The jobs hash is just a way of keeping a handle to jobs based on the request ID, so we can cancel them
21
+ @jobs = T.let({}, T::Hash[T.any(String, Integer), Job])
22
+ @mutex = T.let(Mutex.new, Mutex)
23
+ @worker = T.let(new_worker, Thread)
24
+
25
+ Thread.main.priority = 1
26
+ end
27
+
28
+ sig { void }
29
+ def start
30
+ warn("Starting Ruby LSP...")
31
+
32
+ # Requests that have to be executed sequentially or in the main process are implemented here. All other requests
33
+ # fall under the else branch which just pushes requests to the queue
34
+ @reader.read do |request|
35
+ case request[:method]
36
+ when "initialize", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange"
37
+ result = Executor.new(@store).execute(request)
38
+ finalize_request(result, request)
39
+ when "$/cancelRequest"
40
+ # Cancel the job if it's still in the queue
41
+ @mutex.synchronize { @jobs[request[:params][:id]]&.cancel }
42
+ when "shutdown"
43
+ warn("Shutting down Ruby LSP...")
44
+
45
+ # Close the queue so that we can no longer receive items
46
+ @job_queue.close
47
+ # Clear any remaining jobs so that the thread can terminate
48
+ @job_queue.clear
49
+ @jobs.clear
50
+ # Wait until the thread is finished
51
+ @worker.join
52
+ @store.clear
53
+
54
+ finalize_request(Result.new(response: nil, notifications: []), request)
55
+ when "exit"
56
+ # We return zero if shutdown has already been received or one otherwise as per the recommendation in the spec
57
+ # https://microsoft.github.io/language-server-protocol/specification/#exit
58
+ status = @store.empty? ? 0 : 1
59
+ exit(status)
60
+ else
61
+ # Default case: push the request to the queue to be executed by the worker
62
+ job = Job.new(request: request, cancelled: false)
63
+
64
+ # Remember a handle to the job, so that we can cancel it
65
+ @mutex.synchronize { @jobs[request[:id]] = job }
66
+ @job_queue << job
67
+ end
64
68
  end
65
-
66
- Interface::InitializeResult.new(
67
- capabilities: Interface::ServerCapabilities.new(
68
- text_document_sync: Interface::TextDocumentSyncOptions.new(
69
- change: Constant::TextDocumentSyncKind::INCREMENTAL,
70
- open_close: true,
71
- ),
72
- selection_range_provider: enabled_features.include?("selectionRanges"),
73
- hover_provider: hover_provider,
74
- document_symbol_provider: document_symbol_provider,
75
- document_link_provider: document_link_provider,
76
- folding_range_provider: folding_ranges_provider,
77
- semantic_tokens_provider: semantic_tokens_provider,
78
- document_formatting_provider: enabled_features.include?("formatting"),
79
- document_highlight_provider: enabled_features.include?("documentHighlights"),
80
- code_action_provider: enabled_features.include?("codeActions"),
81
- document_on_type_formatting_provider: on_type_formatting_provider,
82
- diagnostic_provider: diagnostics_provider,
83
- inlay_hint_provider: inlay_hint_provider,
84
- ),
85
- )
86
69
  end
87
70
 
88
- on("textDocument/didChange") do |request|
89
- uri = request.dig(:params, :textDocument, :uri)
90
- store.push_edits(uri, request.dig(:params, :contentChanges))
91
-
92
- Handler::VOID
93
- end
94
-
95
- on("textDocument/didOpen") do |request|
96
- uri = request.dig(:params, :textDocument, :uri)
97
- text = request.dig(:params, :textDocument, :text)
98
- store.set(uri, text)
99
-
100
- Handler::VOID
101
- end
102
-
103
- on("textDocument/didClose") do |request|
104
- uri = request.dig(:params, :textDocument, :uri)
105
- store.delete(uri)
106
- clear_diagnostics(uri)
71
+ private
107
72
 
108
- Handler::VOID
109
- end
110
-
111
- on("textDocument/documentSymbol", parallel: true) do |request|
112
- store.cache_fetch(request.dig(:params, :textDocument, :uri), :document_symbol) do |document|
113
- Requests::DocumentSymbol.new(document).run
114
- end
115
- end
116
-
117
- on("textDocument/documentLink", parallel: true) do |request|
118
- uri = request.dig(:params, :textDocument, :uri)
119
- store.cache_fetch(uri, :document_link) do |document|
120
- RubyLsp::Requests::DocumentLink.new(uri, document).run
121
- end
122
- end
73
+ sig { returns(Thread) }
74
+ def new_worker
75
+ Thread.new do
76
+ # Thread::Queue#pop is thread safe and will wait until an item is available
77
+ loop do
78
+ job = T.let(@job_queue.pop, T.nilable(Job))
79
+ # The only time when the job is nil is when the queue is closed and we can then terminate the thread
80
+ break if job.nil?
123
81
 
124
- on("textDocument/hover") do |request|
125
- position = request.dig(:params, :position)
126
- document = store.get(request.dig(:params, :textDocument, :uri))
82
+ request = job.request
83
+ @mutex.synchronize { @jobs.delete(request[:id]) }
127
84
 
128
- RubyLsp::Requests::Hover.new(document, position).run
129
- end
85
+ result = if job.cancelled
86
+ # We need to return nil to the client even if the request was cancelled
87
+ Result.new(response: nil, notifications: [])
88
+ else
89
+ Executor.new(@store).execute(request)
90
+ end
130
91
 
131
- on("textDocument/foldingRange", parallel: true) do |request|
132
- store.cache_fetch(request.dig(:params, :textDocument, :uri), :folding_ranges) do |document|
133
- Requests::FoldingRanges.new(document).run
92
+ finalize_request(result, request)
93
+ end
134
94
  end
135
95
  end
136
96
 
137
- on("textDocument/selectionRange", parallel: true) do |request|
138
- uri = request.dig(:params, :textDocument, :uri)
139
- positions = request.dig(:params, :positions)
140
-
141
- ranges = store.cache_fetch(uri, :selection_ranges) do |document|
142
- Requests::SelectionRanges.new(document).run
143
- end
144
-
145
- # Per the selection range request spec (https://microsoft.github.io/language-server-protocol/specification#textDocument_selectionRange),
146
- # every position in the positions array should have an element at the same index in the response
147
- # array. For positions without a valid selection range, the corresponding element in the response
148
- # array will be nil.
149
-
150
- unless ranges.nil?
151
- positions.map do |position|
152
- ranges.find do |range|
153
- range.cover?(position)
154
- end
97
+ # Finalize a Queue::Result. All IO operations should happen here to avoid any issues with cancelling requests
98
+ sig { params(result: Result, request: T::Hash[Symbol, T.untyped]).void }
99
+ def finalize_request(result, request)
100
+ @mutex.synchronize do
101
+ error = result.error
102
+ response = result.response
103
+
104
+ # If the response include any notifications, go through them and publish each one
105
+ result.notifications.each { |n| @writer.write(method: n.message, params: n.params) }
106
+
107
+ if error
108
+ @writer.write(
109
+ id: request[:id],
110
+ error: {
111
+ code: Constant::ErrorCodes::INTERNAL_ERROR,
112
+ message: error.inspect,
113
+ data: request.to_json,
114
+ },
115
+ )
116
+ elsif response != VOID
117
+ @writer.write(id: request[:id], result: response)
155
118
  end
156
- end
157
- end
158
119
 
159
- on("textDocument/semanticTokens/full", parallel: true) do |request|
160
- store.cache_fetch(request.dig(:params, :textDocument, :uri), :semantic_highlighting) do |document|
161
- T.cast(
162
- Requests::SemanticHighlighting.new(
163
- document,
164
- encoder: Requests::Support::SemanticTokenEncoder.new,
165
- ).run,
166
- LanguageServer::Protocol::Interface::SemanticTokens,
167
- )
120
+ request_time = result.request_time
121
+ if request_time
122
+ @writer.write(method: "telemetry/event", params: telemetry_params(request, request_time, error))
123
+ end
168
124
  end
169
125
  end
170
126
 
171
- on("textDocument/semanticTokens/range", parallel: true) do |request|
172
- document = store.get(request.dig(:params, :textDocument, :uri))
173
- range = request.dig(:params, :range)
174
- start_line = range.dig(:start, :line)
175
- end_line = range.dig(:end, :line)
176
-
177
- Requests::SemanticHighlighting.new(
178
- document,
179
- range: start_line..end_line,
180
- encoder: Requests::Support::SemanticTokenEncoder.new,
181
- ).run
127
+ sig do
128
+ params(
129
+ request: T::Hash[Symbol, T.untyped],
130
+ request_time: Float,
131
+ error: T.nilable(Exception),
132
+ ).returns(T::Hash[Symbol, T.any(String, Float)])
182
133
  end
183
-
184
- on("textDocument/formatting", parallel: true) do |request|
134
+ def telemetry_params(request, request_time, error)
185
135
  uri = request.dig(:params, :textDocument, :uri)
136
+ params = {
137
+ request: request[:method],
138
+ lspVersion: RubyLsp::VERSION,
139
+ requestTime: request_time,
140
+ }
186
141
 
187
- Requests::Formatting.new(uri, store.get(uri)).run
188
- end.on_error do |error|
189
- show_message(Constant::MessageType::ERROR, "Formatting error: #{error.message}")
190
- end
191
-
192
- on("textDocument/onTypeFormatting", parallel: true) do |request|
193
- uri = request.dig(:params, :textDocument, :uri)
194
- position = request.dig(:params, :position)
195
- character = request.dig(:params, :ch)
142
+ if error
143
+ params[:errorClass] = error.class.name
144
+ params[:errorMessage] = error.message
196
145
 
197
- Requests::OnTypeFormatting.new(store.get(uri), position, character).run
198
- end
146
+ log_params = request[:params]
147
+ params[:params] = log_params.reject { |k, _| k == :textDocument }.to_json if log_params
199
148
 
200
- on("textDocument/documentHighlight", parallel: true) do |request|
201
- document = store.get(request.dig(:params, :textDocument, :uri))
202
-
203
- Requests::DocumentHighlight.new(document, request.dig(:params, :position)).run
204
- end
205
-
206
- on("textDocument/codeAction", parallel: true) do |request|
207
- uri = request.dig(:params, :textDocument, :uri)
208
- document = store.get(uri)
209
- range = request.dig(:params, :range)
210
- start_line = range.dig(:start, :line)
211
- end_line = range.dig(:end, :line)
212
-
213
- Requests::CodeActions.new(uri, document, start_line..end_line).run
214
- end
215
-
216
- on("textDocument/inlayHint", parallel: true) do |request|
217
- document = store.get(request.dig(:params, :textDocument, :uri))
218
- range = request.dig(:params, :range)
219
- start_line = range.dig(:start, :line)
220
- end_line = range.dig(:end, :line)
221
-
222
- Requests::InlayHints.new(document, start_line..end_line).run
223
- end
224
-
225
- on("$/cancelRequest") do |request|
226
- cancel_request(request[:params][:id])
227
- Handler::VOID
228
- end
229
-
230
- on("textDocument/diagnostic", parallel: true) do |request|
231
- uri = request.dig(:params, :textDocument, :uri)
232
- response = store.cache_fetch(uri, :diagnostics) do |document|
233
- Requests::Diagnostics.new(uri, document).run
149
+ backtrace = error.backtrace
150
+ params[:backtrace] = backtrace.map { |bt| bt.sub(/^#{Dir.home}/, "~") }.join("\n") if backtrace
234
151
  end
235
152
 
236
- { kind: "full", items: response.map(&:to_lsp_diagnostic) } if response
237
- end.on_error do |error|
238
- show_message(Constant::MessageType::ERROR, "Error running diagnostics: #{error.message}")
239
- end
240
-
241
- on("shutdown") { shutdown }
242
-
243
- on("exit") do
244
- # We return zero if shutdown has already been received or one otherwise as per the recommendation in the spec
245
- # https://microsoft.github.io/language-server-protocol/specification/#exit
246
- status = store.empty? ? 0 : 1
247
- exit(status)
153
+ params[:uri] = uri.sub(%r{.*://#{Dir.home}}, "~") if uri
154
+ params
248
155
  end
249
156
  end
250
157
  end
@@ -0,0 +1,78 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ # Used to indicate that a request shouldn't return a response
6
+ VOID = T.let(Object.new.freeze, Object)
7
+
8
+ # A notification to be sent to the client
9
+ class Notification
10
+ extend T::Sig
11
+
12
+ sig { returns(String) }
13
+ attr_reader :message
14
+
15
+ sig { returns(Object) }
16
+ attr_reader :params
17
+
18
+ sig { params(message: String, params: Object).void }
19
+ def initialize(message:, params:)
20
+ @message = message
21
+ @params = params
22
+ end
23
+ end
24
+
25
+ # The final result of running a request before its IO is finalized
26
+ class Result
27
+ extend T::Sig
28
+
29
+ sig { returns(T.untyped) }
30
+ attr_reader :response
31
+
32
+ sig { returns(T::Array[Notification]) }
33
+ attr_reader :notifications
34
+
35
+ sig { returns(T.nilable(Exception)) }
36
+ attr_reader :error
37
+
38
+ sig { returns(T.nilable(Float)) }
39
+ attr_reader :request_time
40
+
41
+ sig do
42
+ params(
43
+ response: T.untyped,
44
+ notifications: T::Array[Notification],
45
+ error: T.nilable(Exception),
46
+ request_time: T.nilable(Float),
47
+ ).void
48
+ end
49
+ def initialize(response:, notifications:, error: nil, request_time: nil)
50
+ @response = response
51
+ @notifications = notifications
52
+ @error = error
53
+ @request_time = request_time
54
+ end
55
+ end
56
+
57
+ # A request that will sit in the queue until it's executed
58
+ class Job
59
+ extend T::Sig
60
+
61
+ sig { returns(T::Hash[Symbol, T.untyped]) }
62
+ attr_reader :request
63
+
64
+ sig { returns(T::Boolean) }
65
+ attr_reader :cancelled
66
+
67
+ sig { params(request: T::Hash[Symbol, T.untyped], cancelled: T::Boolean).void }
68
+ def initialize(request:, cancelled:)
69
+ @request = request
70
+ @cancelled = cancelled
71
+ end
72
+
73
+ sig { void }
74
+ def cancel
75
+ @cancelled = true
76
+ end
77
+ end
78
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-01-16 00:00:00.000000000 Z
11
+ date: 2023-02-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: language_server-protocol
@@ -44,20 +44,20 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 5.0.0
47
+ version: '6'
48
48
  - - "<"
49
49
  - !ruby/object:Gem::Version
50
- version: '6'
50
+ version: '7'
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
55
  - - ">="
56
56
  - !ruby/object:Gem::Version
57
- version: 5.0.0
57
+ version: '6'
58
58
  - - "<"
59
59
  - !ruby/object:Gem::Version
60
- version: '6'
60
+ version: '7'
61
61
  description: An opinionated language server for Ruby
62
62
  email:
63
63
  - ruby@shopify.com
@@ -72,9 +72,8 @@ files:
72
72
  - exe/ruby-lsp
73
73
  - lib/ruby-lsp.rb
74
74
  - lib/ruby_lsp/document.rb
75
- - lib/ruby_lsp/handler.rb
75
+ - lib/ruby_lsp/executor.rb
76
76
  - lib/ruby_lsp/internal.rb
77
- - lib/ruby_lsp/queue.rb
78
77
  - lib/ruby_lsp/requests.rb
79
78
  - lib/ruby_lsp/requests/base_request.rb
80
79
  - lib/ruby_lsp/requests/code_actions.rb
@@ -87,9 +86,12 @@ files:
87
86
  - lib/ruby_lsp/requests/hover.rb
88
87
  - lib/ruby_lsp/requests/inlay_hints.rb
89
88
  - lib/ruby_lsp/requests/on_type_formatting.rb
89
+ - lib/ruby_lsp/requests/path_completion.rb
90
90
  - lib/ruby_lsp/requests/selection_ranges.rb
91
91
  - lib/ruby_lsp/requests/semantic_highlighting.rb
92
+ - lib/ruby_lsp/requests/support/annotation.rb
92
93
  - lib/ruby_lsp/requests/support/highlight_target.rb
94
+ - lib/ruby_lsp/requests/support/prefix_tree.rb
93
95
  - lib/ruby_lsp/requests/support/rails_document_client.rb
94
96
  - lib/ruby_lsp/requests/support/rubocop_diagnostic.rb
95
97
  - lib/ruby_lsp/requests/support/rubocop_diagnostics_runner.rb
@@ -97,10 +99,11 @@ files:
97
99
  - lib/ruby_lsp/requests/support/rubocop_runner.rb
98
100
  - lib/ruby_lsp/requests/support/selection_range.rb
99
101
  - lib/ruby_lsp/requests/support/semantic_token_encoder.rb
102
+ - lib/ruby_lsp/requests/support/sorbet.rb
100
103
  - lib/ruby_lsp/requests/support/source_uri.rb
101
- - lib/ruby_lsp/requests/support/syntax_error_diagnostic.rb
102
104
  - lib/ruby_lsp/server.rb
103
105
  - lib/ruby_lsp/store.rb
106
+ - lib/ruby_lsp/utils.rb
104
107
  homepage: https://github.com/Shopify/ruby-lsp
105
108
  licenses:
106
109
  - MIT
@@ -1,118 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "ruby_lsp/requests"
5
- require "ruby_lsp/store"
6
- require "ruby_lsp/queue"
7
-
8
- module RubyLsp
9
- Interface = LanguageServer::Protocol::Interface
10
- Constant = LanguageServer::Protocol::Constant
11
- Transport = LanguageServer::Protocol::Transport
12
-
13
- class Handler
14
- extend T::Sig
15
- VOID = T.let(Object.new.freeze, Object)
16
-
17
- class RequestHandler < T::Struct
18
- extend T::Sig
19
-
20
- const :action, T.proc.params(request: T::Hash[Symbol, T.untyped]).returns(T.untyped)
21
- const :parallel, T::Boolean
22
- prop :error_handler,
23
- T.nilable(T.proc.params(error: Exception, request: T::Hash[Symbol, T.untyped]).void)
24
-
25
- # A proc that runs in case a request has errored. Receives the error and the original request as arguments. Useful
26
- # for displaying window messages on errors
27
- sig do
28
- params(
29
- block: T.proc.bind(Handler).params(error: Exception, request: T::Hash[Symbol, T.untyped]).void,
30
- ).void
31
- end
32
- def on_error(&block)
33
- self.error_handler = block
34
- end
35
- end
36
-
37
- class << self
38
- extend T::Sig
39
-
40
- sig { params(blk: T.proc.bind(Handler).params(arg0: T.untyped).void).void }
41
- def start(&blk)
42
- handler = new
43
- handler.instance_exec(&blk)
44
- handler.start
45
- end
46
- end
47
-
48
- sig { returns(Store) }
49
- attr_reader :store
50
-
51
- sig { void }
52
- def initialize
53
- @writer = T.let(Transport::Stdio::Writer.new, Transport::Stdio::Writer)
54
- @reader = T.let(Transport::Stdio::Reader.new, Transport::Stdio::Reader)
55
- @handlers = T.let({}, T::Hash[String, RequestHandler])
56
- @store = T.let(Store.new, Store)
57
- @queue = T.let(Queue.new(@writer, @handlers), Queue)
58
- end
59
-
60
- sig { void }
61
- def start
62
- warn("Starting Ruby LSP...")
63
-
64
- @reader.read do |request|
65
- handler = @handlers[request[:method]]
66
- next if handler.nil?
67
-
68
- if handler.parallel
69
- @queue.push(request)
70
- else
71
- result = @queue.execute(request)
72
- @queue.finalize_request(result, request)
73
- end
74
- end
75
- end
76
-
77
- private
78
-
79
- sig { params(id: T.any(String, Integer)).void }
80
- def cancel_request(id)
81
- @queue.cancel(id)
82
- end
83
-
84
- sig do
85
- params(
86
- msg: String,
87
- parallel: T::Boolean,
88
- blk: T.proc.bind(Handler).params(request: T::Hash[Symbol, T.untyped]).returns(T.untyped),
89
- ).returns(RequestHandler)
90
- end
91
- def on(msg, parallel: false, &blk)
92
- @handlers[msg] = RequestHandler.new(action: blk, parallel: parallel)
93
- end
94
-
95
- sig { void }
96
- def shutdown
97
- warn("Shutting down Ruby LSP...")
98
- @queue.shutdown
99
- store.clear
100
- end
101
-
102
- sig { params(uri: String).void }
103
- def clear_diagnostics(uri)
104
- @writer.write(
105
- method: "textDocument/publishDiagnostics",
106
- params: Interface::PublishDiagnosticsParams.new(uri: uri, diagnostics: []),
107
- )
108
- end
109
-
110
- sig { params(type: Integer, message: String).void }
111
- def show_message(type, message)
112
- @writer.write(
113
- method: "window/showMessage",
114
- params: Interface::ShowMessageParams.new(type: type, message: message),
115
- )
116
- end
117
- end
118
- end