Cargo.lock 🔗
@@ -9292,6 +9292,7 @@ dependencies = [
"futures 0.3.31",
"gpui",
"http_client",
+ "itertools 0.14.0",
"language",
"log",
"lsp",
Alexander and Piotr Osiewicz created
Related to #35090
Release Notes:
- javascript: Fixed name escaping in dynamic jest/vitest task names
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Cargo.lock | 1
crates/languages/Cargo.toml | 1
crates/languages/src/typescript.rs | 46 ++++++++++++++++++++++++++++---
3 files changed, 43 insertions(+), 5 deletions(-)
@@ -9292,6 +9292,7 @@ dependencies = [
"futures 0.3.31",
"gpui",
"http_client",
+ "itertools 0.14.0",
"language",
"log",
"lsp",
@@ -45,6 +45,7 @@ dap.workspace = true
futures.workspace = true
gpui.workspace = true
http_client.workspace = true
+itertools.workspace = true
language.workspace = true
log.workspace = true
lsp.workspace = true
@@ -5,6 +5,7 @@ use collections::HashMap;
use futures::future::join_all;
use gpui::{App, AppContext, AsyncApp, Task};
use http_client::github::{AssetKind, GitHubLspBinaryVersion, build_asset_url};
+use itertools::Itertools as _;
use language::{
ContextLocation, ContextProvider, File, LanguageName, LanguageToolchainStore, LspAdapter,
LspAdapterDelegate, LspInstaller, Toolchain,
@@ -18,7 +19,7 @@ use std::{
borrow::Cow,
ffi::OsString,
path::{Path, PathBuf},
- sync::Arc,
+ sync::{Arc, LazyLock},
};
use task::{TaskTemplate, TaskTemplates, VariableName};
use util::merge_json_value_into;
@@ -511,9 +512,9 @@ fn eslint_server_binary_arguments(server_path: &Path) -> Vec<OsString> {
}
fn replace_test_name_parameters(test_name: &str) -> String {
- let pattern = regex::Regex::new(r"(%|\$)[0-9a-zA-Z]+").unwrap();
-
- regex::escape(&pattern.replace_all(test_name, "(.+?)"))
+ static PATTERN: LazyLock<regex::Regex> =
+ LazyLock::new(|| regex::Regex::new(r"(\$([A-Za-z0-9_\.]+|[\#])|%[psdifjo#\$%])").unwrap());
+ PATTERN.split(test_name).map(regex::escape).join("(.+?)")
}
pub struct TypeScriptLspAdapter {
@@ -1015,7 +1016,9 @@ mod tests {
use unindent::Unindent;
use util::path;
- use crate::typescript::{PackageJsonData, TypeScriptContextProvider};
+ use crate::typescript::{
+ PackageJsonData, TypeScriptContextProvider, replace_test_name_parameters,
+ };
#[gpui::test]
async fn test_outline(cx: &mut TestAppContext) {
@@ -1227,4 +1230,37 @@ mod tests {
]
);
}
+ #[test]
+ fn test_escaping_name() {
+ let cases = [
+ ("plain test name", "plain test name"),
+ ("test name with $param_name", "test name with (.+?)"),
+ ("test name with $nested.param.name", "test name with (.+?)"),
+ ("test name with $#", "test name with (.+?)"),
+ ("test name with $##", "test name with (.+?)\\#"),
+ ("test name with %p", "test name with (.+?)"),
+ ("test name with %s", "test name with (.+?)"),
+ ("test name with %d", "test name with (.+?)"),
+ ("test name with %i", "test name with (.+?)"),
+ ("test name with %f", "test name with (.+?)"),
+ ("test name with %j", "test name with (.+?)"),
+ ("test name with %o", "test name with (.+?)"),
+ ("test name with %#", "test name with (.+?)"),
+ ("test name with %$", "test name with (.+?)"),
+ ("test name with %%", "test name with (.+?)"),
+ ("test name with %q", "test name with %q"),
+ (
+ "test name with regex chars .*+?^${}()|[]\\",
+ "test name with regex chars \\.\\*\\+\\?\\^\\$\\{\\}\\(\\)\\|\\[\\]\\\\",
+ ),
+ (
+ "test name with multiple $params and %pretty and %b and (.+?)",
+ "test name with multiple (.+?) and (.+?)retty and %b and \\(\\.\\+\\?\\)",
+ ),
+ ];
+
+ for (input, expected) in cases {
+ assert_eq!(replace_test_name_parameters(input), expected);
+ }
+ }
}