lsp: Add schema support for LSP settings field (#48332)
This extends the LSP settings schema system to also provide autocomplete
for the `settings` field (used for `workspace/configuration` responses),
in addition to the existing `initialization_options` support (#).
Changes:
- Add `settings_schema` method to `LspAdapter` trait and
`CachedLspAdapter`
- Update schema URL paths to be more explicit:
- `lsp/{adapter}/initialization_options` for init options schema
- `lsp/{adapter}/settings` for settings schema
- Add schema resolution logic for the new settings path
- Update tests to verify both schema references
Release Notes:
- Added autocomplete support for the `settings` field in LSP
configuration, complementing the existing `initialization_options`
autocomplete.
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
4b2dcf1c68
commit
70f302cffa
3 files changed
+97
-12
No files matched your search
@@ -209,7 +209,7 @@ async fn resolve_dynamic_schema(
|
||||
|
||||
let schema = match schema_name {
|
||||
"settings" if rest.is_some_and(|r| r.starts_with("lsp/")) => {
|
||||
let lsp_name = rest
|
||||
let lsp_path = rest
|
||||
.and_then(|r| {
|
||||
r.strip_prefix(
|
||||
LSP_SETTINGS_SCHEMA_URL_PREFIX
|
||||
@@ -220,6 +220,26 @@ async fn resolve_dynamic_schema(
|
||||
})
|
||||
.context("Invalid LSP schema path")?;
|
||||
|
||||
// Parse the schema type from the path:
|
||||
// - "rust-analyzer/initialization_options" → initialization_options_schema
|
||||
// - "rust-analyzer/settings" → settings_schema
|
||||
enum LspSchemaKind {
|
||||
InitializationOptions,
|
||||
Settings,
|
||||
}
|
||||
let (lsp_name, schema_kind) = if let Some(adapter_name) =
|
||||
lsp_path.strip_suffix("/initialization_options")
|
||||
{
|
||||
(adapter_name, LspSchemaKind::InitializationOptions)
|
||||
} else if let Some(adapter_name) = lsp_path.strip_suffix("/settings") {
|
||||
(adapter_name, LspSchemaKind::Settings)
|
||||
} else {
|
||||
anyhow::bail!(
|
||||
"Invalid LSP schema path: expected '{{adapter}}/initialization_options' or '{{adapter}}/settings', got '{}'",
|
||||
lsp_path
|
||||
);
|
||||
};
|
||||
|
||||
let adapter = languages
|
||||
.all_lsp_adapters()
|
||||
.into_iter()
|
||||
@@ -246,15 +266,19 @@ async fn resolve_dynamic_schema(
|
||||
"either LSP store is not in local mode or no worktree is available"
|
||||
))?;
|
||||
|
||||
adapter
|
||||
.initialization_options_schema(&delegate, cx)
|
||||
.await
|
||||
.unwrap_or_else(|| {
|
||||
serde_json::json!({
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
})
|
||||
let schema = match schema_kind {
|
||||
LspSchemaKind::InitializationOptions => {
|
||||
adapter.initialization_options_schema(&delegate, cx).await
|
||||
}
|
||||
LspSchemaKind::Settings => adapter.settings_schema(&delegate, cx).await,
|
||||
};
|
||||
|
||||
schema.unwrap_or_else(|| {
|
||||
serde_json::json!({
|
||||
"type": "object",
|
||||
"additionalProperties": true
|
||||
})
|
||||
})
|
||||
}
|
||||
"settings" => {
|
||||
let lsp_adapter_names = languages
|
||||
|
||||
@@ -354,6 +354,17 @@ impl CachedLspAdapter {
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn settings_schema(
|
||||
&self,
|
||||
delegate: &Arc<dyn LspAdapterDelegate>,
|
||||
cx: &mut AsyncApp,
|
||||
) -> Option<serde_json::Value> {
|
||||
self.adapter
|
||||
.clone()
|
||||
.settings_schema(delegate, self.cached_binary.clone().lock_owned().await, cx)
|
||||
.await
|
||||
}
|
||||
|
||||
pub fn process_prompt_response(&self, context: &PromptResponseContext, cx: &mut AsyncApp) {
|
||||
self.adapter.process_prompt_response(context, cx)
|
||||
}
|
||||
@@ -493,6 +504,18 @@ pub trait LspAdapter: 'static + Send + Sync + DynLspInstaller {
|
||||
None
|
||||
}
|
||||
|
||||
/// Returns the JSON schema of the settings for the language server.
|
||||
/// This corresponds to the `settings` field in `LspSettings`, which is used
|
||||
/// to respond to `workspace/configuration` requests from the language server.
|
||||
async fn settings_schema(
|
||||
self: Arc<Self>,
|
||||
_delegate: &Arc<dyn LspAdapterDelegate>,
|
||||
_cached_binary: OwnedMutexGuard<Option<(bool, LanguageServerBinary)>>,
|
||||
_cx: &mut AsyncApp,
|
||||
) -> Option<serde_json::Value> {
|
||||
None
|
||||
}
|
||||
|
||||
async fn workspace_configuration(
|
||||
self: Arc<Self>,
|
||||
_: &Arc<dyn LspAdapterDelegate>,
|
||||
|
||||
@@ -1077,7 +1077,13 @@ impl SettingsStore {
|
||||
properties_object.insert(
|
||||
"initialization_options".to_string(),
|
||||
serde_json::json!({
|
||||
"$ref": format!("{LSP_SETTINGS_SCHEMA_URL_PREFIX}{adapter_name}")
|
||||
"$ref": format!("{LSP_SETTINGS_SCHEMA_URL_PREFIX}{adapter_name}/initialization_options")
|
||||
}),
|
||||
);
|
||||
properties_object.insert(
|
||||
"settings".to_string(),
|
||||
serde_json::json!({
|
||||
"$ref": format!("{LSP_SETTINGS_SCHEMA_URL_PREFIX}{adapter_name}/settings")
|
||||
}),
|
||||
);
|
||||
}
|
||||
@@ -2397,7 +2403,23 @@ mod tests {
|
||||
.as_str()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(init_options_ref, "zed://schemas/settings/lsp/rust-analyzer");
|
||||
assert_eq!(
|
||||
init_options_ref,
|
||||
"zed://schemas/settings/lsp/rust-analyzer/initialization_options"
|
||||
);
|
||||
|
||||
let settings_ref = properties
|
||||
.get("rust-analyzer")
|
||||
.unwrap()
|
||||
.pointer("/properties/settings/$ref")
|
||||
.expect("settings should have a $ref")
|
||||
.as_str()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
settings_ref,
|
||||
"zed://schemas/settings/lsp/rust-analyzer/settings"
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
@@ -2432,7 +2454,23 @@ mod tests {
|
||||
.as_str()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(init_options_ref, "zed://schemas/settings/lsp/rust-analyzer");
|
||||
assert_eq!(
|
||||
init_options_ref,
|
||||
"zed://schemas/settings/lsp/rust-analyzer/initialization_options"
|
||||
);
|
||||
|
||||
let settings_ref = properties
|
||||
.get("rust-analyzer")
|
||||
.unwrap()
|
||||
.pointer("/properties/settings/$ref")
|
||||
.expect("settings should have a $ref")
|
||||
.as_str()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
settings_ref,
|
||||
"zed://schemas/settings/lsp/rust-analyzer/settings"
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
|
||||
Reference in new issue
Block a user