-
Notifications
You must be signed in to change notification settings - Fork 223
Implement workspace/didChangeConfiguration and workspace/configuration
#3813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -80,6 +80,9 @@ def process_message(message) | |
| type_hierarchy_supertypes(message) | ||
| when "typeHierarchy/subtypes" | ||
| type_hierarchy_subtypes(message) | ||
| when "workspace/didChangeConfiguration" | ||
| send_log_message("Re-applying Ruby LSP configuration after workspace configuration change") | ||
| workspace_configuration_did_change(message) | ||
| when "workspace/didChangeWatchedFiles" | ||
| workspace_did_change_watched_files(message) | ||
| when "workspace/symbol" | ||
|
|
@@ -157,9 +160,16 @@ def process_message(message) | |
| # Process responses to requests that were sent to the client | ||
| #: (Hash[Symbol, untyped] message) -> void | ||
| def process_response(message) | ||
| case message.dig(:result, :method) | ||
| # Some replies have method in their payload, but some do not and we need to match | ||
| # the request by id to find what the method is. | ||
| method = (message[:result].is_a?(Hash) && message.dig(:result, :method)) || @sent_requests[message[:id]]&.to_hash&.fetch(:method) | ||
|
|
||
| case method | ||
| when "window/showMessageRequest" | ||
| window_show_message_request(message) | ||
| when "workspace/configuration" | ||
| send_log_message("Received workspace configuration from client: #{message}") | ||
| workspace_configuration_received(message) | ||
| end | ||
| end | ||
|
|
||
|
|
@@ -196,6 +206,21 @@ def load_addons(include_project_addons: true) | |
|
|
||
| private | ||
|
|
||
| #: (Hash[Symbol, untyped] message) -> void | ||
| def workspace_configuration_did_change(message) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My understanding based on the spec is that the parameters of Why do we need to make a request to the client? Could we use what we receive as parameters instead?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The way I understand the spec is that
I think it's a strategic decision for the maintaining team to choose which approach to support and I will be happy to adjust this PR to whatever you decide (push, pull or both). |
||
| # This assumes that the workspace configuration is under "rubyLsp" key, which seems | ||
| # to be the standard naming convention. | ||
| send_message(Request.workspace_configuration( | ||
| @current_request_id, section: "rubyLsp" | ||
| )) | ||
| end | ||
|
|
||
| def workspace_configuration_received(message) | ||
| options = { initializationOptions: message[:result]&.first } | ||
| messages_to_send = @global_state.apply_options(options) | ||
|
Comment on lines
+219
to
+220
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a hack to reuse Also, this just takes first hash from the reply's
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, this method is coupling information that we get during initialization (like the workspace folder) with other settings. It would indeed be nice to split into two methods:
Beyond just improving the design, invoking this twice may have weird consequences, like accidentally changing the negotiated encoding, so I don't think we can reuse it as is. For example, if the editor and server negotiated UTF-8 initially, invoking this method without passing the |
||
| messages_to_send.each { |notification| send_message(notification) } | ||
| end | ||
|
|
||
| #: (Hash[Symbol, untyped] message) -> void | ||
| def run_initialize(message) | ||
| options = message[:params] | ||
|
|
@@ -273,6 +298,9 @@ def run_initialize(message) | |
| rename_provider: rename_provider, | ||
| references_provider: !@global_state.has_type_checker, | ||
| document_range_formatting_provider: true, | ||
| workspace: { | ||
| configuration: true, | ||
| }, | ||
| experimental: { | ||
| addon_detection: true, | ||
| compose_bundle: true, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We already process one response for server->client requests here.
Are we able to reuse that and avoid changing the base server?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This implementation relies on the response having
methodinside the payload. In this case it does not, which is why I needed to match it to the request by it's ID to know what method it is. Here are relevant pieces from my session:Perhaps there's a better way to do the reply-to-request matching I did not find?