Skip to content

Commit

Permalink
Use window log messages instead of printing to stderr
Browse files Browse the repository at this point in the history
  • Loading branch information
vinistock committed Aug 8, 2024
1 parent f6bade4 commit fa84c70
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 53 deletions.
13 changes: 9 additions & 4 deletions lib/ruby_lsp/addon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,18 @@ def inherited(child_class)
super
end

# Discovers and loads all addons. Returns the list of activated addons
sig { params(global_state: GlobalState, outgoing_queue: Thread::Queue).returns(T::Array[Addon]) }
# Discovers and loads all addons. Returns a list of errors when trying to require addons
sig do
params(global_state: GlobalState, outgoing_queue: Thread::Queue).returns(T::Array[StandardError])
end
def load_addons(global_state, outgoing_queue)
# Require all addons entry points, which should be placed under
# `some_gem/lib/ruby_lsp/your_gem_name/addon.rb`
Gem.find_files("ruby_lsp/**/addon.rb").each do |addon|
errors = Gem.find_files("ruby_lsp/**/addon.rb").filter_map do |addon|
require File.expand_path(addon)
nil
rescue => e
$stderr.puts(e.full_message)
e
end

# Instantiate all discovered addon classes
Expand All @@ -71,6 +74,8 @@ def load_addons(global_state, outgoing_queue)
rescue => e
addon.add_error(e)
end

errors
end

# Intended for use by tests for addons
Expand Down
9 changes: 7 additions & 2 deletions lib/ruby_lsp/base_server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ def start
when "initialize", "initialized", "textDocument/didOpen", "textDocument/didClose", "textDocument/didChange"
process_message(message)
when "shutdown"
$stderr.puts("Shutting down Ruby LSP...")
send_log_message("Shutting down Ruby LSP...")

shutdown

Expand All @@ -76,7 +76,7 @@ def start
when "exit"
@mutex.synchronize do
status = @incoming_queue.closed? ? 0 : 1
$stderr.puts("Shutdown complete with status #{status}")
send_log_message("Shutdown complete with status #{status}")
exit(status)
end
else
Expand Down Expand Up @@ -145,5 +145,10 @@ def send_message(message)
def send_empty_response(id)
send_message(Result.new(id: id, response: nil))
end

sig { params(message: String, type: Integer).void }
def send_log_message(message, type: Constant::MessageType::LOG)
send_message(Notification.window_log_message(message, type: Constant::MessageType::LOG))
end
end
end
46 changes: 33 additions & 13 deletions lib/ruby_lsp/global_state.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,48 @@ def active_linters
@linters.filter_map { |name| @supported_formatters[name] }
end

sig { params(options: T::Hash[Symbol, T.untyped]).void }
# Applies the options provided by the editor and returns an array of notifications to send back to the client
sig { params(options: T::Hash[Symbol, T.untyped]).returns(T::Array[Notification]) }
def apply_options(options)
notifications = []
direct_dependencies = gather_direct_dependencies
all_dependencies = gather_direct_and_indirect_dependencies
workspace_uri = options.dig(:workspaceFolders, 0, :uri)
@workspace_uri = URI(workspace_uri) if workspace_uri

specified_formatter = options.dig(:initializationOptions, :formatter)
@formatter = specified_formatter if specified_formatter
@formatter = detect_formatter(direct_dependencies, all_dependencies) if @formatter == "auto"

if specified_formatter
@formatter = specified_formatter

if specified_formatter != "auto"
notifications << Notification.window_log_message("Using formatter specified by user: #{@formatter}")
end
end

if @formatter == "auto"
@formatter = detect_formatter(direct_dependencies, all_dependencies)
notifications << Notification.window_log_message("Auto detected formatter: #{@formatter}")
end

specified_linters = options.dig(:initializationOptions, :linters)
@linters = specified_linters || detect_linters(direct_dependencies, all_dependencies)

notifications << if specified_linters
Notification.window_log_message("Using linters specified by user: #{@linters.join(", ")}")
else
Notification.window_log_message("Auto detected linters: #{@linters.join(", ")}")
end

@test_library = detect_test_library(direct_dependencies)
notifications << Notification.window_log_message("Detected test library: #{@test_library}")

@has_type_checker = detect_typechecker(direct_dependencies)
if @has_type_checker
notifications << Notification.window_log_message(
"Ruby LSP detected this is a Sorbet project and will defer to the Sorbet LSP for some functionality",
)
end

