mbeditor 0.12.9 → 0.13.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/CHANGELOG.md +150 -0
- data/app/assets/javascripts/mbeditor/application.js +7 -1
- data/app/assets/javascripts/mbeditor/collaboration_service.js +31 -0
- data/app/assets/javascripts/mbeditor/color_provider.js +5 -0
- data/app/assets/javascripts/mbeditor/components/CollapsibleSection.js +3 -1
- data/app/assets/javascripts/mbeditor/components/EditorPanel.js +102 -25
- data/app/assets/javascripts/mbeditor/components/FileTree.js +6 -1
- data/app/assets/javascripts/mbeditor/components/GitPanel.js +10 -1
- data/app/assets/javascripts/mbeditor/components/ImportConflictModal.js +15 -8
- data/app/assets/javascripts/mbeditor/components/ImportDialog.js +216 -0
- data/app/assets/javascripts/mbeditor/components/MbeditorApp.js +598 -130
- data/app/assets/javascripts/mbeditor/components/ModelGraph.js +25 -6
- data/app/assets/javascripts/mbeditor/components/ProblemsPanel.js +162 -6
- data/app/assets/javascripts/mbeditor/components/QuickOpenDialog.js +39 -33
- data/app/assets/javascripts/mbeditor/components/TabBar.js +11 -2
- data/app/assets/javascripts/mbeditor/components/TestRunPanel.js +312 -0
- data/app/assets/javascripts/mbeditor/editor_plugins.js +427 -111
- data/app/assets/javascripts/mbeditor/file_import.js +78 -0
- data/app/assets/javascripts/mbeditor/file_service.js +122 -18
- data/app/assets/javascripts/mbeditor/git_service.js +130 -8
- data/app/assets/javascripts/mbeditor/history_service.js +33 -38
- data/app/assets/javascripts/mbeditor/log_service.js +4 -0
- data/app/assets/javascripts/mbeditor/search_service.js +30 -2
- data/app/assets/javascripts/mbeditor/tab_manager.js +59 -6
- data/app/assets/javascripts/mbeditor/websocket_service.js +88 -4
- data/app/assets/stylesheets/mbeditor/editor.css +268 -53
- data/app/channels/mbeditor/channel_authentication.rb +7 -0
- data/app/channels/mbeditor/editor_channel.rb +6 -3
- data/app/controllers/mbeditor/application_controller.rb +5 -0
- data/app/controllers/mbeditor/editors_controller.rb +173 -29
- data/app/controllers/mbeditor/git_controller.rb +3 -3
- data/app/controllers/mbeditor/logs_controller.rb +3 -1
- data/app/services/mbeditor/collaboration_doc_store.rb +7 -0
- data/app/services/mbeditor/editor_state_service.rb +36 -26
- data/app/services/mbeditor/exclusion_matcher.rb +12 -10
- data/app/services/mbeditor/file_operation_service.rb +38 -3
- data/app/services/mbeditor/file_tree_service.rb +30 -2
- data/app/services/mbeditor/git_combined_diff_service.rb +13 -3
- data/app/services/mbeditor/git_commit_detail_service.rb +20 -16
- data/app/services/mbeditor/git_diff_service.rb +5 -1
- data/app/services/mbeditor/git_info_service.rb +20 -8
- data/app/services/mbeditor/git_line_diff_service.rb +6 -2
- data/app/services/mbeditor/git_service.rb +65 -15
- data/app/services/mbeditor/js_definition_service.rb +3 -1
- data/app/services/mbeditor/js_globals_service.rb +7 -4
- data/app/services/mbeditor/js_members_service.rb +3 -2
- data/app/services/mbeditor/js_program_service.rb +15 -5
- data/app/services/mbeditor/js_syntax_check_service.rb +15 -4
- data/app/services/mbeditor/process_runner.rb +42 -12
- data/app/services/mbeditor/ri_definition_service.rb +8 -1
- data/app/services/mbeditor/route_service.rb +45 -8
- data/app/services/mbeditor/rubocop_run_service.rb +86 -0
- data/app/services/mbeditor/ruby_definition_service.rb +23 -4
- data/app/services/mbeditor/schema_service.rb +65 -64
- data/app/services/mbeditor/search_replace_service.rb +31 -5
- data/app/services/mbeditor/test_runner_service.rb +98 -10
- data/lib/mbeditor/cable_log_filter.rb +8 -2
- data/lib/mbeditor/configuration.rb +12 -1
- data/lib/mbeditor/editor_bootstrap.rb +18 -12
- data/lib/mbeditor/engine.rb +22 -3
- data/lib/mbeditor/exception_log.rb +2 -2
- data/lib/mbeditor/pending_migrations.rb +33 -0
- data/lib/mbeditor/rack/handle_pending_migrations.rb +25 -15
- data/lib/mbeditor/rack/pending_migration_bypass.rb +104 -0
- data/lib/mbeditor/rack/silence_ping_request.rb +10 -2
- data/lib/mbeditor/route_map.rb +2 -0
- data/lib/mbeditor/ruby_lsp_client.rb +71 -12
- data/lib/mbeditor/version.rb +1 -1
- metadata +7 -2
|
@@ -5,6 +5,7 @@ require "json"
|
|
|
5
5
|
require "digest"
|
|
6
6
|
require "shellwords"
|
|
7
7
|
require "timeout"
|
|
8
|
+
require "uri"
|
|
8
9
|
|
|
9
10
|
module Mbeditor
|
|
10
11
|
# Manages a persistent ruby-lsp process per workspace and speaks the
|
|
@@ -88,10 +89,13 @@ module Mbeditor
|
|
|
88
89
|
|
|
89
90
|
# A snapshot for the editor's status indicator. Deliberately does not start
|
|
90
91
|
# the process — asking "how are you?" must not be what boots the server.
|
|
92
|
+
#
|
|
93
|
+
# Deliberately lock-free: @state_mutex is held for the whole of a start
|
|
94
|
+
# (up to INIT_TIMEOUT) and a restart, and a status chip polled every 10s
|
|
95
|
+
# must not queue behind a handshake. Each field is one reference read, so
|
|
96
|
+
# the worst case is a snapshot that is one transition out of date.
|
|
91
97
|
def health
|
|
92
|
-
@
|
|
93
|
-
{ state: @state, restarts: @crash_times.length, error: @last_error }
|
|
94
|
-
end
|
|
98
|
+
{ state: @state, restarts: @crash_times.length, error: @last_error }
|
|
95
99
|
end
|
|
96
100
|
|
|
97
101
|
# Clears the crash budget so a client latched at :failed can be revived
|
|
@@ -109,22 +113,37 @@ module Mbeditor
|
|
|
109
113
|
end
|
|
110
114
|
|
|
111
115
|
# Syncs the document (didOpen / full-text didChange) and issues a request
|
|
112
|
-
# against it
|
|
113
|
-
#
|
|
116
|
+
# against it, so concurrent Puma threads can't interleave a positional
|
|
117
|
+
# request with a stale document.
|
|
114
118
|
# +params+ is an explicit hash (not keywords) so it can't collide with the
|
|
115
119
|
# +timeout:+ keyword.
|
|
120
|
+
#
|
|
121
|
+
# @doc_mutex covers the sync and the write, not the wait: LSP processes
|
|
122
|
+
# messages in order, so once the request is on the wire behind its didOpen
|
|
123
|
+
# the server already sees the right document. Holding it across the
|
|
124
|
+
# round-trip serialised every ruby-lsp request in the process for up to the
|
|
125
|
+
# full request timeout.
|
|
116
126
|
def request_with_document(method, path, content, params = {}, timeout: nil)
|
|
117
127
|
raise NotReadyError, "ruby-lsp is not running" unless ready?
|
|
118
128
|
|
|
119
|
-
uri =
|
|
120
|
-
|
|
129
|
+
uri = file_uri(path)
|
|
130
|
+
timeout ||= (Mbeditor.configuration.ruby_lsp_timeout || 3).to_f
|
|
131
|
+
id, queue = @doc_mutex.synchronize do
|
|
121
132
|
sync_document(uri, content)
|
|
122
|
-
|
|
133
|
+
send_request(method, params.merge(textDocument: { uri: uri }))
|
|
123
134
|
end
|
|
135
|
+
await_response(method, id, queue, timeout)
|
|
124
136
|
end
|
|
125
137
|
|
|
126
138
|
def request(method, params, timeout: nil)
|
|
127
139
|
timeout ||= (Mbeditor.configuration.ruby_lsp_timeout || 3).to_f
|
|
140
|
+
id, queue = send_request(method, params)
|
|
141
|
+
await_response(method, id, queue, timeout)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Registers a response queue and puts the request on the wire. Returns
|
|
145
|
+
# [id, queue] for #await_response.
|
|
146
|
+
def send_request(method, params)
|
|
128
147
|
queue = Queue.new
|
|
129
148
|
id = @pending_mutex.synchronize do
|
|
130
149
|
@next_id += 1
|
|
@@ -132,15 +151,29 @@ module Mbeditor
|
|
|
132
151
|
@next_id
|
|
133
152
|
end
|
|
134
153
|
|
|
135
|
-
|
|
154
|
+
begin
|
|
155
|
+
write_message({ jsonrpc: "2.0", id: id, method: method, params: params })
|
|
156
|
+
rescue StandardError
|
|
157
|
+
@pending_mutex.synchronize { @pending.delete(id) }
|
|
158
|
+
raise
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
[id, queue]
|
|
162
|
+
end
|
|
136
163
|
|
|
164
|
+
def await_response(method, id, queue, timeout)
|
|
137
165
|
msg = pop_with_timeout(queue, timeout)
|
|
138
|
-
|
|
166
|
+
if msg.nil?
|
|
167
|
+
# Nobody is going to read this answer; tell the server to stop
|
|
168
|
+
# computing it rather than leave it indexing for an abandoned caller.
|
|
169
|
+
cancel_request(id)
|
|
170
|
+
raise TimeoutError, "#{method} timed out after #{timeout}s"
|
|
171
|
+
end
|
|
139
172
|
raise Error, msg["error"]["message"].to_s if msg["error"]
|
|
140
173
|
|
|
141
174
|
msg["result"]
|
|
142
175
|
ensure
|
|
143
|
-
@pending_mutex.synchronize { @pending.delete(id) }
|
|
176
|
+
@pending_mutex.synchronize { @pending.delete(id) }
|
|
144
177
|
end
|
|
145
178
|
|
|
146
179
|
# Queue#pop only accepts a timeout: keyword from Ruby 3.2 onwards, and the
|
|
@@ -187,6 +220,24 @@ module Mbeditor
|
|
|
187
220
|
|
|
188
221
|
private
|
|
189
222
|
|
|
223
|
+
# Ruby 3.4 renamed the RFC2396 parser and deprecated escape on the RFC3986
|
|
224
|
+
# one DEFAULT_PARSER now points at, so name it explicitly where it exists.
|
|
225
|
+
URI_PARSER = defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
|
|
226
|
+
private_constant :URI_PARSER
|
|
227
|
+
|
|
228
|
+
# A workspace path is not a URI: a space raises URI::InvalidURIError inside
|
|
229
|
+
# ruby-lsp and a `#` silently truncates the path at the fragment. Every
|
|
230
|
+
# file:// URI this class builds goes through here.
|
|
231
|
+
def file_uri(path)
|
|
232
|
+
"file://#{URI_PARSER.escape(path.to_s)}"
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
def cancel_request(id)
|
|
236
|
+
write_message({ jsonrpc: "2.0", method: "$/cancelRequest", params: { id: id } })
|
|
237
|
+
rescue StandardError
|
|
238
|
+
nil
|
|
239
|
+
end
|
|
240
|
+
|
|
190
241
|
def ensure_started
|
|
191
242
|
@state_mutex.synchronize do
|
|
192
243
|
return if @state == :ready || @state == :failed
|
|
@@ -221,7 +272,7 @@ module Mbeditor
|
|
|
221
272
|
|
|
222
273
|
result = request("initialize", {
|
|
223
274
|
processId: Process.pid,
|
|
224
|
-
rootUri:
|
|
275
|
+
rootUri: file_uri(@root),
|
|
225
276
|
capabilities: {
|
|
226
277
|
textDocument: {
|
|
227
278
|
synchronization: { didSave: false },
|
|
@@ -365,6 +416,14 @@ module Mbeditor
|
|
|
365
416
|
end
|
|
366
417
|
|
|
367
418
|
def cleanup_process
|
|
419
|
+
# A failed handshake (INIT_TIMEOUT on a large app) otherwise orphans a
|
|
420
|
+
# ruby-lsp that is still indexing. No-op once the child has exited.
|
|
421
|
+
begin
|
|
422
|
+
Process.kill("-KILL", @wait_thr.pid) if @wait_thr
|
|
423
|
+
rescue StandardError
|
|
424
|
+
nil
|
|
425
|
+
end
|
|
426
|
+
|
|
368
427
|
[@stdin, @stdout, @stderr].each do |io|
|
|
369
428
|
begin
|
|
370
429
|
io&.close
|
data/lib/mbeditor/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mbeditor
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Oliver Noonan
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-08-
|
|
11
|
+
date: 2026-08-20 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: rails
|
|
@@ -71,6 +71,7 @@ files:
|
|
|
71
71
|
- app/assets/javascripts/mbeditor/components/FileTree.js
|
|
72
72
|
- app/assets/javascripts/mbeditor/components/GitPanel.js
|
|
73
73
|
- app/assets/javascripts/mbeditor/components/ImportConflictModal.js
|
|
74
|
+
- app/assets/javascripts/mbeditor/components/ImportDialog.js
|
|
74
75
|
- app/assets/javascripts/mbeditor/components/LogPanel.js
|
|
75
76
|
- app/assets/javascripts/mbeditor/components/MbeditorApp.js
|
|
76
77
|
- app/assets/javascripts/mbeditor/components/ModelGraph.js
|
|
@@ -79,6 +80,7 @@ files:
|
|
|
79
80
|
- app/assets/javascripts/mbeditor/components/ShortcutHelp.js
|
|
80
81
|
- app/assets/javascripts/mbeditor/components/TabBar.js
|
|
81
82
|
- app/assets/javascripts/mbeditor/components/TestResultsPanel.js
|
|
83
|
+
- app/assets/javascripts/mbeditor/components/TestRunPanel.js
|
|
82
84
|
- app/assets/javascripts/mbeditor/conflict_parser.js
|
|
83
85
|
- app/assets/javascripts/mbeditor/editor_plugins.js
|
|
84
86
|
- app/assets/javascripts/mbeditor/editor_store.js
|
|
@@ -134,6 +136,7 @@ files:
|
|
|
134
136
|
- app/services/mbeditor/redmine_service.rb
|
|
135
137
|
- app/services/mbeditor/ri_definition_service.rb
|
|
136
138
|
- app/services/mbeditor/route_service.rb
|
|
139
|
+
- app/services/mbeditor/rubocop_run_service.rb
|
|
137
140
|
- app/services/mbeditor/ruby_definition_service.rb
|
|
138
141
|
- app/services/mbeditor/safe_path.rb
|
|
139
142
|
- app/services/mbeditor/schema_service.rb
|
|
@@ -151,8 +154,10 @@ files:
|
|
|
151
154
|
- lib/mbeditor/engine.rb
|
|
152
155
|
- lib/mbeditor/exception_log.rb
|
|
153
156
|
- lib/mbeditor/mount_path.rb
|
|
157
|
+
- lib/mbeditor/pending_migrations.rb
|
|
154
158
|
- lib/mbeditor/private_routes.rb
|
|
155
159
|
- lib/mbeditor/rack/handle_pending_migrations.rb
|
|
160
|
+
- lib/mbeditor/rack/pending_migration_bypass.rb
|
|
156
161
|
- lib/mbeditor/rack/resilient_router.rb
|
|
157
162
|
- lib/mbeditor/rack/silence_ping_request.rb
|
|
158
163
|
- lib/mbeditor/route_map.rb
|