Skip to content

fix: implement LSP initialization and configuration handlers#83

Open
pmig wants to merge 1 commit intonathansbradshaw:mainfrom
pmig:fix/lsp-trait-methods
Open

fix: implement LSP initialization and configuration handlers#83
pmig wants to merge 1 commit intonathansbradshaw:mainfrom
pmig:fix/lsp-trait-methods

Conversation

@pmig
Copy link
Contributor

@pmig pmig commented Feb 25, 2026

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

  • Adds language_server_initialization_options trait method to forward user-configured LSP init options to the Angular Language Server
  • Adds language_server_workspace_configuration trait method to respond to workspace/configuration requests from the server
  • Without these, the Angular LS's workspace/configuration requests fail with Error("relative URL without a base"), and user-configured LSP settings (via Zed's lsp settings) are not forwarded to the server

Follows the same pattern used by the Vue extension.

Relates to #69, #77

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>
Copilot AI review requested due to automatic review settings February 25, 2026 13:18
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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_options to forward user lsp.angular.initialization_options to the server.
  • Implement language_server_workspace_configuration to return user lsp.angular.settings in response to server workspace/configuration requests.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +218 to +222
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))
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +203 to +210
_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))
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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).

Copilot uses AI. Check for mistakes.
Comment on lines +206 to +210
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))
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +203 to +221
_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!({}));
Copy link

Copilot AI Feb 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
_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!({}));

Copilot uses AI. Check for mistakes.
@notpeter
Copy link
Collaborator

Do you have example Zed settings so this can be tested/validated?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants