fix: implement LSP initialization and configuration handlers#83
fix: implement LSP initialization and configuration handlers#83pmig wants to merge 1 commit intonathansbradshaw:mainfrom
Conversation
Add language_server_initialization_options and language_server_workspace_configuration trait methods to properly respond to LSP initialize and workspace/configuration requests. Without these, the Angular Language Server's workspace/configuration requests fail with deserialization errors, and user-configured LSP settings are not forwarded to the server. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR adds missing Zed extension hooks so the Angular Language Server can receive user-provided LSP initialization options and successfully retrieve per-workspace configuration via workspace/configuration, addressing failures reported in #69 and #77.
Changes:
- Implement
language_server_initialization_optionsto forward userlsp.angular.initialization_optionsto the server. - Implement
language_server_workspace_configurationto return userlsp.angular.settingsin response to serverworkspace/configurationrequests.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let settings = LspSettings::for_worktree(Self::LANGUAGE_SERVER_ID, worktree) | ||
| .ok() | ||
| .and_then(|settings| settings.settings) | ||
| .unwrap_or_else(|| serde_json::json!({})); | ||
| Ok(Some(settings)) |
There was a problem hiding this comment.
LspSettings::for_worktree(...).ok() discards any error and silently falls back to {}. If settings parsing fails, returning {} may hide the underlying issue; consider propagating the error or logging it before falling back.
| _language_server_id: &zed::LanguageServerId, | ||
| worktree: &zed::Worktree, | ||
| ) -> Result<Option<serde_json::Value>> { | ||
| let initialization_options = LspSettings::for_worktree(Self::LANGUAGE_SERVER_ID, worktree) | ||
| .ok() | ||
| .and_then(|settings| settings.initialization_options) | ||
| .unwrap_or_else(|| serde_json::json!({})); | ||
| Ok(Some(initialization_options)) |
There was a problem hiding this comment.
This ignores the language_server_id argument and hard-codes Self::LANGUAGE_SERVER_ID when reading per-worktree LSP settings. Using the provided language_server_id keeps this method correct if the server id ever differs (and is consistent with read_user_settings).
| let initialization_options = LspSettings::for_worktree(Self::LANGUAGE_SERVER_ID, worktree) | ||
| .ok() | ||
| .and_then(|settings| settings.initialization_options) | ||
| .unwrap_or_else(|| serde_json::json!({})); | ||
| Ok(Some(initialization_options)) |
There was a problem hiding this comment.
LspSettings::for_worktree(...).ok() discards any error (e.g., malformed user settings) and silently falls back to {}. Consider propagating the error (using ?) or at least emitting a log/warning so configuration problems don’t become hard-to-diagnose runtime behavior.
| _language_server_id: &zed::LanguageServerId, | ||
| worktree: &zed::Worktree, | ||
| ) -> Result<Option<serde_json::Value>> { | ||
| let initialization_options = LspSettings::for_worktree(Self::LANGUAGE_SERVER_ID, worktree) | ||
| .ok() | ||
| .and_then(|settings| settings.initialization_options) | ||
| .unwrap_or_else(|| serde_json::json!({})); | ||
| Ok(Some(initialization_options)) | ||
| } | ||
|
|
||
| fn language_server_workspace_configuration( | ||
| &mut self, | ||
| _language_server_id: &zed::LanguageServerId, | ||
| worktree: &zed::Worktree, | ||
| ) -> Result<Option<serde_json::Value>> { | ||
| let settings = LspSettings::for_worktree(Self::LANGUAGE_SERVER_ID, worktree) | ||
| .ok() | ||
| .and_then(|settings| settings.settings) | ||
| .unwrap_or_else(|| serde_json::json!({})); |
There was a problem hiding this comment.
This ignores the language_server_id argument and hard-codes Self::LANGUAGE_SERVER_ID when reading per-worktree LSP settings. Using the provided language_server_id avoids accidental mismatches and keeps the implementation consistent with other trait methods that accept a server id.
| _language_server_id: &zed::LanguageServerId, | |
| worktree: &zed::Worktree, | |
| ) -> Result<Option<serde_json::Value>> { | |
| let initialization_options = LspSettings::for_worktree(Self::LANGUAGE_SERVER_ID, worktree) | |
| .ok() | |
| .and_then(|settings| settings.initialization_options) | |
| .unwrap_or_else(|| serde_json::json!({})); | |
| Ok(Some(initialization_options)) | |
| } | |
| fn language_server_workspace_configuration( | |
| &mut self, | |
| _language_server_id: &zed::LanguageServerId, | |
| worktree: &zed::Worktree, | |
| ) -> Result<Option<serde_json::Value>> { | |
| let settings = LspSettings::for_worktree(Self::LANGUAGE_SERVER_ID, worktree) | |
| .ok() | |
| .and_then(|settings| settings.settings) | |
| .unwrap_or_else(|| serde_json::json!({})); | |
| language_server_id: &zed::LanguageServerId, | |
| worktree: &zed::Worktree, | |
| ) -> Result<Option<serde_json::Value>> { | |
| let initialization_options = | |
| LspSettings::for_worktree(language_server_id, worktree) | |
| .ok() | |
| .and_then(|settings| settings.initialization_options) | |
| .unwrap_or_else(|| serde_json::json!({})); | |
| Ok(Some(initialization_options)) | |
| } | |
| fn language_server_workspace_configuration( | |
| &mut self, | |
| language_server_id: &zed::LanguageServerId, | |
| worktree: &zed::Worktree, | |
| ) -> Result<Option<serde_json::Value>> { | |
| let settings = | |
| LspSettings::for_worktree(language_server_id, worktree) | |
| .ok() | |
| .and_then(|settings| settings.settings) | |
| .unwrap_or_else(|| serde_json::json!({})); |
|
Do you have example Zed settings so this can be tested/validated? |
This actually a series a fixes to make that extension work again. You can try out the extension locally over at https://github.com/pmig/zed-angular. Although most of the code was written by claude, I (@pmig) manually reviewed and tested it.
Summary
language_server_initialization_optionstrait method to forward user-configured LSP init options to the Angular Language Serverlanguage_server_workspace_configurationtrait method to respond toworkspace/configurationrequests from the serverworkspace/configurationrequests fail withError("relative URL without a base"), and user-configured LSP settings (via Zed'slspsettings) are not forwarded to the serverFollows the same pattern used by the Vue extension.
Relates to #69, #77