Skip to content

Commit 01047e0

Browse files
committed
Implement LSP runner
1 parent a600e02 commit 01047e0

File tree

12 files changed

+30
-371
lines changed

12 files changed

+30
-371
lines changed

README.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,16 +52,15 @@ See the [documentation](https://shopify.github.io/ruby-lsp-rails) for more in-de
5252
5353
## How It Works
5454

55-
This gem consists of two components that enable enhanced Rails functionality in the editor:
55+
When Ruby LSP Rails starts, it spawns a `rails runner` instance which runs
56+
`[server.rb](https://github.com/Shopify/ruby-lsp-rails/blob/main/lib/ruby_lsp/ruby_lsp_rails/server.rb)`.
57+
The addon communicates with this process over a pipe (i.e. `stdin` and `stdout`) to fetch runtime information about the application.
5658

57-
1. A Rack app that automatically exposes APIs when Rails server is running
58-
1. A Ruby LSP addon that connects to the exposed APIs to fetch runtime information from the Rails server
59-
60-
This is why the Rails server needs to be running for some features to work.
59+
When extension is stopped (e.g. by quitting the editor), the server instance is shut down.
6160

6261
> [!NOTE]
63-
> There is no need to restart the Ruby LSP every time the Rails server is booted.
64-
> If the server is shut down, the extra features will temporarily disappear and reappear once the server is running again.
62+
> Prior to v0.3, `ruby-lsp-rails` used a different approach which involved mounting a Rack application with in the Rails app.
63+
> That approach was brittle and susceptible to the application's configuration, such as routing and middleware.
6564
6665
## Contributing
6766

lib/ruby-lsp-rails.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
11
# typed: strict
22
# frozen_string_literal: true
33

4-
require "sorbet-runtime"
5-
require "pathname"
6-
74
require "ruby_lsp_rails/version"
8-
require "ruby_lsp_rails/railtie"
95

106
module RubyLsp
117
# # Supported features

lib/ruby_lsp/ruby_lsp_rails/addon.rb

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
require "ruby_lsp/addon"
55

6-
require_relative "rails_client"
6+
require_relative "runner_client"
77
require_relative "hover"
88
require_relative "code_lens"
99

@@ -12,18 +12,18 @@ module Rails
1212
class Addon < ::RubyLsp::Addon
1313
extend T::Sig
1414

15-
sig { returns(RailsClient) }
15+
sig { returns(RunnerClient) }
1616
def client
17-
@client ||= T.let(RailsClient.new, T.nilable(RailsClient))
17+
@client ||= T.let(RunnerClient.new, T.nilable(RunnerClient))
1818
end
1919

2020
sig { override.params(message_queue: Thread::Queue).void }
21-
def activate(message_queue)
22-
client.check_if_server_is_running!
23-
end
21+
def activate(message_queue); end
2422

2523
sig { override.void }
26-
def deactivate; end
24+
def deactivate
25+
client.shutdown
26+
end
2727

2828
# Creates a new CodeLens listener. This method is invoked on every CodeLens request
2929
sig do

lib/ruby_lsp/ruby_lsp_rails/hover.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class Hover
2222

2323
sig do
2424
params(
25-
client: RailsClient,
25+
client: RunnerClient,
2626
response_builder: ResponseBuilders::Hover,
2727
nesting: T::Array[String],
2828
index: RubyIndexer::Index,

lib/ruby_lsp/ruby_lsp_rails/rails_client.rb

Lines changed: 0 additions & 77 deletions
This file was deleted.

lib/ruby_lsp_rails/rack_app.rb

Lines changed: 0 additions & 58 deletions
This file was deleted.

lib/ruby_lsp_rails/railtie.rb

Lines changed: 0 additions & 38 deletions
This file was deleted.

test/ruby_lsp_rails/addon_test.rb

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,6 @@ class AddonTest < ActiveSupport::TestCase
1010
addon = Addon.new
1111
assert_equal("Ruby LSP Rails", addon.name)
1212
end
13-
14-
test "activate checks if Rails server is running" do
15-
rails_client = stub("rails_client", check_if_server_is_running!: true)
16-
17-
RubyLsp::Rails::RailsClient.stubs(instance: rails_client)
18-
19-
addon = Addon.new
20-
queue = Thread::Queue.new
21-
22-
capture_io { assert(addon.activate(queue)) }
23-
ensure
24-
T.must(queue).close
25-
end
2613
end
2714
end
2815
end

test/ruby_lsp_rails/hover_test.rb

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
# frozen_string_literal: true
33

44
require "test_helper"
5+
# require "ruby_lsp/ruby_lsp_rails/server"
56

67
module RubyLsp
78
module Rails
89
class HoverTest < ActiveSupport::TestCase
910
setup do
10-
File.write("#{Dir.pwd}/test/dummy/tmp/app_uri.txt", "http://localhost:3000")
11-
@client = RailsClient.new
1211
@message_queue = Thread::Queue.new
1312

1413
# Build the Rails documents index ahead of time
@@ -23,7 +22,7 @@ class HoverTest < ActiveSupport::TestCase
2322

2423
test "hook returns model column information" do
2524
expected_response = {
26-
schema_file: "#{@client.root}/db/schema.rb",
25+
schema_file: "#{dummy_root}/db/schema.rb",
2726
columns: [
2827
["id", "integer"],
2928
["first_name", "string"],
@@ -34,8 +33,7 @@ class HoverTest < ActiveSupport::TestCase
3433
],
3534
}
3635

37-
stub_http_request("200", expected_response.to_json)
38-
@client.stubs(:check_if_server_is_running!)
36+
RunnerClient.any_instance.stubs(model: expected_response)
3937

4038
response = hover_on_source(<<~RUBY, { line: 3, character: 0 })
4139
class User < ApplicationRecord
@@ -50,7 +48,7 @@ class User < ApplicationRecord
5048
```
5149
5250
**Definitions**: [fake.rb](file:///fake.rb#L1,1-2,4)
53-
[Schema](file://#{@client.root}/db/schema.rb)
51+
[Schema](file://#{dummy_root}/db/schema.rb)
5452
5553
5654
**id**: integer
@@ -69,7 +67,7 @@ class User < ApplicationRecord
6967

7068
test "return column information for namespaced models" do
7169
expected_response = {
72-
schema_file: "#{@client.root}/db/schema.rb",
70+
schema_file: "#{dummy_root}/db/schema.rb",
7371
columns: [
7472
["id", "integer"],
7573
["first_name", "string"],
@@ -80,8 +78,7 @@ class User < ApplicationRecord
8078
],
8179
}
8280

83-
stub_http_request("200", expected_response.to_json)
84-
@client.stubs(:check_if_server_is_running!)
81+
RunnerClient.any_instance.stubs(model: expected_response)
8582

8683
response = hover_on_source(<<~RUBY, { line: 4, character: 6 })
8784
module Blog
@@ -93,7 +90,7 @@ class User < ApplicationRecord
9390
RUBY
9491

9592
assert_equal(<<~CONTENT.chomp, response.contents.value)
96-
[Schema](file://#{@client.root}/db/schema.rb)
93+
[Schema](file://#{dummy_root}/db/schema.rb)
9794
9895
**id**: integer
9996
@@ -111,12 +108,11 @@ class User < ApplicationRecord
111108

112109
test "handles `db/structure.sql` instead of `db/schema.rb`" do
113110
expected_response = {
114-
schema_file: "#{@client.root}/db/structure.sql",
111+
schema_file: "#{dummy_root}/db/structure.sql",
115112
columns: [],
116113
}
117114

118-
stub_http_request("200", expected_response.to_json)
119-
@client.stubs(:check_if_server_is_running!)
115+
RunnerClient.any_instance.stubs(model: expected_response)
120116

121117
response = hover_on_source(<<~RUBY, { line: 3, character: 0 })
122118
class User < ApplicationRecord
@@ -127,7 +123,7 @@ class User < ApplicationRecord
127123

128124
assert_includes(
129125
response.contents.value,
130-
"[Schema](file://#{@client.root}/db/structure.sql)",
126+
"[Schema](file://#{dummy_root}/db/structure.sql)",
131127
)
132128
end
133129

@@ -137,8 +133,7 @@ class User < ApplicationRecord
137133
columns: [],
138134
}
139135

140-
stub_http_request("200", expected_response.to_json)
141-
@client.stubs(:check_if_server_is_running!)
136+
RunnerClient.any_instance.stubs(model: expected_response)
142137

143138
response = hover_on_source(<<~RUBY, { line: 3, character: 0 })
144139
class User < ApplicationRecord
@@ -213,6 +208,10 @@ def hover_on_source(source, position)
213208
assert_nil(response.error)
214209
response.response
215210
end
211+
212+
def dummy_root
213+
File.expand_path("#{__dir__}/../../test/dummy")
214+
end
216215
end
217216
end
218217
end

0 commit comments

Comments
 (0)