ruby-lsp-rails 0.3.11 → 0.3.13

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8e684ecacd45b09fee18e386a95d0dfa61bd3cce2c64869bf34f711d9d0c2fa3
4
- data.tar.gz: c575d062c88f997967989f1cca84a1241fb6d07750a0535e122112b890e9dd0e
3
+ metadata.gz: e2543aa7d39f0a6b231112f9ddb365692c7e8d06eb14681da551ab55fd8f5a4d
4
+ data.tar.gz: e466ccd6d90934e083e638efdcedfb5d6b8f85fbce70b139e1542eeb2ab8a139
5
5
  SHA512:
6
- metadata.gz: 17c1805f2e1d7363e2734d6983fdba8b11b72e083ff07b0d872745121f9b4c1d20898e439a19c7dc9f179f8729260cf2f90e701e47967d4901576166fe66c420
7
- data.tar.gz: '039f940ff0ea3247316609b379396a7096ada44ed0b4127969223c3277d946bbbd913e106ede27912fc29c53a0e349999231e1561940e5d75ff6adbf0cea1a89'
6
+ metadata.gz: 8f7c82462682d93fd6b944c2705c8b62b424b4abc3636d1f2540eeee1ab9f7e2896eb77d338697bb65a0a64752529085f38e49bd5a75bfc668fa9d31dd5b0d10
7
+ data.tar.gz: a8978fdebb07ba8b76dd10a725b3b3c736961f103cefa806fbc0302b494516e0a196105bf7fac9d114c963a62c8a706959d53f1509a4ed343e2e9d24633c4372
@@ -13,6 +13,7 @@ require_relative "hover"
13
13
  require_relative "code_lens"
14
14
  require_relative "document_symbol"
15
15
  require_relative "definition"
16
+ require_relative "indexing_enhancement"
16
17
 
17
18
  module RubyLsp
18
19
  module Rails
@@ -35,6 +36,8 @@ module RubyLsp
35
36
  # Start booting the real client in a background thread. Until this completes, the client will be a NullClient
36
37
  Thread.new { @client = RunnerClient.create_client }
37
38
  register_additional_file_watchers(global_state: global_state, message_queue: message_queue)
39
+
40
+ T.must(@global_state).index.register_enhancement(IndexingEnhancement.new)
38
41
  end
39
42
 
40
43
  sig { override.void }
@@ -77,7 +80,9 @@ module RubyLsp
77
80
 
78
81
  sig do
79
82
  override.params(
80
- response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::Location],
83
+ response_builder: ResponseBuilders::CollectionResponseBuilder[T.any(
84
+ Interface::Location, Interface::LocationLink
85
+ )],
81
86
  uri: URI::Generic,
82
87
  node_context: NodeContext,
83
88
  dispatcher: Prism::Dispatcher,
@@ -51,7 +51,7 @@ module RubyLsp
51
51
  # class AddFirstNameToUsers < ActiveRecord::Migration[7.1]
52
52
  # # ...
53
53
  # end
54
- # ````
54
+ # ```
55
55
  #
56
56
  # The code lenses will be displayed above the class and above each test method.
57
57
  #
@@ -17,7 +17,7 @@ module RubyLsp
17
17
  # # Example
18
18
  #
19
19
  # ```ruby
20
- # before_action :foo # <- Go to definition on this symbol will jump to the method if it is defined in the same class
20
+ # before_action :foo # <- Go to definition on this symbol will jump to the method
21
21
  # ```
22
22
  #
23
23
  # Notes for named routes:
@@ -34,7 +34,9 @@ module RubyLsp
34
34
  sig do
