languages: Fix local path of JSON and YAML schemas (#44794)
Closes #30938 Release Notes: - Fixed: Unable to load relative path JSON schema for YAML validation (#30938) This patch follows the vscode LSP client logic, see [`jsonClient.ts`](https://github.com/microsoft/vscode/blob/cee904f80cc6d15f22c850482789e06b1f536e72/extensions/json-language-features/client/src/jsonClient.ts#L768-L770). The `url` of the JSON schemas settings and the YAML schemas settings should be resolved to an absolute path in the LSP client when it is submitted to the server. --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
1 parent
8a3badeb90
commit
fa1e392a90
6 files changed
+74
-8
No files matched your search
@@ -379,7 +379,7 @@ pub trait LspAdapterDelegate: Send + Sync {
|
||||
fn http_client(&self) -> Arc<dyn HttpClient>;
|
||||
fn worktree_id(&self) -> WorktreeId;
|
||||
fn worktree_root_path(&self) -> &Path;
|
||||
fn resolve_executable_path(&self, path: PathBuf) -> PathBuf;
|
||||
fn resolve_relative_path(&self, path: PathBuf) -> PathBuf;
|
||||
fn update_status(&self, language: LanguageServerName, status: BinaryStatus);
|
||||
fn registered_lsp_adapters(&self) -> Vec<Arc<dyn LspAdapter>>;
|
||||
async fn language_server_download_dir(&self, name: &LanguageServerName) -> Option<Arc<Path>>;
|
||||
|
||||
@@ -296,7 +296,7 @@ impl LspAdapter for JsonLspAdapter {
|
||||
});
|
||||
let project_options = cx.update(|cx| {
|
||||
language_server_settings(delegate.as_ref(), &self.name(), cx)
|
||||
.and_then(|s| s.settings.clone())
|
||||
.and_then(|s| worktree_root(delegate, s.settings.clone()))
|
||||
});
|
||||
|
||||
if let Some(override_options) = project_options {
|
||||
@@ -320,6 +320,40 @@ impl LspAdapter for JsonLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
fn worktree_root(delegate: &Arc<dyn LspAdapterDelegate>, settings: Option<Value>) -> Option<Value> {
|
||||
let Some(Value::Object(mut settings_map)) = settings else {
|
||||
return settings;
|
||||
};
|
||||
|
||||
let Some(Value::Object(json_config)) = settings_map.get_mut("json") else {
|
||||
return Some(Value::Object(settings_map));
|
||||
};
|
||||
|
||||
let Some(Value::Array(schemas)) = json_config.get_mut("schemas") else {
|
||||
return Some(Value::Object(settings_map));
|
||||
};
|
||||
|
||||
for schema in schemas.iter_mut() {
|
||||
let Value::Object(schema_map) = schema else {
|
||||
continue;
|
||||
};
|
||||
let Some(Value::String(url)) = schema_map.get_mut("url") else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if !url.starts_with(".") && !url.starts_with("~") {
|
||||
continue;
|
||||
}
|
||||
|
||||
*url = delegate
|
||||
.resolve_relative_path(url.clone().into())
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
}
|
||||
|
||||
Some(Value::Object(settings_map))
|
||||
}
|
||||
|
||||
async fn get_cached_server_binary(
|
||||
container_dir: PathBuf,
|
||||
node: &NodeRuntime,
|
||||
|
||||
@@ -156,7 +156,7 @@ impl LspAdapter for YamlLspAdapter {
|
||||
|
||||
let project_options = cx.update(|cx| {
|
||||
language_server_settings(delegate.as_ref(), &Self::SERVER_NAME, cx)
|
||||
.and_then(|s| s.settings.clone())
|
||||
.and_then(|s| worktree_root(delegate, s.settings.clone()))
|
||||
});
|
||||
if let Some(override_options) = project_options {
|
||||
merge_json_value_into(override_options, &mut options);
|
||||
@@ -165,6 +165,38 @@ impl LspAdapter for YamlLspAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
fn worktree_root(delegate: &Arc<dyn LspAdapterDelegate>, settings: Option<Value>) -> Option<Value> {
|
||||
let Some(Value::Object(mut settings_map)) = settings else {
|
||||
return settings;
|
||||
};
|
||||
|
||||
let Some(Value::Object(yaml_config)) = settings_map.get_mut("yaml") else {
|
||||
return Some(Value::Object(settings_map));
|
||||
};
|
||||
|
||||
let Some(Value::Object(schemas)) = yaml_config.remove("schemas") else {
|
||||
return Some(Value::Object(settings_map));
|
||||
};
|
||||
|
||||
let schemas = schemas
|
||||
.into_iter()
|
||||
.map(|(url, v)| {
|
||||
if !url.starts_with(".") && !url.starts_with("~") {
|
||||
(url, v)
|
||||
} else {
|
||||
let resolved_url = delegate
|
||||
.resolve_relative_path(url.into())
|
||||
.to_string_lossy()
|
||||
.into_owned();
|
||||
(resolved_url, v)
|
||||
}
|
||||
})
|
||||
.collect::<serde_json::Map<String, Value>>();
|
||||
|
||||
yaml_config.insert("schemas".into(), Value::Object(schemas));
|
||||
Some(Value::Object(settings_map))
|
||||
}
|
||||
|
||||
async fn get_cached_server_binary(
|
||||
container_dir: PathBuf,
|
||||
node: &NodeRuntime,
|
||||
|
||||
@@ -265,7 +265,7 @@ impl DapStore {
|
||||
DapBinary::Default => None,
|
||||
DapBinary::Custom(binary) => {
|
||||
let path = PathBuf::from(binary);
|
||||
Some(worktree.read(cx).resolve_executable_path(path))
|
||||
Some(worktree.read(cx).resolve_relative_path(path))
|
||||
}
|
||||
});
|
||||
let user_args = dap_settings.and_then(|s| s.args.clone());
|
||||
|
||||
@@ -713,7 +713,7 @@ impl LocalLspStore {
|
||||
env.extend(settings.env.unwrap_or_default());
|
||||
|
||||
Ok(LanguageServerBinary {
|
||||
path: delegate.resolve_executable_path(path),
|
||||
path: delegate.resolve_relative_path(path),
|
||||
env: Some(env),
|
||||
arguments: settings
|
||||
.arguments
|
||||
@@ -14069,8 +14069,8 @@ impl LspAdapterDelegate for LocalLspAdapterDelegate {
|
||||
self.worktree.abs_path().as_ref()
|
||||
}
|
||||
|
||||
fn resolve_executable_path(&self, path: PathBuf) -> PathBuf {
|
||||
self.worktree.resolve_executable_path(path)
|
||||
fn resolve_relative_path(&self, path: PathBuf) -> PathBuf {
|
||||
self.worktree.resolve_relative_path(path)
|
||||
}
|
||||
|
||||
async fn shell_env(&self) -> HashMap<String, String> {
|
||||
|
||||
@@ -2495,7 +2495,7 @@ impl Snapshot {
|
||||
///
|
||||
/// Relative paths that do not exist in the worktree may
|
||||
/// still be found using the `PATH` environment variable.
|
||||
pub fn resolve_executable_path(&self, path: PathBuf) -> PathBuf {
|
||||
pub fn resolve_relative_path(&self, path: PathBuf) -> PathBuf {
|
||||
if let Some(path_str) = path.to_str() {
|
||||
if let Some(remaining_path) = path_str.strip_prefix("~/") {
|
||||
return home_dir().join(remaining_path);
|
||||
|
||||
Reference in new issue
Block a user