diff --git a/backend/parsers/windmill-parser-bash/src/lib.rs b/backend/parsers/windmill-parser-bash/src/lib.rs index 9b62ad3b0c..39f1d2667b 100644 --- a/backend/parsers/windmill-parser-bash/src/lib.rs +++ b/backend/parsers/windmill-parser-bash/src/lib.rs @@ -9,7 +9,7 @@ use regex_lite::Regex; use serde_json::json; -use std::collections::HashMap; +use std::{collections::HashMap, str::FromStr}; use windmill_parser::{Arg, MainArgSignature, Typ}; pub fn parse_bash_sig(code: &str) -> anyhow::Result { @@ -84,36 +84,94 @@ fn parse_bash_file(code: &str) -> anyhow::Result>> { Ok(Some(args)) } +enum ParserState { + Normal, + InSingleQuote, + InDoubleQuote, +} +fn split_pwsh_args(code: &str) -> Vec<&str> { + let mut chars = code.char_indices().peekable(); + let mut state = ParserState::Normal; + let mut splits = vec![]; + let mut last_idx = 0; + while let Some((idx, char)) = chars.next() { + match (&state, char) { + (ParserState::Normal, '\'') => { + state = ParserState::InSingleQuote; + } + (ParserState::Normal, '"') => { + state = ParserState::InDoubleQuote; + } + (ParserState::InSingleQuote, '\'') => { + state = ParserState::Normal; + } + (ParserState::InDoubleQuote, '"') => { + state = ParserState::Normal; + } + (ParserState::Normal, ',') => { + splits.push(&code[last_idx..idx]); + last_idx = idx + 1; // skip the comma + } + _ => {} + } + } + + if last_idx < code.len() { + splits.push(&code[last_idx..]); + } + + splits +} + fn parse_powershell_file(code: &str) -> anyhow::Result>> { let param_wrapper = RE_POWERSHELL_PARAM.captures(code); let mut args = vec![]; if let Some(param_wrapper) = param_wrapper { let param_wrapper = param_wrapper.get(1).unwrap().as_str(); - for cap in RE_POWERSHELL_ARGS.captures_iter(param_wrapper) { - let typ = cap - .get(1) - .map(|x| x.as_str().to_string()) - .unwrap_or("string".to_string()); - let name = cap.get(2).unwrap().as_str().to_string(); - let default = cap - .get(3) - .or(cap.get(4)) - .map(|x| json!(x.as_str().to_string())); + let params = split_pwsh_args(param_wrapper); + for param in params { + if let Some(cap) = RE_POWERSHELL_ARGS.captures(param) { + let typ = cap.get(1).map(|x| x.as_str().to_string()); + let name = cap.get(2).unwrap().as_str().to_string(); - args.push(Arg { - name: name, - typ: match typ.as_str() { - "string" => Typ::Str(None), - "int" | "long" => Typ::Int, - "decimal" | "double" | "single" => Typ::Float, - "datetime" | "DateTime" => Typ::Datetime, - _ => Typ::Str(None), - }, - default: default.clone(), - otyp: None, - has_default: default.is_some(), - oidx: None, - }); + let mut parsed_typ = if let Some(typ) = typ { + match typ.as_str() { + "string" => Some(Typ::Str(None)), + "int" | "long" => Some(Typ::Int), + "decimal" | "double" | "single" => Some(Typ::Float), + "datetime" | "DateTime" => Some(Typ::Datetime), + _ => None, + } + } else { + None + }; + + let default = if let Some(x) = cap.get(3) { + Some(json!(x.as_str().to_string())) + } else if let Some(x) = cap.get(4) { + if parsed_typ.is_none() { + if x.as_str().parse::().is_ok() { + parsed_typ = Some(Typ::Int); + } else if x.as_str().parse::().is_ok() { + parsed_typ = Some(Typ::Float); + } + } + serde_json::Number::from_str(x.as_str()) + .ok() + .map(serde_json::Value::Number) + } else { + None + }; + + args.push(Arg { + name: name, + typ: parsed_typ.unwrap_or(Typ::Str(None)), + default: default.clone(), + otyp: None, + has_default: default.is_some(), + oidx: None, + }); + } } } Ok(Some(args)) @@ -192,4 +250,77 @@ non_required="${5:-}" Ok(()) } + + #[test] + fn test_parse_powershell_sig() -> anyhow::Result<()> { + let code = r#"param($Msg, [string]$Msg2, $Dflt = "default value, with comma", [int]$Nb = 3 , $Nb2 = 5.0, $Nb3 = 5, $Wahoo = $env:WAHOO)"#; + assert_eq!( + parse_powershell_sig(code)?, + MainArgSignature { + star_args: false, + star_kwargs: false, + args: vec![ + Arg { + otyp: None, + name: "Msg".to_string(), + typ: Typ::Str(None), + default: None, + has_default: false, + oidx: None + }, + Arg { + otyp: None, + name: "Msg2".to_string(), + typ: Typ::Str(None), + default: None, + has_default: false, + oidx: None + }, + Arg { + otyp: None, + name: "Dflt".to_string(), + typ: Typ::Str(None), + default: Some(json!("default value, with comma")), + has_default: true, + oidx: None + }, + Arg { + otyp: None, + name: "Nb".to_string(), + typ: Typ::Int, + default: Some(json!(3)), + has_default: true, + oidx: None + }, + Arg { + otyp: None, + name: "Nb2".to_string(), + typ: Typ::Float, + default: Some(json!(5.0)), + has_default: true, + oidx: None + }, + Arg { + otyp: None, + name: "Nb3".to_string(), + typ: Typ::Int, + default: Some(json!(5)), + has_default: true, + oidx: None + }, + Arg { + otyp: None, + name: "Wahoo".to_string(), + typ: Typ::Str(None), + default: None, + has_default: false, + oidx: None + } + ], + no_main_func: None, + has_preprocessor: None + } + ); + Ok(()) + } } diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b7291147d8..baa4085a52 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -72,7 +72,7 @@ "windmill-parser-wasm-go": "^1.429.0", "windmill-parser-wasm-php": "^1.429.0", "windmill-parser-wasm-py": "^1.429.0", - "windmill-parser-wasm-regex": "^1.429.0", + "windmill-parser-wasm-regex": "^1.435.2", "windmill-parser-wasm-rust": "^1.429.0", "windmill-parser-wasm-ts": "^1.429.0", "windmill-parser-wasm-yaml": "^1.429.0", @@ -13660,9 +13660,9 @@ "integrity": "sha512-cqc+tblQVHVrc8wNA4esVYD1Dv59XQJ4mHXFFPa8Lx5UjXv7FO/0VQxyQuRyXaP/V6J6DDy0oeN107eFNLxrBg==" }, "node_modules/windmill-parser-wasm-regex": { - "version": "1.429.0", - "resolved": "https://registry.npmjs.org/windmill-parser-wasm-regex/-/windmill-parser-wasm-regex-1.429.0.tgz", - "integrity": "sha512-rjgrgSYjEBU2+RB6ffFR+nmvEJdiqVKYiwugzHQE+VgVTYMJ0jLBE370n5dBjDj5KPsF+Sfmj6DIUK69uu9wSA==" + "version": "1.435.2", + "resolved": "https://registry.npmjs.org/windmill-parser-wasm-regex/-/windmill-parser-wasm-regex-1.435.2.tgz", + "integrity": "sha512-kQShKPNjXok8jV7b7llfvKhypHfqePwiKgTHm8MlzBt4BZC87xrQ7TH0eS9h7OSK9Q98H9fIiUr2AbN8zTCraA==" }, "node_modules/windmill-parser-wasm-rust": { "version": "1.429.0", diff --git a/frontend/package.json b/frontend/package.json index 981382670e..8348523b89 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -128,8 +128,8 @@ "ol": "^7.4.0", "openai": "^4.57.2", "p-limit": "^6.1.0", - "pdfjs-dist": "4.8.69", "panzoom": "^9.4.3", + "pdfjs-dist": "4.8.69", "quill": "^1.3.7", "rfc4648": "^1.5.3", "svelte-carousel": "^1.0.25", @@ -145,7 +145,7 @@ "windmill-parser-wasm-go": "^1.429.0", "windmill-parser-wasm-php": "^1.429.0", "windmill-parser-wasm-py": "^1.429.0", - "windmill-parser-wasm-regex": "^1.429.0", + "windmill-parser-wasm-regex": "^1.435.2", "windmill-parser-wasm-rust": "^1.429.0", "windmill-parser-wasm-ts": "^1.429.0", "windmill-parser-wasm-yaml": "^1.429.0",