encodings = options.dig(:capabilities, :general, :positionEncodings)
@encoding = if !encodings || encodings.empty?
Expand All @@ -91,6 +118,8 @@ def apply_options(options)

@experimental_features = options.dig(:initializationOptions, :experimentalFeaturesEnabled) || false
@type_inferrer.experimental_features = @experimental_features

notifications
end

sig { returns(String) }
Expand Down Expand Up @@ -163,16 +192,7 @@ def detect_test_library(dependencies)
def detect_typechecker(dependencies)
return false if ENV["RUBY_LSP_BYPASS_TYPECHECKER"]

# We can't read the env from within `Bundle.with_original_env` so we need to set it here.
ruby_lsp_env_is_test = (ENV["RUBY_LSP_ENV"] == "test")
Bundler.with_original_env do
sorbet_static_detected = dependencies.any?(/^sorbet-static/)
# Don't show message while running tests, since it's noisy
if sorbet_static_detected && !ruby_lsp_env_is_test
$stderr.puts("Ruby LSP detected this is a Sorbet project so will defer to Sorbet LSP for some functionality")
end
sorbet_static_detected
end
dependencies.any?(/^sorbet-static/)
rescue Bundler::GemfileNotFound
false
end
Expand Down
27 changes: 21 additions & 6 deletions lib/ruby_lsp/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ def initialize(test_mode: false)
def process_message(message)
case message[:method]
when "initialize"
$stderr.puts("Initializing Ruby LSP v#{VERSION}...")
send_log_message("Initializing Ruby LSP v#{VERSION}...")
run_initialize(message)
when "initialized"
$stderr.puts("Finished initializing Ruby LSP!") unless @test_mode
send_log_message("Finished initializing Ruby LSP!") unless @test_mode
run_initialized
when "textDocument/didOpen"
text_document_did_open(message)
Expand Down Expand Up @@ -121,12 +121,20 @@ def process_message(message)
end
end

$stderr.puts("Error processing #{message[:method]}: #{e.full_message}")
send_log_message("Error processing #{message[:method]}: #{e.full_message}", type: Constant::MessageType::ERROR)
end

sig { void }
def load_addons
Addon.load_addons(@global_state, @outgoing_queue)
errors = Addon.load_addons(@global_state, @outgoing_queue)

if errors.any?
send_log_message(
"Error loading addons:\n\n#{errors.map(&:full_message).join("\n\n")}",
type: Constant::MessageType::WARNING,
)
end

errored_addons = Addon.addons.select(&:error?)

if errored_addons.any?
Expand All @@ -140,7 +148,12 @@ def load_addons
),
)

$stderr.puts(errored_addons.map(&:errors_details).join("\n\n")) unless @test_mode
unless @test_mode
send_log_message(
errored_addons.map(&:errors_details).join("\n\n"),
type: Constant::MessageType::WARNING,
)
end
end
end

Expand All @@ -149,7 +162,7 @@ def load_addons
sig { params(message: T::Hash[Symbol, T.untyped]).void }
def run_initialize(message)
options = message[:params]
@global_state.apply_options(options)
global_state_notifications = @global_state.apply_options(options)

client_name = options.dig(:clientInfo, :name)
@store.client_name = client_name if client_name
Expand Down Expand Up @@ -258,6 +271,8 @@ def run_initialize(message)
process_indexing_configuration(options.dig(:initializationOptions, :indexing))

begin_progress("indexing-progress", "Ruby LSP: indexing files")

global_state_notifications.each { |notification| send_message(notification) }
end

sig { void }
Expand Down
12 changes: 12 additions & 0 deletions lib/ruby_lsp/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def to_hash; end
class Notification < Message
class << self
extend T::Sig

sig { params(message: String).returns(Notification) }
def window_show_error(message)
new(
Expand All @@ -63,6 +64,14 @@ def window_show_error(message)
),
)
end

sig { params(message: String, type: Integer).returns(Notification) }
def window_log_message(message, type: Constant::MessageType::LOG)
new(
method: "window/logMessage",
params: Interface::LogMessageParams.new(type: type, message: message),
)
end
end

extend T::Sig
Expand Down Expand Up @@ -122,6 +131,9 @@ class Result
sig { returns(T.untyped) }
attr_reader :response

sig { returns(Integer) }
attr_reader :id

sig { params(id: Integer, response: T.untyped).void }
def initialize(id:, response:)
@id = id
Expand Down
Loading

0 comments on commit fa84c70

Please sign in to comment.