From 885c4edbeb50213e82ce1a09aca4f1ae7d2b4f5f Mon Sep 17 00:00:00 2001 From: Stan Lo Date: Tue, 9 Jan 2024 17:04:06 +0000 Subject: [PATCH] Decouple Listener from Request --- lib/ruby_lsp/check_docs.rb | 2 +- lib/ruby_lsp/listener.rb | 54 ++------------------------------------ 2 files changed, 3 insertions(+), 53 deletions(-) diff --git a/lib/ruby_lsp/check_docs.rb b/lib/ruby_lsp/check_docs.rb index d7b490921d..6cff3d50d5 100644 --- a/lib/ruby_lsp/check_docs.rb +++ b/lib/ruby_lsp/check_docs.rb @@ -53,7 +53,7 @@ def run_task # documented features = ObjectSpace.each_object(Class).select do |k| klass = T.unsafe(k) - klass < Requests::Request && klass != Listener && klass != ExtensibleListener + klass < Requests::Request end missing_docs = T.let(Hash.new { |h, k| h[k] = [] }, T::Hash[String, T::Array[String]]) diff --git a/lib/ruby_lsp/listener.rb b/lib/ruby_lsp/listener.rb index d77960eeb9..7b856456f9 100644 --- a/lib/ruby_lsp/listener.rb +++ b/lib/ruby_lsp/listener.rb @@ -4,7 +4,7 @@ module RubyLsp # Listener is an abstract class to be used by requests for listening to events emitted when visiting an AST using the # Prism::Dispatcher. - class Listener < Requests::Request + class Listener extend T::Sig extend T::Helpers extend T::Generic @@ -20,7 +20,7 @@ def initialize(dispatcher) @dispatcher = dispatcher end - sig { override.returns(ResponseType) } + sig { returns(ResponseType) } def response _response end @@ -30,54 +30,4 @@ def response sig { abstract.returns(ResponseType) } def _response; end end - - # ExtensibleListener is an abstract class to be used by requests that accept addons. - class ExtensibleListener < Listener - extend T::Sig - extend T::Generic - - ResponseType = type_member - - abstract! - - # When inheriting from ExtensibleListener, the `super` of constructor must be called **after** the subclass's own - # ivars have been initialized. This is because the constructor of ExtensibleListener calls - # `initialize_external_listener` which may depend on the subclass's ivars. - sig { params(dispatcher: Prism::Dispatcher).void } - def initialize(dispatcher) - super - @response_merged = T.let(false, T::Boolean) - @external_listeners = T.let( - Addon.addons.filter_map do |ext| - initialize_external_listener(ext) - end, - T::Array[RubyLsp::Listener[ResponseType]], - ) - end - - # Merge responses from all external listeners into the base listener's response. We do this to return a single - # response to the editor including the results of all addons - sig { void } - def merge_external_listeners_responses! - @external_listeners.each { |l| merge_response!(l) } - end - - sig { override.returns(ResponseType) } - def response - merge_external_listeners_responses! unless @response_merged - super - end - - sig do - abstract.params(addon: RubyLsp::Addon).returns(T.nilable(RubyLsp::Listener[ResponseType])) - end - def initialize_external_listener(addon); end - - # Does nothing by default. Requests that accept addons should override this method to define how to merge responses - # coming from external listeners - sig { abstract.params(other: Listener[T.untyped]).returns(T.self_type) } - def merge_response!(other) - end - end - private_constant(:ExtensibleListener) end