35
35
  params(
36
36
  client: RunnerClient,
37
- response_builder: ResponseBuilders::CollectionResponseBuilder[Interface::Location],
37
+ response_builder: RubyLsp::ResponseBuilders::CollectionResponseBuilder[T.any(
38
+ Interface::Location, Interface::LocationLink
39
+ )],
38
40
  node_context: NodeContext,
39
41
  index: RubyIndexer::Index,
40
42
  dispatcher: Prism::Dispatcher,
@@ -0,0 +1,113 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ module RubyLsp
5
+ module Rails
6
+ class IndexingEnhancement
7
+ extend T::Sig
8
+ include RubyIndexer::Enhancement
9
+
10
+ sig do
11
+ override.params(
12
+ index: RubyIndexer::Index,
13
+ owner: T.nilable(RubyIndexer::Entry::Namespace),
14
+ node: Prism::CallNode,
15
+ file_path: String,
16
+ ).void
17
+ end
18
+ def on_call_node(index, owner, node, file_path)
19
+ return unless owner
20
+
21
+ name = node.name
22
+
23
+ case name
24
+ when :extend
25
+ handle_concern_extend(index, owner, node)
26
+ when :has_one, :has_many, :belongs_to, :has_and_belongs_to_many
27
+ handle_association(index, owner, node, file_path)
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ sig do
34
+ params(
35
+ index: RubyIndexer::Index,
36
+ owner: RubyIndexer::Entry::Namespace,
37
+ node: Prism::CallNode,
38
+ file_path: String,
39
+ ).void
40
+ end
41
+ def handle_association(index, owner, node, file_path)
42
+ arguments = node.arguments&.arguments
43
+ return unless arguments
44
+
45
+ name_arg = arguments.first
46
+
47
+ name = case name_arg
48
+ when Prism::StringNode
49
+ name_arg.content
50
+ when Prism::SymbolNode
51
+ name_arg.value
52
+ end
53
+
54
+ return unless name
55
+
56
+ # Reader
57
+ index.add(RubyIndexer::Entry::Method.new(
58
+ name,
59
+ file_path,
60
+ name_arg.location,
61
+ name_arg.location,
62
+ [],
63
+ [RubyIndexer::Entry::Signature.new([])],
64
+ RubyIndexer::Entry::Visibility::PUBLIC,
65
+ owner,
66
+ ))
67
+
68
+ # Writer
69
+ index.add(RubyIndexer::Entry::Method.new(
70
+ "#{name}=",
71
+ file_path,
72
+ name_arg.location,
73
+ name_arg.location,
74
+ [],
75
+ [RubyIndexer::Entry::Signature.new([RubyIndexer::Entry::RequiredParameter.new(name: name.to_sym)])],
76
+ RubyIndexer::Entry::Visibility::PUBLIC,
77
+ owner,
78
+ ))
79
+ end
80
+
81
+ sig do
82
+ params(
83
+ index: RubyIndexer::Index,
84
+ owner: RubyIndexer::Entry::Namespace,
85
+ node: Prism::CallNode,
86
+ ).void
87
+ end
88
+ def handle_concern_extend(index, owner, node)
89
+ arguments = node.arguments&.arguments
90
+ return unless arguments
91
+
92
+ arguments.each do |node|
93
+ next unless node.is_a?(Prism::ConstantReadNode) || node.is_a?(Prism::ConstantPathNode)
94
+
95
+ module_name = node.full_name
96
+ next unless module_name == "ActiveSupport::Concern"
97
+
98
+ index.register_included_hook(owner.name) do |index, base|
99
+ class_methods_name = "#{owner.name}::ClassMethods"
100
+
101
+ if index.indexed?(class_methods_name)
102
+ singleton = index.existing_or_new_singleton_class(base.name)
103
+ singleton.mixin_operations << RubyIndexer::Entry::Include.new(class_methods_name)
104
+ end
105
+ end
106
+ rescue Prism::ConstantPathNode::DynamicPartsInConstantPathError,
107
+ Prism::ConstantPathNode::MissingNodesInConstantPathError
108
+ # Do nothing
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -41,6 +41,7 @@ module RubyLsp
41
41
 
42
42
  sig { void }
43
43
  def initialize
44
+ @mutex = T.let(Mutex.new, Mutex)
44
45
  # Spring needs a Process session ID. It uses this ID to "attach" itself to the parent process, so that when the
45
46
  # parent ends, the spring process ends as well. If this is not set, Spring will throw an error while trying to
46
47
  # set its own session ID
@@ -84,9 +85,7 @@ module RubyLsp
84
85
  if @wait_thread.alive?
85
86
  $stderr.puts("Ruby LSP Rails is force killing the server")
86
87
  sleep(0.5) # give the server a bit of time if we already issued a shutdown notification
87
-
88
- # Windows does not support the `TERM` signal, so we're forced to use `KILL` here
89
- Process.kill(T.must(Signal.list["KILL"]), @wait_thread.pid)
88
+ force_kill
90
89
  end
91
90
  end
92
91
  end
@@ -149,6 +148,9 @@ module RubyLsp
149
148
  send_message("shutdown")
150
149
  sleep(0.5) # give the server a bit of time to shutdown
151
150
  [@stdin, @stdout, @stderr].each(&:close)
151
+ rescue IOError
152
+ # The server connection may have died
153
+ force_kill
152
154
  end
153
155
 
154
156
  sig { returns(T::Boolean) }
@@ -169,28 +171,35 @@ module RubyLsp
169
171
  read_response
170
172
  end
171
173
 
172
- sig { params(request: String, params: T.nilable(T::Hash[Symbol, T.untyped])).void }
174
+ sig { overridable.params(request: String, params: T.nilable(T::Hash[Symbol, T.untyped])).void }
173
175
  def send_message(request, params = nil)
174
176
  message = { method: request }
175
177
  message[:params] = params if params
176
178
  json = message.to_json
177
179
 
178
- @stdin.write("Content-Length: #{json.length}\r\n\r\n", json)
180
+ @mutex.synchronize do
181
+ @stdin.write("Content-Length: #{json.length}\r\n\r\n", json)
182
+ end
179
183
  rescue Errno::EPIPE
180
184
  # The server connection died
181
185
  end
182
186
 
183
- alias_method :send_notification, :send_message
187
+ # Notifications are like messages, but one-way, with no response sent back.
188
+ sig { params(request: String, params: T.nilable(T::Hash[Symbol, T.untyped])).void }
189
+ def send_notification(request, params = nil) = send_message(request, params)
184
190
 
185
- sig { returns(T.nilable(T::Hash[Symbol, T.untyped])) }
191
+ sig { overridable.returns(T.nilable(T::Hash[Symbol, T.untyped])) }
186
192
  def read_response
187
- headers = @stdout.gets("\r\n\r\n")
188
- raise IncompleteMessageError unless headers
193
+ raw_response = @mutex.synchronize do
194
+ headers = @stdout.gets("\r\n\r\n")
195
+ raise IncompleteMessageError unless headers
189
196
 
190
- content_length = headers[/Content-Length: (\d+)/i, 1].to_i
191
- raise EmptyMessageError if content_length.zero?
197
+ content_length = headers[/Content-Length: (\d+)/i, 1].to_i
198
+ raise EmptyMessageError if content_length.zero?
199
+
200
+ @stdout.read(content_length)
201
+ end
192
202
 
193
- raw_response = @stdout.read(content_length)
194
203
  response = JSON.parse(T.must(raw_response), symbolize_names: true)
195
204
 
196
205
  if response[:error]
@@ -203,6 +212,12 @@ module RubyLsp
203
212
  # The server connection died
204
213
  nil
205
214
  end
215
+
216
+ sig { void }
217
+ def force_kill
218
+ # Windows does not support the `TERM` signal, so we're forced to use `KILL` here
219
+ Process.kill(T.must(Signal.list["KILL"]), @wait_thread.pid)
220
+ end
206
221
  end
207
222
 
208
223
  class NullClient < RunnerClient
@@ -3,6 +3,6 @@
3
3
 
4
4
  module RubyLsp
5
5
  module Rails
6
- VERSION = "0.3.11"
6
+ VERSION = "0.3.13"
7
7
  end
8
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-lsp-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.11
4
+ version: 0.3.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shopify
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-07-19 00:00:00.000000000 Z
11
+ date: 2024-08-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-lsp
@@ -16,7 +16,7 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.17.2
19
+ version: 0.17.12
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
22
  version: 0.18.0
@@ -26,7 +26,7 @@ dependencies:
26
26
  requirements:
27
27
  - - ">="
28
28
  - !ruby/object:Gem::Version
29
- version: 0.17.2
29
+ version: 0.17.12
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: 0.18.0
@@ -46,6 +46,7 @@ files:
46
46
  - lib/ruby_lsp/ruby_lsp_rails/definition.rb
47
47
  - lib/ruby_lsp/ruby_lsp_rails/document_symbol.rb
48
48
  - lib/ruby_lsp/ruby_lsp_rails/hover.rb
49
+ - lib/ruby_lsp/ruby_lsp_rails/indexing_enhancement.rb
49
50
  - lib/ruby_lsp/ruby_lsp_rails/runner_client.rb
50
51
  - lib/ruby_lsp/ruby_lsp_rails/server.rb
51
52
  - lib/ruby_lsp/ruby_lsp_rails/support/active_support_test_case_helper.rb
@@ -79,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
79
80
  - !ruby/object:Gem::Version
80
81
  version: '0'
81
82
  requirements: []
82
- rubygems_version: 3.5.15
83
+ rubygems_version: 3.5.17
83
84
  signing_key:
84
85
  specification_version: 4
85
86
  summary: A Ruby LSP addon for Rails