Skip to content

Commit

Permalink
Separate server_addon into new file
Browse files Browse the repository at this point in the history
  • Loading branch information
johansenja committed Oct 2, 2024
1 parent 51df5ac commit df12cec
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 45 deletions.
46 changes: 1 addition & 45 deletions lib/ruby_lsp/ruby_lsp_rails/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,57 +2,13 @@
# frozen_string_literal: true

require "json"
require_relative "server_addon"

# NOTE: We should avoid printing to stderr since it causes problems. We never read the standard error pipe from the
# client, so it will become full and eventually hang or crash. Instead, return a response with an `error` key.

module RubyLsp
module Rails
class ServerAddon
@server_addon_classes = []
@server_addons = {}

class << self
# We keep track of runtime server add-ons the same way we track other add-ons, by storing classes that inherit
# from the base one
def inherited(child)
@server_addon_classes << child
super
end

# Delegate `request` with `params` to the server add-on with the given `name`
def delegate(name, request, params)
@server_addons[name]&.execute(request, params)
end

# Instantiate all server addons and store them in a hash for easy access after we have discovered the classes
def finalize_registrations!(stdout)
until @server_addon_classes.empty?
addon = @server_addon_classes.shift.new(stdout)
@server_addons[addon.name] = addon
end
end
end

def initialize(stdout)
@stdout = stdout
end

# Write a response back. Can be used for sending notifications to the editor
def write_response(response)
json_response = response.to_json
@stdout.write("Content-Length: #{json_response.length}\r\n\r\n#{json_response}")
end

def name
raise NotImplementedError, "Not implemented!"
end

def execute(request, params)
raise NotImplementedError, "Not implemented!"
end
end

class Server
def initialize(stdout: $stdout, override_default_output_device: true)
# Grab references to the original pipes so that we can change the default output device further down
Expand Down
70 changes: 70 additions & 0 deletions lib/ruby_lsp/ruby_lsp_rails/server_addon.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# typed: strict
# frozen_string_literal: true

require "sorbet-runtime"

module RubyLsp
module Rails
class ServerAddon
extend T::Sig
extend T::Helpers

abstract!

@server_addon_classes = T.let([], T::Array[T.class_of(ServerAddon)])
@server_addons = T.let({}, T::Hash[String, ServerAddon])

module Types
Params = T.type_alias { T::Hash[T.untyped, T.untyped] }
Response = T.type_alias { T::Hash[Symbol, T.untyped] }
end

class << self
extend T::Sig

# We keep track of runtime server add-ons the same way we track other add-ons, by storing
# classes that inherit from the base one
sig { params(child: T::Class[T.anything]).void }
def inherited(child)
@server_addon_classes << T.cast(child, T.class_of(ServerAddon))
super
end

# Delegate `request` with `params` to the server add-on with the given `name`
sig { params(name: String, request: String, params: Types::Params).returns(T.nilable(Types::Response)) }
def delegate(name, request, params)
@server_addons[name]&.execute(request, params)
end

# Instantiate all server addons and store them in a hash for easy access after we have discovered the classes
sig { params(stdout: T.any(IO, StringIO)).void }
def finalize_registrations!(stdout)
until @server_addon_classes.empty?
addon = T.must(@server_addon_classes.shift).new(stdout)
@server_addons[addon.name] = addon
end
end
end

sig { params(stdout: T.any(IO, StringIO)).void }
def initialize(stdout)
@stdout = stdout
end

# Write a response back. Can be used for sending notifications to the editor
sig { params(response: Types::Response).void }
def write_response(response)
json_response = response.to_json
@stdout.write("Content-Length: #{json_response.length}\r\n\r\n#{json_response}")
end

sig { abstract.returns(String) }
def name
end

sig { abstract.params(request: String, params: Types::Params).returns(Types::Response) }
def execute(request, params)
end
end
end
end

0 comments on commit df12cec

Please sign in to comment.