diff --git a/crates/task/src/vscode_format.rs b/crates/task/src/vscode_format.rs index 9078a73fbb1d2bf747af4bee25c364f6c08862f6..15afd3c63aa9b8e6a1791659a452d80bfeb411ac 100644 --- a/crates/task/src/vscode_format.rs +++ b/crates/task/src/vscode_format.rs @@ -13,17 +13,46 @@ struct TaskOptions { env: HashMap, } -#[derive(Clone, Debug, Deserialize, PartialEq)] -#[serde(rename_all = "camelCase")] +#[derive(Clone, Debug, PartialEq)] struct VsCodeTaskDefinition { label: String, - #[serde(flatten)] command: Option, - #[serde(flatten)] other_attributes: HashMap, options: Option, } +impl<'de> serde::Deserialize<'de> for VsCodeTaskDefinition { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + #[derive(Deserialize)] + #[serde(rename_all = "camelCase")] + struct TaskHelper { + #[serde(default)] + label: Option, + #[serde(flatten)] + command: Option, + #[serde(flatten)] + other_attributes: HashMap, + options: Option, + } + + let helper = TaskHelper::deserialize(deserializer)?; + + let label = helper + .label + .unwrap_or_else(|| generate_label(&helper.command)); + + Ok(VsCodeTaskDefinition { + label, + command: helper.command, + other_attributes: helper.other_attributes, + options: helper.options, + }) + } +} + #[derive(Clone, Deserialize, PartialEq, Debug)] #[serde(tag = "type")] #[serde(rename_all = "camelCase")] @@ -41,6 +70,21 @@ enum Command { }, } +fn generate_label(command: &Option) -> String { + match command { + Some(Command::Npm { script }) => format!("npm: {}", script), + Some(Command::Gulp { task }) => format!("gulp: {}", task), + Some(Command::Shell { command, .. }) => { + if command.trim().is_empty() { + "shell".to_string() + } else { + command.clone() + } + } + None => "Untitled Task".to_string(), + } +} + impl VsCodeTaskDefinition { fn into_zed_format( self, @@ -128,7 +172,7 @@ mod tests { vscode_format::{Command, VsCodeTaskDefinition}, }; - use super::EnvVariableReplacer; + use super::{EnvVariableReplacer, generate_label}; fn compare_without_other_attributes(lhs: VsCodeTaskDefinition, rhs: VsCodeTaskDefinition) { assert_eq!( @@ -358,4 +402,62 @@ mod tests { let tasks: TaskTemplates = vscode_definitions.try_into().unwrap(); assert_eq!(tasks.0, expected); } + + #[test] + fn can_deserialize_tasks_without_labels() { + const TASKS_WITHOUT_LABELS: &str = include_str!("../test_data/tasks-without-labels.json"); + let vscode_definitions: VsCodeTaskFile = + serde_json_lenient::from_str(TASKS_WITHOUT_LABELS).unwrap(); + + assert_eq!(vscode_definitions.tasks.len(), 4); + assert_eq!(vscode_definitions.tasks[0].label, "npm: start"); + assert_eq!(vscode_definitions.tasks[1].label, "Explicit Label"); + assert_eq!(vscode_definitions.tasks[2].label, "gulp: build"); + assert_eq!(vscode_definitions.tasks[3].label, "echo hello"); + } + + #[test] + fn test_generate_label() { + assert_eq!( + generate_label(&Some(Command::Npm { + script: "start".to_string() + })), + "npm: start" + ); + assert_eq!( + generate_label(&Some(Command::Gulp { + task: "build".to_string() + })), + "gulp: build" + ); + assert_eq!( + generate_label(&Some(Command::Shell { + command: "echo hello".to_string(), + args: vec![] + })), + "echo hello" + ); + assert_eq!( + generate_label(&Some(Command::Shell { + command: "cargo build --release".to_string(), + args: vec![] + })), + "cargo build --release" + ); + assert_eq!( + generate_label(&Some(Command::Shell { + command: " ".to_string(), + args: vec![] + })), + "shell" + ); + assert_eq!( + generate_label(&Some(Command::Shell { + command: "".to_string(), + args: vec![] + })), + "shell" + ); + assert_eq!(generate_label(&None), "Untitled Task"); + } } diff --git a/crates/task/test_data/tasks-without-labels.json b/crates/task/test_data/tasks-without-labels.json new file mode 100644 index 0000000000000000000000000000000000000000..d4e504e597abd8aa76b33aea94d48017896b1c10 --- /dev/null +++ b/crates/task/test_data/tasks-without-labels.json @@ -0,0 +1,22 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "npm", + "script": "start" + }, + { + "label": "Explicit Label", + "type": "npm", + "script": "test" + }, + { + "type": "gulp", + "task": "build" + }, + { + "type": "shell", + "command": "echo hello" + } + ] +}