Parse human readable module name for Rust tasks (#10337)

Part of https://github.com/zed-industries/zed/issues/10132 extracted out
of a bigger PR that refactors tasks and shows labels that look more like
commands (ergo needs better readable package names)

Release Notes:

- N/A
This commit is contained in:
Kirill Bulatov 2024-04-09 23:18:09 +02:00 committed by GitHub
parent 7dfc7184b1
commit 0331fdebd3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -10,7 +10,13 @@ use project::project_settings::ProjectSettings;
use regex::Regex;
use settings::Settings;
use smol::fs::{self, File};
use std::{any::Any, borrow::Cow, env::consts, path::PathBuf, sync::Arc};
use std::{
any::Any,
borrow::Cow,
env::consts,
path::{Path, PathBuf},
sync::Arc,
};
use task::{
static_source::{Definition, TaskDefinitions},
TaskVariables, VariableName,
@ -333,25 +339,17 @@ impl ContextProvider for RustContextProvider {
) -> Result<TaskVariables> {
let mut context = SymbolContextProvider.build_context(location.clone(), cx)?;
if let Some(path) = location.buffer.read(cx).file().and_then(|file| {
let local_file = file.as_local()?.abs_path(cx);
local_file.parent().map(PathBuf::from)
}) {
let Some(pkgid) = std::process::Command::new("cargo")
.current_dir(path)
.arg("pkgid")
.output()
.log_err()
else {
return Ok(context);
};
let package_name = String::from_utf8(pkgid.stdout)
.map(|name| name.trim().to_owned())
.ok();
if let Some(package_name) = package_name {
context.insert(RUST_PACKAGE_TASK_VARIABLE.clone(), package_name);
}
let local_abs_path = location
.buffer
.read(cx)
.file()
.and_then(|file| Some(file.as_local()?.abs_path(cx)));
if let Some(package_name) = local_abs_path
.as_deref()
.and_then(|local_abs_path| local_abs_path.parent())
.and_then(human_readable_package_name)
{
context.insert(RUST_PACKAGE_TASK_VARIABLE.clone(), package_name);
}
Ok(context)
@ -408,6 +406,38 @@ impl ContextProvider for RustContextProvider {
}
}
fn human_readable_package_name(package_directory: &Path) -> Option<String> {
fn split_off_suffix(input: &str, suffix_start: char) -> &str {
match input.rsplit_once(suffix_start) {
Some((without_suffix, _)) => without_suffix,
None => input,
}
}
let pkgid = String::from_utf8(
std::process::Command::new("cargo")
.current_dir(package_directory)
.arg("pkgid")
.output()
.log_err()?
.stdout,
)
.ok()?;
// For providing local `cargo check -p $pkgid` task, we do not need most of the information we have returned.
// Output example in the root of Zed project:
// ```bash
// cargo pkgid zed
// path+file:///absolute/path/to/project/zed/crates/zed#0.131.0
// ```
// Extrarct the package name from the output according to the spec:
// https://doc.rust-lang.org/cargo/reference/pkgid-spec.html#specification-grammar
let mut package_name = pkgid.trim();
package_name = split_off_suffix(package_name, '#');
package_name = split_off_suffix(package_name, '?');
let (_, package_name) = package_name.rsplit_once('/')?;
Some(package_name.to_string())
}
async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
maybe!(async {
let mut last = None;